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

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

2020-2-24 14:02
11795

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

    1、99cK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6G2j5X3k6#2M7$3y4S2N6r3!0J5i4K6u0V1L8r3I4$3L8g2)9J5c8X3!0T1k6Y4g2K6j5$3q4@1L8%4u0Q4c8e0c8Q4b7U0S2Q4z5p5u0Q4c8e0S2Q4b7V1c8Q4b7V1c8Q4c8e0k6Q4z5f1y4Q4z5o6m8Q4c8e0k6Q4z5e0k6Q4b7U0m8Q4c8e0N6Q4z5f1q4Q4z5o6c8G2L8r3I4$3L8g2!0q4y4g2)9^5z5q4)9^5y4W2!0q4y4W2)9&6y4q4!0m8c8W2!0q4y4#2!0n7b7#2)9&6y4W2!0q4z5q4!0m8c8W2)9&6x3g2)9J5b7#2!0q4y4g2)9^5y4W2)9^5c8r3u0#2K9h3I4V1i4K6u0r3j5X3W2F1i4@1f1@1i4@1t1^5i4K6S2n7i4@1f1%4i4K6V1@1i4K6W2r3i4@1f1$3i4K6R3^5i4K6V1H3j5$3I4S2L8X3N6Q4c8e0y4Q4z5o6m8Q4z5o6t1`.

                 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控制流图,

        混淆前:

    

        

        混淆后:

       


    看下源码, e7eK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6G2j5X3k6#2M7$3y4S2N6r3!0J5i4K6u0V1L8r3I4$3L8g2)9J5c8X3!0T1k6Y4g2K6j5$3q4@1L8%4u0Q4x3U0k6F1j5Y4y4H3i4K6y4n7Lib\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的方式寻找到真实块

    


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 3
支持
分享
最新回复 (8)
雪    币: 42959
活跃值: (65807)
能力值: (RANK:135 )
在线值:
发帖
回帖
粉丝
2
感谢分享!
2020-2-24 14:38
0
雪    币: 1449
活跃值: (128)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
3
也在学无名侠师傅的思路,楼主加油!
2020-2-24 16:42
0
雪    币: 94
活跃值: (3107)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
4
可以,很6
2020-2-24 17:56
0
雪    币: 11606
活跃值: (8149)
能力值: ( LV12,RANK:219 )
在线值:
发帖
回帖
粉丝
5
666
2020-2-24 21:57
0
雪    币: 199
活跃值: (327)
能力值: ( 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
活跃值: (396)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
学习
2020-3-27 11:34
0
雪    币: 443
活跃值: (1187)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
9
unicorn一个字,好使  hahha
2021-3-21 22:50
0
游客
登录 | 注册 方可回帖
返回