首页
社区
课程
招聘
[原创]Unicorn反ollvm控制流平坦化之bb
发表于: 2020-2-24 14:02 11408

[原创]Unicorn反ollvm控制流平坦化之bb

2020-2-24 14:02
11408

    感谢无名大佬提供的思路,使用了下unicorn,编写idapython脚本去掉控制流混淆,unicorn一个字,好使,推荐大家可以用用,

    1、https://github.com/obfuscator-llvm/obfuscator下载最新的ollvm分支编译,再build/bin下生成clang。

                 1)、 在llvm目录下创建build文件。

                 2)、 在build目录下行 cmake  -DCMAKE_BUILD_TYPE=Release-DLLVM_INCLUDE_TESTS=OFF ../

                 3)、 make -j4

                 4)、 build目录下会生成clang的可执行文件bin、lib目录

    2、将Lib\Transforms\Obfuscation\Flattening.cpp移植出来单独编译,方便测试,否则修改了源文件还得放到整个ollvm源码中编译,费时不方便测试。编译生成            libflatten.so

    


    3、编写一个简单的llvm-test.cpp,只有一个测试函数。

    


    4、使用clang分别进行编译,一个加载控制流混淆pass,一个不加载,在ida中进行对比下看看效果

    


    未加控制流混淆pass:

    除了入口块,还剩余4个真实块

    


    添加控制流混淆pass:

        可以看到添加了好多用来寻找真实块的无用块,统一从0xDB0块出发,找到真实块,最后统一从块0xDC0回到块0xDB0,跳转到入口块的指令都是有很明显的

    特征的,后边会提到

    


        以上是llvm生成的最终的机器指令控制流程图

        llvm 通过Function.viewCFG()提供生成的中间IR指令的控制流图

        在控制流混淆Pass的runOnFunction函数的前后调用f.viewCFG(),可以清晰的看到

        混淆前后中间IR指令控制流图对比


        对比下IR控制流图,

        混淆前:

    

        

        混淆后:

       


    看下源码, https://github.com/obfuscator-llvm/obfuscator Lib\Transforms\Obfuscation\Flattening.cpp中的flatten函数

    1、  第一个块              :添加 AllocaInst、StoreInst、BranchInst指令,alloca分配switchVar变量空间,store填充switchVar为随机值,bl跳转到loopEntry块

    2、  loopEntry块          :添加 LoadInst、SwitchInst指令,load获取switchVar变量地址,switch根据获取的switchVar值,查表跳转

    3、  loopEnd块            :添加 BranchInst指令,跳转到loopEntry块

    4、  真实块                  :如果是无条件分支指令,去掉终止指令br,添加StoreInst、BranchInst指令,根据真实块后继对应的switchNum用store更新    

                                            switchVar值,跳转到loopEnd块如果是条件分支指令,去掉终止指令br,添加SelectInst、StoreInst、BranchInst指令,根据SelectInst                                              指令选择的真实块后继对应的switchNum用store更新switchVar值,跳转到loopEnd块

    5、 switchDefault块    :添加 BranchInst指令,跳转到loopEnd块

    引用网上的一张图

    


    总结控制流混淆的原理:

        搭建一个switch代码框架,将真实块塞到框架case中,根据switchVar变量的值,通过switch指令寻找到真实的代码块,跟前边开启了混淆编译,中间生成

    IR 流程就能匹配起来了。

        控制流混淆生成的中间IR控制流图和源码是完全能对应起来的,都是通过switch指令,随机值串联起来的,但是和生成的汇编控制流图还不太一样,反汇编生      成的控制流图是通过多个块中的比较指令,最终找到真实块


    Hook app输出日志函数pBA425510043BB3BE41A7E30AA69623BE

    反混淆之前控制流图:

    


    F5伪代码:外层一个大的while循环,内部通过switch case的方式寻找到真实块

    


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 3
支持
分享
最新回复 (8)
雪    币: 26205
活跃值: (63302)
能力值: (RANK:135 )
在线值:
发帖
回帖
粉丝
2
感谢分享!
2020-2-24 14:38
0
雪    币: 1449
活跃值: (128)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
3
也在学无名侠师傅的思路,楼主加油!
2020-2-24 16:42
0
雪    币: 94
活跃值: (2397)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
4
可以,很6
2020-2-24 17:56
0
雪    币: 10944
活跃值: (7329)
能力值: ( LV12,RANK:219 )
在线值:
发帖
回帖
粉丝
5
666
2020-2-24 21:57
0
雪    币: 199
活跃值: (272)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
牛b啊
2020-2-25 08:38
0
雪    币: 47
活跃值: (418)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
7
看这示例函数名感觉像是 libdexhelper.so 
2020-2-25 14:59
0
雪    币: 57
活跃值: (386)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
学习
2020-3-27 11:34
0
雪    币: 443
活跃值: (1157)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
9
unicorn一个字,好使  hahha
2021-3-21 22:50
0
游客
登录 | 注册 方可回帖
返回
//