Files

1.8 KiB
Raw Permalink Blame History

控制流平坦化与 Opcode 模式

这份文档用于处理控制流平坦化、opcode if 链、虚拟机解释器主分发器,以及测试位噪声分支。

适用场景

  • for (...; ![];) { switch (...) { ... } }
  • while (true) { switch (...) { ... } }
  • "3|1|2".split('|') 一类数组或顺序表驱动的平坦化
  • 大量 if (0x31 === opcode) ... else if ...
  • 虚拟机解释器里围绕同一个 opcode 变量做长链分发

控制流展平原则

  • 优先写定向 visitor,不要一开始追求通用大而全。
  • 先验证 init、test、update、body 结构是否稳定。
  • 只要结构不匹配,就直接跳过,不要强行展平。
  • 拼接 case 时同步清理仅用于跳转的赋值、无意义 break 和明显噪声语句。

if 链改写为 switch

仅在以下条件同时满足时改写:

  • 整条链都在判断同一个判别表达式。
  • 每个分支都拿这个表达式与字面量比较。
  • 分支数量足够长,改写后可读性明显提升。

测试位噪声与哨兵比较

某些样本会在测试条件里塞入噪声,例如:

cond && fn(...) !== {}
cond && fn(...) === {}

只在以下前提下清理:

  • 它位于 if、for.test 或 while.test 位置。
  • 右侧确实只是混淆器注入的空对象比较噪声。
  • 删除后不会影响左侧真实条件的副作用顺序。

虚拟机解释器建议

  • 第一轮只求看清主分发器、栈变量、opcode 读取器。
  • 清掉虚假分支后,再把 if 链改成 switch。
  • 第二轮再考虑简化 case 内的局部结构。

停止条件

  • 主 opcode 分发器已可读。
  • 关键 case 已经可以逐个分析。
  • 继续静态展开开始明显增加误改写风险。

到这里就可以转入人工分析或结合运行时证据继续逆向。