【原创】移除ollvm中的控制流平坦化、不透明谓词

  • A+
所属分类:安全闲碎

作者坛账号:小远zi

llux

ollvm de-obfuscator

移除ollvm中的控制流平坦化、不透明谓词

ll取自ollvmux取自lux,寓意混淆之中的光亮和线索

【原创】移除ollvm中的控制流平坦化、不透明谓词
【原创】移除ollvm中的控制流平坦化、不透明谓词
【原创】移除ollvm中的控制流平坦化、不透明谓词
【原创】移除ollvm中的控制流平坦化、不透明谓词
【原创】移除ollvm中的控制流平坦化、不透明谓词

Description

* 实现了在x86_64架构下,开启代码优化后,控制流平坦化以及不透明谓词的移除

* 实现原理不同于符号执行,无需条件约束,在遇到BCF增加的死循环块的时候,依然可以完成路径遍历

* 针对ollvm进行了充分地优化,速度对于符号执行框架angr速度较快,且可以处理复杂样本

* 暂未开源,因为这样会使得混淆对抗太过于简单,这里只提供了工具方便使用

Usage 1

我们有如下代码,使用函数注解的形式开启了ollvm的全部的混淆功能,使用较低的bcf概率 -mllvm -bcf_prob=3,在开启较高概率时,可以对部分条件进行手动patch,最终在程序运行结束之后会提示一些无法到达的基本块,手动删除即可,参考Usage 3

* fla:控制流平坦化

* sub:指令替换

* split:基本块拆分

* bcf:伪造控制流

【原创】移除ollvm中的控制流平坦化、不透明谓词

编译后的CFG(控制流程图)

【原创】移除ollvm中的控制流平坦化、不透明谓词

在要去除混淆的函数入口下断(硬件断点),并运行到

【原创】移除ollvm中的控制流平坦化、不透明谓词

dump堆栈内存

【原创】移除ollvm中的控制流平坦化、不透明谓词

dump模块内存

【原创】移除ollvm中的控制流平坦化、不透明谓词

编写subroutine.txt

【原创】移除ollvm中的控制流平坦化、不透明谓词

将dump的内存和subroutine.txt按如下方式布局

【原创】移除ollvm中的控制流平坦化、不透明谓词

程序在短暂运行后会在当前路径下生成code.asm

【原创】移除ollvm中的控制流平坦化、不透明谓词

拿到vs进行编译

【原创】移除ollvm中的控制流平坦化、不透明谓词

经过对代码进行一定的修改,使得其可以通过编译(修改后的代码上传到了Release)

【原创】移除ollvm中的控制流平坦化、不透明谓词

【原创】移除ollvm中的控制流平坦化、不透明谓词

观察到不透明谓词

【原创】移除ollvm中的控制流平坦化、不透明谓词

其中是dword_14001DA48,dword_14001DA4C分别是ollvm bcf功能中的int类型的全局变量x和y,地址连续,值恒为0

 复制代码 隐藏代码
mov    eax,dword_14001DA48

手动修改成如下代码化简逻辑

mov    eax,0
 复制代码 隐藏代码
cmp    dword_14001DA4C, 0ah
cmovl  eax, r13d

手动修改成如下代码化简逻辑

;cmp    dword_14001DA4C, 0ah
mov    eax, r13d
 复制代码 隐藏代码
mov    eax, 0ff85a711h
mov    ecx, 4ef55c6dh
cmovl  eax, ecx
;jmp    1400012f0h
cmp    eax,0ff85a711h
je     loc_1400013a1
jmp    loc_140001459

手动修改为如下代码化简逻辑

;mov    eax, 0ff85a711h
;mov    ecx, 4ef55c6dh
;cmovl  eax, ecx
;jmp    1400012f0h
;cmp    eax,0ff85a711h
jl     loc_140001459
jmp    loc_1400013a1

按照上述的方法对代码进行一些调整,得到:

【原创】移除ollvm中的控制流平坦化、不透明谓词

使用函数返回值对比验证逻辑的正确性,通过

【原创】移除ollvm中的控制流平坦化、不透明谓词

我们在基于angr框架的deflat.py了进行了测试,结果是失败的

【原创】移除ollvm中的控制流平坦化、不透明谓词


Usage 2 multi-dispatcher

按照上述操作,我们同样地实现了更加复杂且拥有多个分发器样本的去混淆

【原创】移除ollvm中的控制流平坦化、不透明谓词

编译后的CFG(控制流程图)

【原创】移除ollvm中的控制流平坦化、不透明谓词

短暂运行后,我们过滤掉了无法到达的基本块140001cd7、1400025c5(这里是程序逻辑本身就不可达,并不是BCF,因为我们没有进行patch)

【原创】移除ollvm中的控制流平坦化、不透明谓词

诸如此类的逻辑会出现不可能到达的基本块,这是因为ollvm的混淆pass会优先于llvm的优化pass

【原创】移除ollvm中的控制流平坦化、不透明谓词

手动删除未到达的基本块140001cd7、1400025c5

手动删除死循环块

【原创】移除ollvm中的控制流平坦化、不透明谓词

手动删除死循环块的引用

【原创】移除ollvm中的控制流平坦化、不透明谓词

按照上述的方法对代码进行一些调整,得到:

【原创】移除ollvm中的控制流平坦化、不透明谓词

使用函数返回值对比验证逻辑的正确性,通过

【原创】移除ollvm中的控制流平坦化、不透明谓词

Usage 3 bcf patch

我们将Usage 1中的代码使用默认的bcf概率-mllvm -bcf_prob=30进行编译,相较于-mllvm -bcf_prob=3的概率明显复杂了一些。我们需要寻找类似箭头所指的bcf块,特点是有多个前驱,后继为分发器,这种情况是因为编译优化造成的

【原创】移除ollvm中的控制流平坦化、不透明谓词

bcf块内容如下,一般情况两个cmov都是条件都是满足的,可以看做mov

【原创】移除ollvm中的控制流平坦化、不透明谓词

所以逐一对bcf块的所有前驱进行简单的patch操作

【原创】移除ollvm中的控制流平坦化、不透明谓词

bcf块进行nop操作

【原创】移除ollvm中的控制流平坦化、不透明谓词

按照Usage 1中演示的方法进行操作。llux对一些基本块进行了合并,并提示了无法到达的基本块

【原创】移除ollvm中的控制流平坦化、不透明谓词

手动删除因为基本块合并导致重定义的符号

【原创】移除ollvm中的控制流平坦化、不透明谓词

并按照之前的方法对代码进行一定的调整,最终得到

【原创】移除ollvm中的控制流平坦化、不透明谓词

使用函数返回值对比验证逻辑的正确性,通过

【原创】移除ollvm中的控制流平坦化、不透明谓词

Reference

  • deflat

  • PLCT实验室维护的ollvm分支

  • 利用符号执行去除控制流平坦化

  • Deobfuscation: recovering an OLLVM-protected program

Github

https://github.com/llxiaoyuan/llux

--

www.52pojie.cn


--

pojie_52

本文始发于微信公众号(吾爱破解论坛):【原创】移除ollvm中的控制流平坦化、不透明谓词

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: