Arsylk/jadx-deflatten

GitHub: Arsylk/jadx-deflatten

jadx 插件,通过静态去虚拟化还原基于 hashCode-switch 调度器的控制流平坦化混淆,重建 Android 应用的原始控制流图。

Stars: 1 | Forks: 0

# jadx 控制流平坦化还原 (`deflatten`) 一个 [jadx](https://github.com/skylot/jadx) 插件,能够**还原控制流平坦化**,针对几种 Android 字符串/控制流混淆器(例如在野外发现的 Enigma 运行时助手)使用的 `while (true) switch (str.hashCode() ^ K)` 形式,重建该方法的原始控制流图。 平坦化将方法的真实控制流替换为调度器循环:一个 `String` *state* 变量通过 `state.hashCode()` 并与一系列常量进行折叠(folded),然后由一个庞大的 `switch` 将每个状态路由到相应的 case 块中,该块在执行少量工作后会分配*下一个*状态。由于每个状态字符串都是编译时常量,因此 case 块的执行序列是完全静态的,可以进行静态去虚拟化。该插件为每个状态计算 `hashCode(state) ^ K`,追踪 `state = …` 转换以重建真实的 CFG,并折叠该调度器,最终留下可供 jadx 正常结构化的普通控制流。 它**在构造上是安全可靠的**:只有当*每个*状态字符串都能解析为编译时常量,并路由到具体的(非默认) switch case 时,调度器才会被重写;并且在进行任何修改之前,整个计划都会经过验证——因此,无法识别的结构会干净地中止退出,方法保持原样。在无关的应用上启用它是安全的(它只会在非调度器代码上无操作)。 ## 安装 ``` # 推荐(当在 marketplace 上架时): jadx plugins --install deflatten # 从 GitHub release jar: jadx plugins --install-jar jadx-deflatten-.jar # 直接从此 repo: jadx plugins --install github:Arsylk:jadx-deflatten jadx plugins --list ``` 在 jadx-gui 中,该插件显示在 **Preferences → Plugins → Control-Flow Deflatten** 下。 ## 处理范围 - **线性调度器** —— 一系列以终止(`return`)case 结束的中继状态。 - **循环携带值** —— 累加器和对象句柄(例如跨状态构建的 `Pattern`/`StringBuilder`)会被贯穿(threaded)连接到每个状态所看到的具体值。 - **条件转换** —— `state = cond ? "X" : "Y"` 会变成具有两条直接边的真实 `if` 语句。 - **重合与循环** —— 两个状态推进到同一个第三个状态,或者从初始化器和回边都能到达的循环头状态,会通过在每个共享目标处插入合并 phi(针对每个循环携带变量),重建为真实的合并/循环。 - **嵌套调度器** —— 每轮定点(fixpoint)移除一个,因此内部调度器会在后续遍历中处理。 生产级混淆器生成的真实调度器结构(一种*双 phi* 调度器:包含一个头 phi 和一个带有“状态不变”默认自环的回边合并 phi)会被检测并拆解。 ## 工作原理 该插件在 block/SSA IR 上添加了两个 `JadxDecompilePass`: 1. **DeflattenUnlock**(`after BlockProcessor`,`before BlockFinisher`)在同时具有 `SWITCH` 和 `String.hashCode()` 调用的方法上设置 `AFlag.DISABLE_BLOCKS_LOCK`,以便它们的基本块图在重写期间保持可变状态(jadx 通常会将前驱/后继列表锁定为不可变集合)。普通方法保持默认锁定的 CFG,不受影响。 2. **Deflatten**(`after ReplaceNewArray`,`before RegionMakerVisitor`)检测调度器,静态评估每个状态的选择器(`SelectorEval`),重建状态图,并将每个转换边直接重新连接到该选择器路由到的 case 块——在重合/循环头处为循环携带变量插入合并 phi。随后,调度器头、选择器、`hashCode` 调用和常量链将变成死代码并被移除。 ## 设置 | 选项 | 默认值 | 描述 | |---|---|---| | `deflatten.enabled` | `true` | 该遍的主开关。 | | `deflatten.comments` | `true` | 向被重写的方法添加 `Control-flow deflattened: N dispatcher(s)` 信息注释。 | ## 构建 ``` # Standalone(此 repo): mv settings.gradle.kts.disabled settings.gradle.kts # only needed outside the jadx tree ./gradlew jar # -> build/libs/jadx-deflatten-.jar ./gradlew test # golden tests: fixtures are compiled + decompiled through jadx ``` 该插件针对 `io.github.skylot:jadx-core` 进行编译(由宿主 jadx 在运行时提供);它永远不会被打包进去。请保持 `build.gradle.kts` 中的 `version`、`DeflattenPlugin.VERSION` 以及发布标签同步。 ## 许可证 Apache License 2.0 — 参见 [LICENSE](LICENSE)。
标签:JS文件枚举, 后台面板检测, 域名枚举