ollvm介绍以及环境配置
什么是OLLVM?
首先了解什么是llvm,[原创]LLVM了解篇剧场版
以上这篇文章简要地介绍了LLVM
LLVM:Low Level Virtual Machine(最初)
官方定义:LLVM是一个模块化和可重用的编译器和工具链技术的集合
LLVM最初是在2000年由伊利诺伊大学香槟分校(UUIC)的学生Chris Lattner及其硕士顾问Vikram Adve创建的研究项目,并在2003年发布第一个正式版本,目的是提供一种基于SSA的现代编译策略,这种策略能够支持任何编程语言的静态和动态编译。
有意思的是,他的作者原本想要写一个低层虚拟机的,然而他并没有被当成虚拟机来用,逐渐地偏离了他原本的方向。现在llvm不是任何单词的缩写,而是一种体系,包含了一系列的项目
对于LLVM核心(LLVM Core)来说,它是一个编译器基础设施框架,它包含了为我们编写编译器一系列的库(如程序分析、代码优化、机器代码生成等),并且提供了调用这些库的相关工具,如llvm-opt可以调用LLVM优化相关的库,llvm-mc可以调用LLVM机器代码生成相关的库。并为此提供了一个非常方便简单、具备类型的、平台无关的统一中间代码语言,称之为LLVM IR.
Obfuscator-LLVM
Obfuscator-LLVM是由瑞士伊夫尔东莱班的应用科学与艺术大学信息安全小组(HEIG-VD)于2010年6月发起的一个项目。
该项目的目的是提供LLVM编译套件的开源分支,该套件能够通过代码混淆和防篡改来提高软件安全性。由于我们目前大部分工作在中间表示(IR)级别,因此我们的工具与所有编程语言(C,C ++,Objective-C,Ada和Fortran)和目标平台(x86,x86-64,PowerPC,PowerPC-64)兼容。
LLVM当前支持的ARM,Thumb,SPARC,Alpha,CellSPU,MIPS,MSP430,SystemZ和XCore)。
Obfuscator-LLVM的目的主要是在编译时增强软件就对抗向工程和编译时修改(动态调试?)
总之一句话,就是混淆llvm编译的可执行文件,让逆向分析更困难
环境编译
移植ollvm或者写自定义的pass等等,都需要先编译环境,网上有很多ollvm版本。
由于最开始就是llvm4.0版本,但现在迭代太快,不可能用这么老的版本。
这里演示挑选:ollvm9.0版本
1 | ➜ clang --version |
孤挺花https://github.com/GoSSIP-SJTU/Armariris中编译的是llvm4.0版本。
许多功能没有,hakari的字符串没有孤挺花的好用。
但是可以移植,这里找了一份可移植性比较高的版本。https://github.com/kunnan/KNHikari-20180526
将全部源码下载,mac编译
1 | git clone https://github.com/kunnan/KNHikari-20180526 |
编译完成会生成build/bin目录。
但是一般不出意外都会编译错误。
这里有很多编译问题:https://magic-king.net/posts/ollvm-learning/
https://www.jianshu.com/p/ab3694b12cfc 这位大佬已经帮我们编译好了一个ollvm版本,亲测可用。
接下来讲讲怎么把孤挺花里面的stringpass移植进去。
移植stringpass
一般的pass文件都是在lib/Transforms/Obfuscation
头文件 include/llvm/Transforms/Obfuscation
目标是将StringObfuscation.cpp移植到goron中,
先看看cpp中需要那些h文件。
1 |
拷贝到goron同级目录中。
看下我的目录结构
1 | goron/llvm/lib/Transforms/Obfuscation on llvm-9.0.0 [!?] |
移植了要注意以下几点:
cmakelist要声明StringObfuscation.cpp
ObfuscationPassManager.h 添加
\#include "llvm/Transforms/Obfuscation/StringObfuscation.h"
ObfuscationOptions.h 添加
bool EnableSOBF;
StringObfuscation.h 改为
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
namespace llvm {
class ModulePass;
class PassRegistry;
class IPObfuscationContext;
struct ObfuscationOptions;
ModulePass* createStringObfuscationPass();
ModulePass* createStringObfuscationPass(bool flag, IPObfuscationContext *IPO, ObfuscationOptions *Options);
void initializeStringEncryptionPass(PassRegistry &Registry);
}StringObfuscation.cpp 将最后几行修改一下,为了匹配头文件
1
2
3
4
5
6
7
8
9
10
11
12
13char StringObfuscationPass::ID = 0;
static RegisterPass<StringObfuscationPass> X("GVDiv", "Global variable (i.e., const char*) diversification pass", false, true);
// Pass * llvm::createStringObfuscationPass(bool flag) {
// return new StringObfuscationPass(flag);
// }
ModulePass *llvm::createStringObfuscationPass() { return new StringObfuscationPass(true); }
ModulePass *llvm::createStringObfuscationPass(bool flag,
IPObfuscationContext *IPO,
ObfuscationOptions *Options) {
return new StringObfuscationPass(flag);
}ObfuscationPassManager.cpp 中也要添加一个注册方式
1
2
3
4
5
6
7
8
9
10
11static cl::opt<bool>
EnableIRStringObfuscation("irobf-sobf", cl::init(false), cl::NotHidden,
cl::desc("Enable IR Constant String Obfuscation."));
if (EnableIRStringEncryption || Options->EnableCSE) {
add(llvm::createStringEncryptionPass(true, IPO, Options.get()));
// add(llvm::createStringObfuscationPass(true, IPO, Options.get()));
} else if (EnableIRStringObfuscation || Options->EnableSOBF)
{
add(llvm::createStringObfuscationPass(true, IPO, Options.get()));
}
可以开始编译了,不出意外就不会出意外,编译完成之后。
移植到NDK中
建议21.3/21.4版本的NDK
将ollvm中的clang
, clang++
, clang-format
三个文件复制到ndk/21.1.6352462/toolchains/llvm/prebuilt/darwin-x86_64/bin
中,使用替换
方式。
配置NDK
在app\build.gradle
中增加下面配置:
1 | android { |
编译APK
出现下面错误
1 | /sysroot/usr/include/jni.h:27:10: fatal error: 'stdarg.h' file not found |
复制头文件
上面的提示缺少stdarg.h
文件,此文件在ollvm编译
的文件夹lib/clang/9.0.0/include/
中可以找到,然后复制到/ndk/21.1.6352462/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include
的目录下。
以此类推的复制头文件,我这里一共复制了下面这些文件:
1 | stdarg.h |
开启混淆
上面的构建是一个常规的c++项目,并没有开启ollvm的混淆,把混淆开启一下,goron支持的配置如下:
说明 | 配置 |
---|---|
间接跳转 | -mllvm -irobf-indbr |
间接函数调用 | -mllvm -irobf-icall |
间接全局变量引用 | -mllvm -irobf-indgv |
字符串(c string)加密功能 | -mllvm -irobf-cse |
过程相关控制流平坦混淆 | -mllvm -irobf-cff |
过程相关控制流平坦混淆 -mllvm -irobf-sobf 孤挺花的字符串加密。
1 | externalNativeBuild { |
下载
知道你们懒,这是我编译好的goron,直接替换到你们的ndk就可以了,下载去吧:腾讯云
考虑时间的流逝,替换的时请注意您的ndk里的llvm的版本,我当前的版本:21.1.6352462