-
-
[原创]LLVM Pass编写及去除 —— 控制流平坦化
-
-
[原创]LLVM Pass编写及去除 —— 控制流平坦化
ollvm更改了原始代码块的跳转关系,将代码分割为基本块,由分发块统一控制,如下图

基本块为由终结指令结尾的代码块,每个基本块都会跳转到返回块,返回块回到分发块进行下一次跳转
具体代码如下
利用swich case结构控制下一个跳转的基本快,但是这种方式写出来的case值会直接暴露在代码中,很容易找到跳转关系
我们可以尝试手动去除一下这种ollvm

在loc_4011DF这个基本块中,给存放case变量的指针赋值,然后回到返回块,此时0x5CAFE12C就是分发器要找的下一个case值

找到比较0x5CAFE12C的分发器,就可以顺藤摸瓜发现跳转的下一个块为loc_4011F2

也就可以据此恢复跳转关系去除混淆
知道原理之后就可以写出idc脚本批量操作
脚本从基本块入手,从pass编写脚本可知每个基本块的最后两条指令为给swValPtr赋值和跳转到返回块,且基本块必定只有一个跳转指令,可以根据这些特征轻松定位基本块并进行处理
效果如下
原始伪代码:
使用idc脚本去混淆后
可以成功去除
但是这样的ollvm混淆,case值直接暴露在汇编中,使用d810等工具就可以一把梭,为了增加混淆去除难度,可以对case值的生成进行魔改
如上,在处理基本块时,对case值的生成新增了异或运算,间接运算case值可以使d810失效

依旧手动去除一下
图中可以看到loc_4011F6的case值为0x772811A7,自身异或的值为0x15FBEF3,运算后得到0x7677AF54

得到后继块为loc_40120E
如果有两个后继块,图中条件为cmovb,相应应该更改为jb + jmp
编写idc脚本去除
因为异或运算需要自身case值,所以可以从分发块开始解析
去混淆效果如下
去混淆前
去除混淆后
idc脚本去除ollvm混淆的思路是通用的,但是文中代码只是根据我手里被混淆过的文件特征进行去除,如果想在不同的文件中使用,最好把一些常用代码封装成函数,根据不同的ollvm魔改方式进行去除
此题为魔改ollvm,以它为例,讲解如何分析及去除一个陌生的ollvm,并写出idc脚本一键处理

观察cfg,发现和之前学到的有些不同,只有入口块、分发块和基本块,缺少了返回块

每个基本块都是直接返回到主分发块,而且也没有将case值压入指针的操作,那么分发块是如何确定下一个跳转的基本块的呢
再来看主分发块
传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!