编写LLVM的自定义混淆Pass后,每次使用都需要用opt 工具加载Pass的so,混淆BC文件,这个步骤麻烦又很累!
而OLLVM的混淆Pass可以直接用clang的特定参数启动,为了让我编写的自定义混淆Pass也能直接用clang启动,就有
了这篇文章。 虽然网上有一些参考资料,但是使用的却是非常老的LLVM3.5及其以下版本,OLLVM使用的是LLVM4.0 。
其实并没有很难,只是网上几乎没有资料,让人很头痛……因为毕竟这么大一个项目,没那么好搞。但是有OLLVM
作为参考,真的很棒啊……
1.创建头文件,并添加创建Pass的函数声明(我是直接在混淆器的include目录下添加的):
//文件MyObfPass.h
namespace llvm{
Pass *createMyObfPass ();
Pass *createMyObfPass (bool);
}
2.在混淆源码cpp文件中,实现这两个创建Pass的函数:
//MyObfPass.cpp文件
struct MyObfPass : public ModulePass {
static char ID; // Pass identification, replacement for typeid
bool flag;
MyObfPass() : ModulePass(ID) {}
MyObfPass(bool flag) : ModulePass(ID) {this->flag = flag; MyObfPass();}
}
Pass *createMyObfPass() {
return new MyObfPass();
}
Pass *createMyObfPass(bool flag) {
return new MyObfPass(flag);
}
3.修改Obfuscation目录下的CMakeList.txt文件,添加源码:
add_llvm_library(LLVMObfuscation
CryptoUtils.cpp
Substitution.cpp
BogusControlFlow.cpp
Utils.cpp
SplitBasicBlocks.cpp
Flattening.cpp
MyObfPass.cpp #自定义的混淆源码
)
add_dependencies(LLVMObfuscation intrinsics_gen)
4.修改lib/Transform/IPO/PassManagerBuilder.cpp文件,添加启动参数识别:
//定义一个 bool 类型的参数选项,参数名myobf:
static cl::opt MyObf("myobf",cl::init(false),
cl::desc("Enable my Obfuscation pass!"));
//创建Pass并添加到Pass Manager
void PassManagerBuilder::populateModulePassManager(
legacy::PassManagerBase &MPM){
//....... 忽略其他的代码
MPM.add(createMyObfPass(MyObf));
}
遇到的问题:
I.一开始的时候,我是在其他目录定义我的混淆器,并且编写了LLVMBuild.txt文件,然后修改了
PassManagerBuilder.cpp 添加Pass,但是会遇到问题:
../../lib/libLLVMipo.a(PassManagerBuilder.cpp.obj):PassManagerBuilder.cpp:(.text+0x2043): undefined reference to `createMyObfPass(bool)'
collect2.exe: error: ld returned 1 exit status
tools\bugpoint\CMakeFiles\bugpoint.dir\build.make:242: recipe for target 'bin/bugpoint.exe' failed
mingw32-make[2]: *** [bin/bugpoint.exe] Error 1
CMakeFiles\Makefile2:20310: recipe for target 'tools/bugpoint/CMakeFiles/bugpoint.dir/all' failed
mingw32-make[1]: *** [tools/bugpoint/CMakeFiles/bugpoint.dir/all] Error 2
这个问题真的把我搞崩溃了,一晚上没睡好觉…… 明明所有东西都和OLLVM做的一样了,为啥不行呢?
一天以后,我用一个思路,找到了这个问题的原因…… 思路是:把OLLVM创建Pass的函数的头文件去掉,看下会出什么错。
结果:
P:\ollvm\ollvm\lib\Transforms\IPO\PassManagerBuilder.cpp: In member function 'void llvm::PassManagerBuilder::populateModulePassManager(llvm::legacy::PassManagerBase&)':
P:\ollvm\ollvm\lib\Transforms\IPO\PassManagerBuilder.cpp:434:32: error: 'createMyObfPass' was not declared in this scope
MPM.add(createMyObfPass(MyObf));
^
P:\ollvm\ollvm\lib\Transforms\IPO\PassManagerBuilder.cpp:436:39: error: 'createBogus' was not declared in this scope
MPM.add(createBogus(BogusControlFlow));
^
lib\Transforms\IPO\CMakeFiles\LLVMipo.dir\build.make:398: recipe for target 'lib/Transforms/IPO/CMakeFiles/LLVMipo.dir/PassManagerBuilder.cpp.obj' failed
提示的是 was not declared in this scope . 和之前的 undefined reference to `createMyObfPass(bool)'.
是不一样的! 一个是没有声明,另一个是没有定义的引用…… 诶! 都怪自己菜! 现在真的要记住这些区别了!
没有声明就是因为没有头文件声明函数,然后直接调用了函数,就会出 was not declared in this scope 。
没有定义的引用是啥意思呢? 个人理解是,这个函数声明了,但是没有找到对应的实现代码,导致“没有定义的引用”。
OK,那么怎么解决这个问题呢? 其实于PassManagerBuilder.cpp同一个目录下,有一个LLVMBuild.txt文件!
这个文件声明了当前目录的一些信息,其中包含了 引用库 的名字! 所以,只需要在自定义的混淆器目录下,
新建一个LLVMBuild.txt , 设置库的名字等信息,然后在 PassManagerBuilder.cpp 同目录下的LLVMBuild.txt文件
中,添加该库的名字即可! 真的被这个问题搞得很无奈……不过还好,自己最后还是搞出来了,欣慰……菜鸟……
最后附上一张使用截图,刚刚编译好,第一次使用!
再来一张混淆效果: