吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 6667|回复: 15
收起左侧

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

  [复制链接]
欧阳锋锋 发表于 2020-2-24 14:29
本帖最后由 欧阳锋锋 于 2020-2-24 16:14 编辑

                      ollvm控制流混淆学习、逆向过程
    感谢无名大佬提供的思路,使用了下unicorn,编写IDApython脚本去掉控制流混淆,unicorn一个字,好使,推荐大家可以用用

                    第一部分ollvm编译,实际测试下控制流混淆的效果
    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
          图片1.png

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

    4、使用clang分别进行编译,一个加载控制流混淆pass,一个不加载,在ida中进行对比下看看效果
    图片59.png
       未加控制流混淆pass
  除了入口块,还剩余4个真实块
   图片60.png

      添加控制流混淆pass
     可以看到添加了好多用来寻找真实块的无用块,统一从0xDB0块出发,找到真实块,最后统一从块0xDC0回到块0xDB0,跳
  转到入口块的指令都是有很明显的特征的,后边会提到
   图片61.png

      以上是llvm生成的最终的机器指令控制流程图
     llvm 通过Function.viewCFG()提供生成bB的中间IR指令的控制流图      在控制流混淆PassrunOnFunction函数的前后调用
       f.viewCFG(),可以清晰的看到       混淆前后中间IR指令控制流图对比

  
图片62.png

    对比下IR控制流图,
混淆前:
图片63.png
     混淆后:
图片64.png


      第二部分简单看看ollvm控制流平坦源码流程
看下源码, https://github.com/obfuscator-llvm/obfuscator Lib\Transforms\Obfuscation\Flattening.cpp中的flatten函数     
    1、  第一个块                :添加 AllocaInstStoreInstBranchInst指令,alloca分配switchVar变量空间,store填充switchVar为随机                 
               值,bl跳转到loopEntry      
    2、  loopEntry           : 添加 LoadInstSwitchInst指令,load获取switchVar变量地址,switch根据获取的switchVar值,查表跳转
    3、  loopEnd               添加 BranchInst指令,跳转到loopEntry      
    4、真实块                     : 如果是无条件分支指令,去掉终止指令br,添加StoreInstBranchInst指令,根据真实块后继对应的switchNum
                 用store更新switchVar值,跳转到loopEnd块如果是条件分支指令,去掉终止指令br,添加SelectInstStoreInst、
                 BranchInst指令,根据SelectInst指令选择的真实块后继对应的switchNumstore更新switchVar值,跳转到loopEnd     
    5 switchDefault         添加 BranchInst指令,跳转到loopEnd

引用网上的一张图

图片65.png

     总结控制流混淆的原理:            
    搭建一个switch代码框架,将真实块塞到框架case中,根据switchVar变量的值,通过switch指令寻找到真实的代码块,跟前边开启
了混淆编译,中间生成的IR流程就能匹配起来了。控制流混淆生成的中间IR控制流图和源码是完全能对应起来的,都是通过switch
令, 随机值串联起来的,但是和生成的汇编控制流图还不太一样,反汇编生成的控制流图是通过多个块中的比较指令,最终找到真实块

                   第三部分bb平坦化混淆   
   Hook app输出日志函数pBA425510043BB3BE41A7E30AA69623BE     反混淆之前控制流图:   
图片66.png        

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

反混淆之后控制流图:   
图片69.png    

F5伪代码: 可以看到是劫持了libcutils.soliblog.so中的符号:__android_log_write __android_log_buf_write  
   图片70.png       
   图片71.png    

字符串解密函数: 反混淆之前控制流图:
图片72.png

    F5伪代码  
   图片73.png

     反混淆之后  F5伪代码
      图片74.png                

        第四部分通过Unicorn去掉bb控制流混淆   

1、  找出函数中的分支分发指令TBB/TBH的地址,switch表的个数通过Capstone反汇编引擎,通过简单的助记符匹配即可找到,
    这一组指令的地址,并获取其中的操作数        
   图片75.png    

第一个cmp的操作数,一般为函数的pop指令所在块的入口号 第二个cmp的操作数,一般为函数的pop指令所在块的入口号  
   图片76.png          
图片77.png    
图片78.png    

2、  tbb/tbh指令开始,已知switch表的地址,表的个数n,计算出tbb指令跳转的case地址,即为真实块的入口地址,找到switchVar  
        和块地址映射关系,tbb指令表的每一项大小位1字节,tbh每一项大小位2字节
图片79.png    
图片80.png    
  
3、tbb/tbh指令开始,模拟执行所有可能的路径,在路径退出时获取R3的值,,再对应前边找到的switch表的映射关系,就能   
知道当前路径所要跳转的下一个真实块的地址,以及需要patch的地址   
   a)、执行到pop指令,栈平衡,函数退出指令   
   b)、执行到pop指令,栈平衡,函数退出指令   
   图片81.png    

4、根据找到的对应关系利用keystone引擎patch,即可实现对控制流平坦化去混淆

总结:实际操作过程中各种情况还是很多的,有很多问题需要注意,比如:    . 寻找switch指令特征可能是cmp/bhi/tbb   
    .  一个case链中还存在switch表。   
    .  swtichVar变量赋值,不是直接给定立即数,可能是上个真实块中的某个寄存器,再进行逻辑运算生成的。            
    . 一个真实块会根据其中的某些结果,跳转到不同的真实块,通过ITE/MOVELT/MOVEGE            
    给R3赋值。            
   等等还是有好多细节,可能无法完全自动化,需要根据各个函数的特征,进行匹配,  
控制流平坦化去混淆的思路是一样的。
参考
1. https://bbs.pediy.com/thread-252321.htm
2. https://security.tencent.com/index.php/blog/msg/112
3. https://github.com/obfuscator-llvm/obfuscator.git      
4.https://rpis.ec/blog/dissection-llvm-obfuscator-p1/         

免费评分

参与人数 9吾爱币 +11 热心值 +9 收起 理由
6603547 + 1 + 1 谢谢@Thanks!
XhyEax + 1 + 1 我很赞同!
二娃 + 2 + 1 我很赞同!
Ravey + 1 + 1 谢谢@Thanks!
丶咖啡猫丶 + 1 + 1 谢谢@Thanks!
sxkw + 1 + 1 我很赞同!
windy_ll + 2 + 1 我很赞同!
heletian + 1 + 1 我很赞同!
大虹Vinnie + 1 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

雨落惊鸿, 发表于 2020-2-24 15:01
???在哪呢
涛之雨 发表于 2020-2-24 17:48
精华预约(此时尚未获得精华)
那有可能看一下这个帖子吗?
2020年春节红包第四题wp
https://www.52pojie.cn/thread-1101266-1-1.html
(出处: 吾爱破解论坛)

这个就是ollvm的,不知道能不能简化一下,
安卓的应该和Linux差不了多少吧(虽然安卓本来就是Linux改的。。。。)
 楼主| 欧阳锋锋 发表于 2020-2-24 16:20
头像被屏蔽
那年听风 发表于 2020-2-24 20:37
提示: 作者被禁止或删除 内容自动屏蔽
mucong88star 发表于 2020-2-24 21:11
感谢哈非常不错哈哈
thysut 发表于 2020-2-24 22:05
学习了,感谢分享
heletian 发表于 2020-2-25 05:45
谢谢大佬的分享!
SaoXiaoyu 发表于 2020-2-25 07:59
大佬,小白完全看不懂
lxhwan100 发表于 2020-2-25 08:57
厉害,感谢分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-12-26 12:10

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表