首页
社区
课程
招聘
[原创]LLVM Pass编写及去除 —— 控制流平坦化
发表于: 22小时前 742

[原创]LLVM Pass编写及去除 —— 控制流平坦化

22小时前
742

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值压入指针的操作,那么分发块是如何确定下一个跳转的基本块的呢

再来看主分发块


传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 4
支持
分享
最新回复 (1)
雪    币: 104
活跃值: (8232)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
tql
9小时前
0
游客
登录 | 注册 方可回帖
返回