EasyAntiCheat New Code obfuscation Muation-Optimization Section 1
之前 EasyAntiCheat 变异分析之搜集基本块 我们介绍了 如何搜集基本块 这样我们能够将所有被变异的代码片段抽取出来 然后使用正常的jcc指令将这些基本块连接起来尝试还原可读性 经过一番简单的操作 我们得到了如下图所示
现在我们把编译后的bin丢进IDA 随便挑选一个看看
如上图所示 可读性 基本=0 尤其是红框中标注的内容 很影响阅读.注:这里有一条死分支 后面再说.
那么怎么去除呢?
首先直接跳转的相关基本块 可以用之前定位他们的方式直接去除无意义指令 比如保存跳转寄存器的push 以及 跳到目标后的pop 指令 还有负责给定偏移的mov 指令
直接转移块:
push r15 mov r15,offset 两条
和
他的目标 pop r15 一条 可见 他们操作的目标寄存器都和负责转移的寄存器有关 这里使用 当时我们使用jcc_dispatcher确定的转移寄存器以防止出错
.deobf:0000000140720945 push r15 去除
.deobf:0000000140720947 mov r15, 0FFFFFFFFF11C4FCBh 去除
.deobf:0000000140720951 pop r15 去除
条件转移块:
.deobf:0000000140720983 push r15 去除
.deobf:0000000140720985 push r14 去除
.deobf:0000000140720987 mov r14, 0FFFFFFFFF0E52B1Bh 去除
.deobf:0000000140720991 mov r15, 0FFFFFFFFF1347274h 去除
.deobf:000000014072099B cmovz r15, r14 去除
.deobf:000000014072099F pop r14 去除
.deobf:000000014072097A loc_14072097A: ; CODE XREF: sub_140720945+62↓j
.deobf:000000014072097A pop r15 去除
条件转移块使用cmovz确定两条指令设计的寄存器 查找写入他们的 以及负责保存他们的 且在去除CMOV指令本身 以及去掉 他的两个分支用于弹出跳转寄存器的指令
…..
….
…
..
.
经过一番简单的操作 我们根据之前方法轻松的确定了要剔除的这些和转移有关的指令 结果如下图:
嗯…勉强可读 还有一些 无意义指令 但是 就不能依赖这种基本块跳转的方式去搞了.
关于死分支 上图中有一个简单的例子:
观察经过清理的代码 好像第一个条件转移指令不对劲 如图所示 str reg 执行后 reg=0x40, and reg,5 执行后 reg=0 所以 ZF标志位 置1 那么 该条件转移指令实际是一个jmp指令 因为它的另一条路径永远不会执行 所以这一个块 和条件转移相关的所有指令都可以剔除掉,然后将块的属性改为直接跳转.
图:我是图……
PS:应该有更好的办法去优化它们 比如翻译为LLVM IR 用LLVM 的优化通道 优化它们 我在探索这种办法 嗯……
本节 未完待续