Skip to content

iFlyCode H() 字符串混淆体系与解码方案完整分析

版本: 3.4.2-222 | 分析日期: 2026-05-11 | 文档编号: 64

1. 概述

本文档详细分析 iFlyCode 的 H() 字符串混淆体系,包括混淆原理、定义点分布、调用者统计、解码算法和三种破解方案。

2. H() 混淆原理

2.1 算法流程

调用者类.方法()


H(混淆字符串)

    ├── 1. LinkageError.getStackTrace()
    │   └── 获取调用栈 → 提取调用者类名和方法名

    ├── 2. 生成 XOR 密钥
    │   └── callerClassName + methodName → 字符串 → XOR 密钥

    ├── 3. XOR 解码
    │   └── 混淆字符串 ⊕ 密钥 → 明文字符串

    └── 4. 返回明文

2.2 关键技术细节

  1. LinkageError 而非 Thread: 使用 LinkageError.getStackTrace() 而非 Thread.currentThread().getStackTrace(),可能因为 LinkageError 是 Error 而非 Exception,在某些安全检查中不会被拦截。

  2. 调用者信息提取: 从栈帧中提取调用者类的简单名称(不含包名)和方法名,拼接为 XOR 密钥。

  3. XOR 编码: 对混淆字符串的每个字符与密钥字符进行 XOR 运算,密钥循环使用。

2.3 伪代码

java
public static String H(String obfuscated) {
    // 1. 获取调用者信息
    StackTraceElement[] stack = new LinkageError().getStackTrace();
    String callerClassName = stack[1].getClassName();  // 简单名称
    String callerMethodName = stack[1].getMethodName();
    
    // 2. 生成 XOR 密钥
    String key = callerClassName + callerMethodName;
    
    // 3. XOR 解码
    char[] result = new char[obfuscated.length()];
    for (int i = 0; i < obfuscated.length(); i++) &#123;
        result[i] = (char)(obfuscated.charAt(i) ^ key.charAt(i % key.length()));
    &#125;
    
    return new String(result);
&#125;

3. H() 定义点分布

3.1 主要定义点

字符串数领域
AICodeStringUtil526核心混淆 + 代码文本处理util
GenericUtils312通用混淆util
NewFileUtils108文件操作混淆util
PropertyUtils64属性读取混淆util
FontKt字体/样式ui
HandleCacheUtil38缓存util
MethodGeneratorConfig方法生成(推断)
GeneratorConfig生成器(推断)
IndentLineUtil34缩进util
LanguageFileExtensionDetails语言映射language

3.2 次要定义点 (17+)

分布在 action、inline、template、agent 等包中,每个定义点服务于特定领域的混淆需求。

4. 调用者统计

4.1 按目标类分组

目标类调用次数说明
AICodeStringUtil~150核心混淆,最多调用
GenericUtils~100通用混淆
NewFileUtils~30文件操作
PropertyUtils~15属性读取
其他 23+ 类~50各自领域

4.2 按调用者包分组

H() 调用数说明
agent~80Agent 通信相关
inline~40内联聊天
template~60模板生成
action~30用户操作
listener~25事件监听
service~20服务层
util~15工具类
其他~30其余包

4.3 Top 20 调用者

调用者H() 调用数说明
SessionController~25内联聊天会话
ChatServiceImpl~20聊天服务
PluginWebsocketClient~15WebSocket 客户端
AutoCodeGenerateListener~15自动补全
JavaTestBuilderImpl~15Java 单测生成
TemplateRequestService~12AI 辅助单测
OpenInlineChatAction~10打开内联聊天
InlineChatCommandServiceImpl~10内联聊天命令
CodeCheckServiceImpl~8代码检查
GitReviewServiceImpl~8Git 评审
RequestTipServiceImpl~6补全请求
AICodeUnloadPluginListener~5插件卸载
OpenTelemetryService~5APM 服务
PluginUpdater~5插件更新
StatusBarPopup~4状态栏
CommitHandlerFactory$o~4Git 提交
CodeEditorListener~3编辑器监听
GitBranchChangeListener~3Git 分支
BatchUTGeneratorAction~3批量单测
UnitTestAction~3单测 Action

5. 解码方案

5.1 方案 A: Java Agent Hook (推荐)

原理: 在运行时 Hook H() 方法,拦截输入和输出。

实现步骤:

  1. 编写 Java Agent,使用 Instrumentation API
  2. 在 H() 方法入口插入 System.out.println("H: " + obfuscated + " -> " + result)
  3. 启动 IntelliJ IDEA,加载 iFlyCode 插件
  4. 触发所有功能,收集解码结果

优点: 100% 准确,无需理解 XOR 算法细节 缺点: 需要 Java 运行时和 IntelliJ IDEA

代码框架:

java
public class HDeobfuscatorAgent &#123;
    public static void premain(String args, Instrumentation inst) &#123;
        new AgentBuilder.Default()
            .type(ElementMatchers.named("com.aicode.util.AICodeStringUtil"))
            .transform((builder, typeDescription, classLoader, module) ->
                builder.method(ElementMatchers.named("H"))
                    .intercept(Advice.to(HInterceptor.class))
            ).installOn(inst);
    &#125;
    
    public static class HInterceptor &#123;
        @Advice.OnMethodExit
        public static void onExit(@Advice.Argument(0) String input,
                                   @Advice.Return String result) &#123;
            System.out.println("H_DECODED: " + input + " -> " + result);
        &#125;
    &#125;
&#125;

5.2 方案 B: 静态 Python 解码器

原理: 从 .class 文件提取调用者类名和方法名,计算 XOR 密钥,解码混淆字符串。

实现步骤:

  1. 解析每个 .class 文件的常量池
  2. 找到 H() 方法调用点
  3. 确定调用者类名和方法名
  4. 计算 XOR 密钥 = callerClassName + callerMethodName
  5. 对 H() 的参数字符串进行 XOR 解码

优点: 不需要 Java 运行时,纯静态分析 缺点: 需要精确定位 H() 调用点和参数,字节码分析复杂

代码框架:

python
def decode_h_string(obfuscated, caller_class, caller_method):
    key = caller_class + caller_method
    result = []
    for i, c in enumerate(obfuscated):
        result.append(chr(ord(c) ^ ord(key[i % len(key)])))
    return ''.join(result)

5.3 方案 C: Frida Hook (移动端方案适配)

原理: 使用 Frida 动态插桩框架 Hook JVM 方法。

实现步骤:

  1. 安装 Frida 和 JVM 插件
  2. 编写 Frida 脚本 Hook H() 方法
  3. 运行 IntelliJ IDEA 触发功能
  4. 收集解码结果

优点: 动态分析,无需修改插件 缺点: Frida JVM 支持有限

6. 混淆字符串内容推测

基于 H() 调用者的领域和上下文,推测混淆字符串的内容类别:

调用者领域推测内容示例
Agent 通信WebSocket URL、命令名"ws://localhost:6832"
内联聊天分类名称、提示文本"EXPLAIN"、"请选择操作"
模板生成模板路径、代码片段"templates/junit4.vm"
设置配置键名、默认值"autoTrigger"、"INTELLIGENT_MODE"
APMSpan 名称、属性名"code.complete.duration"
权限权限代码"inline_chat"、"code_optimization"
UI按钮文本、图标路径"Accept"、"icons/accept.svg"
GitGit 命令、分支名"git diff"、"main"
加密API 密钥、Token(敏感信息)

7. 安全性评估

维度评估说明
混淆强度中等XOR 可逆,密钥可推导
密钥来源可推导调用者类名+方法名可从 .class 文件提取
破解难度静态分析可完全还原
运行时 HookJava Agent 或 Frida 可轻松拦截
静态解码需要精确的字节码分析
防护效果主要防止简单的字符串搜索,不能防止逆向

8. 关键发现

  1. H() 是核心混淆机制: 27+ 定义点,312 调用类,~500-800 混淆字符串,覆盖所有关键功能。

  2. LinkageError 技巧: 使用 LinkageError.getStackTrace() 而非 Thread.currentThread().getStackTrace(),可能绕过某些安全检查。

  3. 密钥可推导: XOR 密钥由调用者类名+方法名组成,这些信息可从 .class 文件的常量池中提取。

  4. Java Agent 最优解: 方案 A(Java Agent Hook)是最可靠的解码方案,100% 准确,无需理解 XOR 算法细节。

  5. 混淆目的有限: H() 混淆的主要目的是防止简单的字符串搜索(如 grep "ws://localhost"),不能防止有意的逆向工程。

  6. 敏感信息保护不足: API 密钥、Token、URL 等敏感信息仅通过 H() 混淆保护,解码后完全暴露。

  7. AICodeStringUtil 双重职责: 既是 H() 混淆的核心实现(526 strings),也是代码文本处理(行分割、空白检测)的工具类。

  8. GenericUtils 复用栈追踪: 与 OpenTelemetryUtil 使用相同的 LinkageError.getStackTrace() 技巧获取调用者信息。

  9. Template 包最多 H() 调用: JavaTestBuilderImpl (956 strings) 和 TemplateRequestService (893 strings) 是 H() 调用最多的类,说明模板生成系统大量使用混淆字符串。

  10. 方案 B 可行但复杂: 静态 Python 解码器需要精确的字节码分析来定位 H() 调用点和参数,实现难度中等。

本项目仅供学习研究,逆向分析内容归原厂商所有。