下面是 Windows 10 系统中搭建 obfuscator llvm 6.0
步骤,适配的是 Android NDK 17.2.4988734
。
大致步骤是先准备环境,下载源码,编译源码,集成到 Android NDK 中,最后在项目中使用。
最后在 Mac10.15.5 系统中也搭建成功了。
准备环境
确保 gcc g++ 环境
由于是在windows上安装的(系统是Windows 10),因为没有gcc g++环境,需要安装mingw。
下载地址:mingw-w64
离线包安装: x86_64-posix-seh
如果使用在线安装会很慢,所以下载了离线安装包,这样耗费了些时间
下载离线安装包,解压就行。
添加路径 D:\mingw64\bin
以及 D:\mingw64\include
到系统环境变量中
这个是使用在线安装参考:在Windows中安装MinGW-w64
离线安装参考:MinGW-w64离线安装,测试可用
官方下载地址:mingw-w64
添加 cmake 环境变量
这里使用的是Android SDK自带的 3.10.2 版本
添加系统环境变量D:\Software\Android\Android\cmake\3.10.2.4988404\bin
方便直接使用cmake
命令
检查 ndk 版本
这里是准备直接使用 Android SDK 目录下的ndk-bundle
,这个也是ndk,本地一直有这个目录,点进去查看source.properties
文件:
1 | Pkg.Desc = Android NDK |
也就是说本地的SDK 是17.2.4988734
检查 clang 版本
检查本地的clang 版本,这个是非常重要的,决定了接下来编译哪个版本的 obfuscator
。
1 | D:\Software\Android\Android\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --version |
结果是 6.0.2的,之前一直使用4.0版本,各种出问题。
安装 obfuscator llvm
官方文档是4.0的:wiki-Installation
1 | $ git clone -b llvm-4.0 https://github.com/obfuscator-llvm/obfuscator.git |
6.0.0版本:LLVM 6.0 + Ollvm + Armariris
1 | git clone https://github.com/yazhiwang/ollvm-tll.git |
文档上已经写的很清楚应该怎么做了,很好
Armariris: 由上海交通大学密码与计算机安全实验室维护的LLVM混淆框架,主要是由字符串混淆。这里也有一个坑,从后面看到,就是设置种子的长度。
编译过程中如果测试用例跑不过,可以在cmake 后面跟参数 -DLLVM_INCLUDE_TESTS=OFF
关闭测试用例检查,不过我没有出这个问题。
第一步编译 obfuscator
工程 clone下来后,编译、链接生成可执行文件
在 cmd 中执行:
1 | git clone https://github.com/yazhiwang/ollvm-tll.git obfuscator-6.0 |
|tee b_build.txt
主要是将命令行日志打印到本地文件中
有两个注意的地方:
-G "MinGW Makefiles"
表示使用MinGW 来构建- 因为前面是mingw构建的,所有使用了
mingw32-make
而不是make指令,在这里耗费了些时间
make 过程确实比较耗时,起码30分钟吧。
- 生成obfuscator步骤后,就会在 build目录下生成
bin
、lib
目录 - make 之后会在 build目录下生成
bin
、lib
会有具体的执行文件和依赖库
这里并没有将生产文件放到外部目录,如在外部目录需要修改参数
1 | cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release ../obfuscator/ |tee b_build.txt |
4.0版本能编译完成,提示有错误:
1 | [100%] Built target llvm-lto2 |
下载6.0版本,过程中也有一些错误
1 | [ 98%] Built target arcmt-test |
make过程中也会有错误,先不管,能编译完成就行。
编译完成后可以简单检查下生产的clang是否可用,版本号能正常打印就ok
1 | cd build/lib |
第二步集成到 Android NDK
一共看到3种方式,最后只有一种方式成功了。因为项目使用的cmake方式,但是网上大部分都是ndk-build的方式。
修改目录就行:D:\Software\Android\Android\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64
- 先备份下修改的目录
- 打开修改的目录,将
lib
和bin
目录删除 - 然后将将刚刚生成的
build
目录下的bin
和lib
拷贝过去
就这样就使用了新的ollvm了。因为Cmake默认是要llvm的clang编译,这里相当于直接替换成了新的clang了。
第三步如何使用
项目使用的是Cmake,所以再工程的CMakeLists.txt
中增加
1 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mllvm -fla") |
打包APK,或者执行gradle任务 externalNativeBuildRelease
生成的so文件以及被混淆。
是否生效
对比前后so的函数,查看语句是否变复杂,是否添加了一些额外的干扰阅读的变量。
参数解释
控制流扁平化
这个模式主要是把一些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
字符串混淆
- -mllvm -sobf:编译时候添加选项开启字符串加密
- -mllvm -seed=0xdeadbeaf:指定随机数生成器种子流程
在build文件中添加:
1 | android { |
我是在CMakeLists.txt
中修改的:
1 | set(OLLVM "-mllvm -fla -mllvm -seed=32位长度大写 ") |
遇到的错误
Cannot open /dev/random
配置了AS工程后rebuild编译成功,但是又警告
1 | Cannot open /dev/random |
搜索到ollvm 使用——“Cannot open /dev/random”错误的解决方法
文中说到修改\obfuscator-llvm-4.0\lib\Transforms\Obfuscation\CryptoUtils.cpp
中bool CryptoUtils::prng_seed()
方法。
我看了下这个文件是有这个方法prng_seed
,按照他给的方法来做的话,完全行不通的样子,这个方法有返回值的,它提供的却没有。但是看到这个函数打印错误的地方,是seed的长度不匹配时,会这个报错
1 | bool CryptoUtils::prng_seed(const std::string _seed) { |
然后又看到文章 Automated Obfuscation of Windows Malware and Exploits Using O-LLVM 说到产生这个错误的原因时没有设置aesSeed
,马上设置,但是还是报错。然后再 Armariris 官方文档上看到是要设置 -mllvm -seed=0xdeadbeaf
。也就是 seed
的长度必须时32或者时34。修改后搞定,没有报警告了。
另外这里也有一个修改方案,不过没有使用 WIN10 x64搭建OLLVM4.0 android NDK 编译环境跨坑指南
Mac 下搭建
mac 环境下搭建就方便点。因为不需要安装gcc、g++环境,系统因为自带都有。具有的步骤跟前面类似。不同的是:
将 cmake 添加到环境变量中
1 | export CMAKE_ROOT=~/Documents/program/Android/SDK/cmake/3.10.2.4988404/bin |
同时需要查看 Android SDK 目录下的ndk-bundle
版本是不是17.2.4988734
,因为不同的ndk版本,可能使用的llvm不一样。如果没有这版本的SDK,使用SDK Manager 下载就行。
1 | android{ |
下载源码,编译编码、生产可执行文件,这些都是一样的步骤,不需要使用 -G "MinGW Makefiles"
参数
1 | makdir build |
最后将生产的文件夹📂 lib
和 bin
替换 ndk 目录中的 llvm目录下的文件夹📂 lib
和 bin
我这里的路径是:~/SDK/ndk/17.2.4988734/toolchains/llvm/prebuilt/darwin-x86_64
,里面并没有lib
目录
参考
windows 下搭建:
参数解释:
WIN10 x64搭建OLLVM4.0 android NDK 编译环境跨坑指南
mac 下搭建: