简介
参考原文 https://www.jianshu.com/p/e0637f3169a3
OLLVM(Obfuscator-LLVM)是瑞士西北应用科技大学安全实验室于2010年6月份发起的一个项目,该项目旨在提供一套开源的针对LLVM的代码混淆工具,以增加对逆向工程的难度。github上地址是https://github.com/obfuscator-llvm/obfuscator,只不过仅更新到llvm的4.0,2017年开始就没在更新。
移植
先放一下移植好的版本地址https://github.com/heroims/obfuscator.git,fork原版后又加入了llvm5.0,6.0,7.0以及swift-llvm5.0的版本,应该能满足大部分需求了,如果有新版本下面的讲解,各位也可以自己动手去下载自己需要的llvm和clang进行移植。
下载LLVM
llvm地址:https://github.com/llvm-mirror swift-llvm地址:https://github.com/apple 大家可以从上面的地址下载最新的自己需要的llvm和clang
1
2
3
4
5
6
7
8
9
10
#下载llvm源码
wget https://codeload.github.com/llvm-mirror/llvm/zip/release_70
unzip llvm-release_70.zip
mv llvm-release_70 llvm
#下载clang源码
wget https://codeload.github.com/llvm-mirror/clang/zip/release_70
unzip clang-release_70.zip
mv clang-release_70 llvm/tools/clang
添加混淆代码
如果用git的话只需要执行git cherry-pick xxxx
把xxxx换成对应的我的版本上的提交哈希填上即可。极度推荐用git搞定。
如果手动一点点加的话,第一步就是把我改过的OLLVM文件夹里/include/llvm/Transforms/Obfuscation
和/lib/llvm/Transforms/Obfuscation
移动到刚才下载好的llvm源码文件夹相同的位置。
1
2
3
4
5
git clone https://github.com/heroims/obfuscator.git
cd obfuscator
git checkout llvm-7.0
cp include/llvm/Transforms/Obfuscation llvm/include/llvm/Transforms/Obfuscation
cp lib/llvm/Transforms/Obfuscation llvm/lib/llvm/Transforms/Obfuscation
编译
1
2
3
4
5
mkdir build
cd build
#如果不想跑测试用例加上-DLLVM_INCLUDE_TESTS=OFF
cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_CREATE_XCODE_TOOLCHAIN=ON ../obfuscator/
make -j7
使用
这里原版提供了3种混淆方式分别是控制流扁平化,指令替换,虚假控制流程,用起来都是加cflags的方式。下面简单说下这几种模式。
控制流扁平化
这个模式主要是把一些if-else语句,嵌套成do-while语句
-mllvm -fla:激活控制流扁平化 -mllvm -split:激活基本块分割。在一起使用时改善展平。 -mllvm -split_num=3:如果激活了传递,则在每个基本块上应用3次。默认值:1
指令替换
这个模式主要用功能上等效但更复杂的指令序列替换标准二元运算符(+ , – , & , | 和 ^) |
-mllvm -sub:激活指令替换 -mllvm -sub_loop=3:如果激活了传递,则在函数上应用3次。默认值:1
虚假控制流程
这个模式主要嵌套几层判断逻辑,一个简单的运算都会在外面包几层if-else,所以这个模式加上编译速度会慢很多因为要做几层假的逻辑包裹真正有用的代码。
另外说一下这个模式编译的时候要浪费相当长时间包哪几层不是闹得!
-mllvm -bcf:激活虚假控制流程 -mllvm -bcf_loop=3:如果激活了传递,则在函数上应用3次。默认值:1 -mllvm -bcf_prob=40:如果激活了传递,基本块将以40%的概率进行模糊处理。默认值:30
上面说完模式下面讲一下几种使用方式
直接用二进制文件
直接使用编译的二进制文件build/bin/clang test.c -o test -mllvm -sub -mllvm -fla -mllvm -bcf
NDK集成
这里分为工具链的制作和项目里的配置。
制作Toolchains
这里以修改最新的ndk r18为例,老的ndk版本比这更容易都在ndk-bundle/toolchains里放着需要修改的文件。
1
2
3
4
5
6
7
8
9
10
#复制ndk的toolschain里的llvm
cp -r ndk-bundle/toolchains/llvm ndk-bundle/toolchains/ollvm
#删除prebuilt文件夹下的文件夹的bin和lib64,prebuilt文件夹下根据系统不同命名也不同
rm -rf ndk-bundle/toolchains/ollvm/prebuilt/darwin-x86_64/bin
rm -rf ndk-bundle/toolchains/ollvm/prebuilt/darwin-x86_64/lib64
#把我们之前编译好的ollvm下的bin和lib移到我们刚才删除bin和lib64的目录下
mv build/bin ndk-bundle/toolchains/ollvm/prebuilt/darwin-x86_64/
mv build/lib ndk-bundle/toolchains/ollvm/prebuilt/darwin-x86_64/
#复制ndk-bundle/build/core/toolchains的文件夹,这里根据自己对CPU架构的需求自己复制然后修改
cp -r ndk-bundle/build/core/toolchains/arm-linux-androideabi-clang ndk-bundle/build/core/toolchains/arm-linux-androideabi-clang-ollvm
最后把arm-linux-androideabi-clang-ollvm里的setup.mk文件进行修改
1
2
3
TOOLCHAIN_NAME := ollvm
TOOLCHAIN_ROOT := $(call get-toolchain-root,$(TOOLCHAIN_NAME))
TOOLCHAIN_PREFIX := $(TOOLCHAIN_ROOT)/bin
config.mk里是CPU架构,刚才是复制出来的所以不用修改,但如果要添加其他的自定义架构需要严格按照格式规范命名最初的文件夹,如mips的需要添加文件夹mipsel-linux-android-clang-ollvm,setup.mk和刚才的修改一样即可。
项目中配置
到了项目里还需要修改两个文件: 在Android.mk 中添加混淆编译参数
LOCAL_CFLAGS += -mllvm -sub -mllvm -bcf -mllvm -fla
Application.mk中配置NDK_TOOLCHAIN_VERSION
1
2
3
4
#根据需要添加
APP_ABI := x86 armeabi-v7a x86_64 arm64-v8a mips armeabi mips64
#使用刚才我们做好的编译链
NDK_TOOLCHAIN_VERSION := ollvm