移动端安全 OLLVM
字数 2359 2025-08-22 12:23:30
OLLVM移植与使用详解
1. OLLVM简介
OLLVM(Obfuscator-LLVM)是一个基于LLVM框架的代码混淆工具,主要用于增强代码的安全性,防止逆向工程分析。它提供了三种主要的混淆功能:
- 指令替换(Instruction Substitution)
- 虚假控制流(Bogus Control Flow)
- 控制流平坦化(Control Flow Flattening)
2. OLLVM移植到LLVM-14.0.6
2.1 移植步骤
-
获取OLLVM项目:
git clone https://github.com/buffcow/ollvm-project -
添加头文件:
- 在
llvm/include/llvm/Transforms文件夹下创建Obfuscation目录 - 按照[commit](llvm support obfuscator)中的内容逐个添加头文件
- 在
-
添加源文件:
- 在
llvm/lib/Transforms文件夹下创建Obfuscation目录 - 按照[commit](llvm support obfuscator)中的内容逐个添加源文件
- 在
-
修改支持文件及配置:
- 按照[commit](llvm support obfuscator)对LLVM项目中相关文件进行补充或修改
2.2 编译OLLVM
mkdir build
sudo cmake -S llvm -B build -G Ninja -DLLVM_ENABLE_PROJECTS="clang" -DCMAKE_BUILD_TYPE=Release -DLLVM_INCLUDE_TESTS=OFF -DLLVM_ENABLE_NEW_PASS_MANAGER=OFF
sudo cmake --build build -j4
编译完成后,可在build/bin文件夹中查看生成的工具。
3. OLLVM混淆功能详解
3.1 指令替换(Instruction Substitution)
功能:随机选择一种功能上等效但更复杂的指令序列替换标准二元运算符。
编译选项:
-mllvm -sub:激活指令替换操作-mllvm -sub_loop=3:在函数上应用3次,默认值为1
替换规则示例:
-
算术运算:
a = b + c替换为:a = b - (-c) // 或 a = -(-b + (-c)) // 或 r = rand(); a = b + r; a = a + c; a = a - r // 或 r = rand(); a = b - r; a = a + b; a = a + ra = b - c替换为:a = -(-b + c) // 或 r = rand(); a = b + r; a = a - c; a = a - r // 或 r = rand(); a = b - r; a = a - c; a = a + r
-
逻辑运算:
a = b & c替换为a = (b ^ ~c) & ba = b | c替换为a = (b & c) | (b ^ c)a = a ^ b替换为a = (~a & b) | (a & ~b)
源码分析:
Substitution类继承自LLVM中的FunctionPass类- 覆盖
runOnFunction实现混淆逻辑 toObfuscate函数根据传入的flag和其他参数决定是否混淆函数substitute方法执行实际的混淆逻辑
3.2 虚假控制流(Bogus Control Flow)
功能:在程序的控制流图(CFG)中引入虚假的分支和基本块。
编译选项:
-mllvm -bcf:激活虚假控制流-mllvm -bcf_loop=3:对基本块混淆操作连续进行3次-mllvm -bcf_prob=40:操作发生的概率为40%
示例:
#include <stdlib.h>
int main(int argc, char **argv) {
int a = atoi(argv[1]);
if (a == 0) return 1;
else return 10;
return 0;
}
源码分析:
BogusControlFlow类继承自FunctionPassbogus函数:- 将函数的所有basicblock存放到list容器
- 使用while循环调用
addBogusFlow函数对选中的basicblock增加虚假控制流
addBogusFlow函数:- 使用
getFirstNonPHIOrDbgOrLifetime找到第一个有效指令地址 - 使用
splitBasicBlock将一个basicblock一分为二 - 使用
createAlteredBasicBlock拷贝生成"altered basicblock" - 设置跳转条件,创建分支跳转指令
- 使用
doF函数:- 遍历Module内的所有指令
- 将所有的FCMP_TRUE分支指令替换为永真式
3.3 控制流平坦化(Control Flow Flattening)
功能:把程序原有逻辑转化成多个case-swich的扁平状结构。
编译选项:
-mllvm -fla:激活控制流平坦化功能-mllvm -split:激活基本块分裂-mllvm -split_num=3:使每个基本块上分裂3次
实现原理:
- 创建循环入口基本块(loopEntry)和循环出口基本块(loopEnd)
- 创建switch-default基本块(swDefault)
- 创建switch指令,根据条件决定跳转方向
- 将函数原有基本块添加到switch-case语句中
- 修改基本块之间的跳转关系
4. OLLVM移植到NDK
4.1 移植步骤
-
覆盖NDK目录:
- 将LLVM中的
bin、lib、include目录覆盖NDK的toolchains/llvm/prebuilt/linux-86_64/目录下对应目录
- 将LLVM中的
-
覆盖clang目录:
- 将
toolchains/llvm/prebuilt/linux-86_64/lib64目录下的clang文件夹覆盖到toolchains/llvm/prebuilt/linux-86_64/lib目录下
- 将
4.2 CMake配置
在cpp目录下的CMakeLists.txt中添加混淆配置:
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mllvm -bcf -mllvm -bcf_loop=3 -mllvm -fla -mllvm -split -mllvm -split_num=3")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mllvm -bcf -mllvm -bcf_loop=3 -mllvm -fla -mllvm -split -mllvm -split_num=3")
5. LLVM Pass操作对象结构
OLLVM混淆操作主要针对以下LLVM IR结构:
- Module:对应C/C++文件
- Function:对应C/C++代码中的函数
- BasicBlock:每个函数被划分为若干基本块,一个block只有一个入口和一个出口
- Instruction:具体的指令
6. 总结
OLLVM提供了强大的代码混淆能力,通过指令替换、虚假控制流和控制流平坦化等技术,可以有效增加逆向工程的难度。移植到特定版本的LLVM和NDK需要仔细处理文件结构和编译配置。在实际应用中,可以根据安全需求选择适当的混淆选项和参数组合。