移植OLLVM混淆pass
文件
仅仅是学习混淆pass的编写,改动不是很大。将OLLVM的pass放进新版本(7.0.0 release)的LLVM源码下进行编译。
OLLVM的pass目录:OLLVM/lib/Transforms/Obfuscation
控制流平坦化:Flattening.cpp
虚假控制流:BogusControlFlow.cpp SplitBasicBlocks.cpp
指令替换:Substitution.cpp
对应头文件目录:OLLVM/include/llvm/Transforms/Obfuscation
这里以分割基本块的pass为例,将
SplitBasicBlocks.cpp SplitBasicBlocks.h
Utils.cpp Utils.h
CryptoUtils.h(include/llvm/)
复制到对应目录。
修改对应目录下的LLVMBuild.txt,subdirectories添加模块目录名称。修改对应目录下(Obfuscation目录下和Transforms目录下)的CMakeLists.txt,add_llvm_library添加模块名称和参与编译文件,add_dependencies添加模块名称。此时进行编译就可以看到build/lib目录下已经有libLLVMObfus.a(我把OLLVM里的Obfuscation改成了Obfus)。
但是此时运行opt,发现无-split
参数。
所以我们还需要修改IPO(Transforms/IPO),加入PassManager之后可以直接通过clang的参数使用pass了
PassManagerBuilder.cpp:
1 | +45 |
IPO的LLVMBuild.txt:+required_libraries=Obfus
ok,此时编译完成后,opt参数列表里就有了-split
。
代码
split PASS的实现:
保存Function的所有Block;
逐个处理Block,对非单一指令BB和不包含PHI指令的BB进行分割;
生成乱序表;
乱序处理Block中的指令;
具体处理单个指令的方法:
*BasicBlock->splitBasicBlock(BasicBlock::iterator,*BasicBlock->getName()+".splist")
位于OLLVM/lib/IR/BasicBlock.cpp
在指定的指令处将一个基本块一分为二。注意所有在指定指令前的指令会作为原始基本块的一部分,一个无条件分支会被添加到新的BB,余下的指令会被移到新的BB,包括旧BB的终止符。这会使迭代器无效。
注意这只针对一下格式合格的BB(有头有尾),并且指定的指令不允许是指令列表的最后一个(会导致生成一个退化的BB,而且内部带终止符)。新建一个BB,将指定指令移到新的BB,为新BB添加分支指令;
遍历新block的后继block,更新所有PHI节点信息,将原来从旧block出来的分支路径改为从新block出来。
判断PHI节点:
1 | for (BasicBlock::iterator II = Successor->begin(); |
这里添加几条打印信息代码:
1 | #++ 88 |
打印出对BB的分割点。
对比pass效果./clang -save-temps -S -mllvm -split test.c -o test.s
拿到的是pass处理的汇编文件,和中间文件。
对test.bc->test.ll->test.s(得到未经过pass处理的汇编文件),可自行对比(处理的BB会被添上“.split”)。