前言
这个收集整理工作笔者是2022年左右完成的, 现在拿出来分享. OLLVM学习这个系列可能内容会有点乱, 因笔者目前在研究IR, 一些成果是几天内出的.
之前提到LLVM的架构优于Gcc, 因此可以在其上可以更好的实现编译器层级的代码混淆. 这就是ollvm(obfuscated-llvm). 笔者第一次接触到ollvm是在2017年做漏洞挖掘的时候, 去年笔者写过一篇文章简单介绍过Ollvm和VMPhttps://www.0xaa55.com/thread-27389-1-1.html.
控制方式
以下Ollvm项目中, 有的混淆类型是全局的(-mllvm), 有的是基于模块的(-mllvm), 而有的则可以指定到函数这一层, 有的支持注解方式(如__attribute((__annotate__(("fla"))))
), 而有的支持json文件来控制黑白名单, 方便一些无法使用注解的特殊场景使用.
最早的OLLVM
https://github.com/obfuscator-llvm/obfuscator, 是瑞士西北应用科技大学安全实验室于2010年6月份发起的一个项目, 支持LLVM3.3-4.0. 之后出现呢的所有ollvm项目均基于该项目开发. 该项目首次提出LLVM方式进行“控制流伪造”(BCF),“控制流平坦化”(FLA),“指令替换”(SUB)的代码混淆方式.
Hikari
https://github.com/HikariObfuscator/Hikari, 2018年开始的Ollvm项目, 支持LLVM6.0-8.0, 与obfuscator相比增加了如下功能:
- OC混淆, 混淆Objective-C类名及selector, 防止你优雅的逆向, 看一眼函数就知道干嘛的了
- 函数包装, 将一个函数调用变成深层嵌套函数, 功能不强, 可以恶心一些小白
- 字符串加密, 通过异或的方式加密字符串到数据区, 首次使用时解密
- 间接分支, 将跳转地址改为跳转寄存器, 大大增强FLA难度
- 拆分基本块, 功能也很强, 但容易产生崩溃
- 函数调用混淆, 把函数调用改成dlopen+dlsym的动态调用
Hikari-LLVM15
https://github.com/61bcdefg/Hikari-LLVM15, 2022年开始的替代Hikari的项目, Hikari原作者不开发了. 支持LLVM15+, 与Hikari相比增加了如下功能:
- 支持Swift
- 反调试
- 反Hook
- 常量加密
- 支持arm64e
Pluto
https://github.com/bluesadi/Pluto, 2021年开始的Ollvm项目, 支持LLVM14, 与obfuscator相比增加了如下功能:
- 增强的FLA
- 增强BCF为“随机控制流”(RCF)
- 反Angr, Angr是一种利用符号执行动态分析Ollvm的方式
- MBA(Mixed Boolean-Arithmetic)混淆, 将一个常量表达式用一系列运算代替, 算伪造指令流, 但比花指令高级多了
混合布尔算术(Mixed Boolean Arithmetic)是2007年提出的一种混淆算法, 这种算法由算数运算(例如ADD/SUB/MUL)和布尔运算(例如AND/OR/NOT)的混合使用组成
goron
https://github.com/amimo/goron, 2019年开始的Ollvm项目, 支持LLVM7/8/9/10, 与obfuscator相比增加了如下功能:
- 间接调用, 将引用的函数地址变换后存到数据区, 再动态调用
- 间接全局变量, 将引用的变量地址变换后存到数据区, 再动态调用
Arkari
https://github.com/KomiMoe/Arkari, 2022年开始的基于goron的项目, goron原作者不开发了. 支持LLVM14+, 功能和goron一致
xVMP
https://github.com/GANGE666/xVMP, 用LLVM实现的VMP, 支持LLVM8, 只支持Debug不支持Release
其他Ollvm
PS: 关于基于Ollvm的VMP, iOS上因为有内存保护, 非越狱无法动态更改指令, 因此iOS上的VMP只能沦为IR解释器, 因此其解密难度比Lua/JS等解释器低得多. 所以还不如用跨语言方式去增加整体复杂度.
总结
就跨平台兼容性和稳定性而言, 原版Ollvm > Hikari > 其他Ollvm, 这里的不稳定指的是编译失败, 或运行时未达到混淆目的, 或运行时因为混淆导致问题; 就功能而言, Hikari > 原版Ollvm, 其他Ollvm各有特色. 可以根据自己实际情况使用