ollvm 0x2 bcf

ollvm分析之bcf

昨日小记,在昨天,我的小手机到了之后,我想要调试soul,结果发现。安装不了?于是想要刷机刷至安卓5.0,嗯。。首先相信了所谓的flyme os for 红米1s,结果,到底是第三方rom,一堆垃圾软件抢着占用5037端口,adb一直显示offline,卸载之后什么软件都安装不了,太真实了,最后无奈刷回了miui9.0,所以,调试soul的计划又延迟了,不过我可以试试那个virtual android debug可以在x86上调试so。。无奈,之前修改分辨率绕过模拟器检测的方法似乎不好用了,所以还是等新手机吧。。以下是分割线

—————————————————————————————————————————————————
Ollvm混淆的两大特色就是虚假指令流和控制流平坦化(之前所有的分析都是为分析这两个做铺垫),虚假指令流大概由不透明谓词实现,简单的说就是通过条件判断语句去隐藏真实的执行流程,条件判断处一般加入的是十分难以理解的等式或不等式(很多数学上的定理可以使用,费马大定理之类的),攻击者在静态分析时很难辨别出真正的控制流。
图片.png-20.9kB
图片.png-74.9kB

上面这张图就清晰的展示了不透明谓词的用法,可以插入false代码块并复制正确代码块加大混淆的力度,首先看下混淆效果,样例代码:
图片.png-16.4kB
进行虚假指令流混淆
图片.png-42.8kB
观察下混淆后的cfg图(在文件夹附件demo1.png中),可以看到原本顺序执行的cfg图出现了一个分支,并且含有多次跳转,较为复杂,现在去分析下bcf的实现。
首先观察下boguscontrolflow.h这个头文件,
图片.png-17kB
和之前一样,不过导入的库较多,现在直接去看下实现的c文件,首先我们应该先去读一下关于bcf的详细介绍,可以选择git上的wiki(https://github.com/obfuscator-llvm/obfuscator/wiki/Bogus-Control-Flow),也可以选择看注释,读下大致我们可以了解到大致实现就是修改一个基本块的调用关系,一般是在这个基本块之前插入一个不透明谓词,然后通过判断性的跳转跳向原始的基本块(当然这里面会有大量花指令的插入)
图片.png-22.4kB
上图为注释中的描述,我们通过描述可以大概理解整个虚假指令流的执行过程
图片.png-38.1kB
首先可以看到的是每个基本块的默认混淆概率–defaultObfRate和默认的混淆次数defaultObfTime,然后根据编译时输入的参数可以自己确定混淆概率和次数,分别关联与ObfProbRate和ObfTimes,
图片.png-61kB
然后我们可以看到BogusControlFlow依旧是继承自FunctionPass,因此传入的参数是函数,然后校验了输入的混淆次数和概率的合法性,读取函数的annotation确定开启bcf后依次传入bogus和doF函数进行处理,首先看下bogus函数
图片.png-76.9kB
可以看到函数的一开始依旧是一些冗余的校验和调试的log信息,进入混淆真正开始,可以看到log出了混淆的全部函数名,并且创建了一个list用来保存该函数中的全部基本块
图片.png-35.1kB
然后开始对每一个基本块进行操作,从下图我们逐行分析,可以发现先从llvm的加密工具类中获得一个1-100的随机数与ObfRate进行对比,如果小于的话表示这个基本块被选中了,并且调用addBogusFlow进行混淆
图片.png-17.4kB
我们可以看到addBogusFlow的参数是当前基本块以及当前函数,下面进入增加虚假指令流函数内部进行分析,
图片.png-39.6kB
从注释中我们知道首先要进行的是分割基本块,分割成的两块中第一块只包含调试信息以及phi结点,第二个基本块包含了原始基本块的全部指令,这样做可以不用考虑更改控制流对phi结点造成的影响,然后分析下具体实现
图片.png-37.5kB
首先调用getFirstNonPHIOrDbgLifetime()获得第一条不是phi结点并且不是调试信息的地址,获得了这个地址是为了调用splitBasicBlock去分割,这个函数之前讲过,需要的参数就是从第i条指令开始分割以及分割后基本块的名字,这里我们可以看到分割后原本的基本块的名字叫OrignalBB,然后把初始基本块传入了CreateAlteredBasicBlock函数进行操作,去看下这个函数
图片.png-73.3kB
它首先调用llvm中的CloneBasicBlock函数克隆了原始的基本块,并且重命名了了之前phi结点的income块,然后它遍历并且保存了整个基本块中的全部指令,然后进行插入junk code(花指令)操作,
图片.png-99.6kB
可以看到首先对opcode进行判断,如果是add,sub,mul之类的,则传入switch进行加花操作,加花有四种操作,这里都是进行的opcode替换,详细的分析在之前的指令替换中可以看到
图片.png-58.9kB
在复制基本块和加入花指令的操作都完成之后,这个函数会返回一个创造出的基本块叫做alteredBB,之前分割基本块分割出来的叫做originalBB,再获得全部需要的BasicBlock之后,清楚了基本块原本的父子关系使之成为独立的基本块
图片.png-30.7kB
画一个大致的示意图
图片.png-5.6kB
这是原本的基本块在进行分割后得到的ir(详细的可以看之前的分析),然后去生成一个可选块alteredBB,清除父子关系后就是三个独立的基本块
图片.png-9.2kB
现在我们要做的就是重整控制流去完成混淆,
图片.png-38.6kB
首先去获得了两个浮点数,都是1.0,然后在原本的基本块的end处插入一条名为condition的浮点数比较指令,由于两个数都1.0,因此比较是恒成立的
图片.png-38.4kB
然后根据判断设置跳转条件,如果跳转条件为真(当然这里百分之百为真),则跳转至oringinalBB,否则就跳转到alteredBB,并且在alteredBB中添加一条跳转指令,跳转至oringinalBB,然后就是bogus函数的最后一部分了
图片.png-99.7kB
先获得了oringinalBB的最后一条指令的地址,然后再次对originalBB进行分割,分割完再次清除了父子关系,然后在分割的父基本块oringinalBB中插入一条判断语句,如果为真,则跳转到分割出的oringinalBB2,否则就跳转至alteredBB,此时画一张图理解下,
图片.png-16.5kB
上面就是bogus函数结束后的基本块的跳转图,在runOnFunction中我们知道执行完bogus函数后,我们会进行doF函数也就是最后的结束函数,
图片.png-77.1kB
DoF函数主要负责将全部为true的语句进行替换,首先它创造了两个全局变量x和y,用来建立等式或不等式(上图)
图片.png-65.8kB
然后遍历所有条件判断的指令,例如之前插入的fcmp_inst,并且筛选出全部为真的判断语句,存入toEdit中,后面就对x和y赋值并且创造等式
图片.png-121.4kB

利用恒等的式子进行替换之前1.00=1.00,就完成了不透明文谓词的混淆实现,至此,bcf的分析结束

附加:
脱离ollvm的不透明谓词混淆实现,原文(https://blog.quarkslab.com/turning-regular-code-into-atrocities-with-llvm.html)
这里选择的混淆方法依旧是在使之前正常执行的基本块混入了条件判断执行,其中,谓词中使用不等式为

其中 1 p1和p2是不同的质数
2 a1和a2是不同的随机正数
3 x和y是从程序中挑选的两个变量
由于这个不等式恒成立,因此结果恒为NULL,这里就用这个不等式去替换代码中所有出现的NULL值,
为了实现如上的混淆策略,我们首先要做的就是遍历基本块并找出其中为0的值

图片.png-83kB

这里我们注册的是集成自basicBlock的runOnBasicBlock函数,传入一个基本块中,我们遍历其中的每一条指令,使用getNumOperands获得指令的操作数,传入isValidCandidateOperand去判断这个数是否为整数以及是否为0,然后我们就要去生成不透明的谓词了,首先我们遍历程序中的所有整数并把申请一个vector把他们保存起来,

图片.png-4.1kB

图片.png-2.6kB

图片.png-85.1kB

——————————————————————————————————————————————————————————————————————————————
2019 2/26更新
Hikari中对bcf的升级,hikari是脱胎于ollvm 的升级版混淆工具,我们看下他对bcf的升级,首先在张总的博客中写到了关于ollvm原生bcf的缺点,总结一下,主要就是bcf中使用的不透明谓词是固定统一的,攻击者可以轻松的识别出这个谓词从而判断真实的基本快,甚至可以利用ida进行模块匹配还原出真实代码,因此,hikari make the predicate “on the fly”,也就是动态的,具体的实现,等闲下来继续看。

参考资料:
有关llvm混淆的一切,强推张总博客,mayuyu.io
ollvm分析:https://sq.163yun.com/blog/article/175307579596922880
www.ench4nt3r.com/2018/02/26/post/
https://github.com/HikariObfuscator/Hikari
https://blog.csdn.net/baimafujinji/article/details/80547088