LLVM(二)obfuscator混淆工具移植llvm-10.0
参考:
Deobfuscation: recovering an OLLVM-protected program
OLLVM代码混淆移植与使用
0x0 OLLVM简介
OLLVM(Obfuscator-LLVM)是瑞士西北应用科技大学于2010年6月份发起的一个项目,该项目旨在提供一套开源的针对LLVM的代码混淆工具,以增加对逆向工程的难度。
OLLVM是基于LLVM实现的,LLVM是一个编译器框架,它也采用经典的三段式设计。前端可以使用不同的编译工具对代码文件做词法分析以形成抽象语法树AST,然后将分析好的代码转换成LLVM的中间表示IR(intermediate representation);中间部分的优化器只对中间表示IR操作,通过一系列的Pass对IR做优化;后端负责将优化好的IR解释成对应平台的机器码。LLVM的优点在于,不同的前端语言最终都转换成同一种的IR。
OLLVM的混淆操作就是在中间表示IR层,通过编写Pass来混淆IR,然后后端依据IR来生成的目标代码也就被混淆了。得益于LLVM的设计,OLLVM适用LLVM支持的所有语言(C, C++, Objective-C, Ada 和 Fortran)和目标平台(x86, x86-64, PowerPC, PowerPC-64, ARM, Thumb, SPARC, Alpha, CellSPU, MIPS, MSP430, SystemZ, 和 XCore)。
0x1 移植到llvm-10.0
OLLVM项目的编译,需要把OLLVM的代码拷贝到LLVM项目中,与LLVM项目一起编译。
移植好的项目:https://github.com/gandalf4a/obfuscator_llvm10.0
0x11 下载源码
OLLVM源码为:https://github.com/obfuscator-llvm/obfuscator
不过开源版本仅更新到llvm的4.0,2017年开始就不再更新了。
但llvm已经在2020.3.24更新到了10.0.0,下载地址为:
https://releases.llvm.org/
移植ollvm之前,可以先尝试编译一下llvm,确定llvm源码是否能编译通过,也可以帮助在之后的ollvm移植中修改错误,参考LLVM(一)安装&编译
# 下载llvm源码
$ wget https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/llvm-10.0.0.src.tar.xz
$ tar xvf llvm-10.0.0.src.tar.xz
$ mv llvm-10.0.0.src llvm
# 下载clang源码,clang需要放在llvm项目的tools目录下
$ wget https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang-10.0.0.src.tar.xz
$ tar xvf clang-10.0.0.src.tar.xz
$ mv clang-10.0.0.src llvm/tools/clang
# 下载ollvm最新分之代码,源码只支持到llvm-4.0
$ git clone -b llvm-4.0 https://github.com/obfuscator-llvm/obfuscator.git
# obfuscator 项目是包含了完整llvm项目的,ollvm实际代码只有以下三个部分,需要拷贝到llvm-10.0对应目录下
$ cp -r ./obfuscator/include/llvm/Transforms/Obfuscation ./llvm/include/llvm/Transforms/Obfuscation
$ cp -r ./obfuscator/lib/Transforms/Obfuscation ./llvm/lib/Transforms/Obfuscation
$ cp ./obfuscator/include/llvm/CryptoUtils.h ./llvm/include/llvm/CryptoUtils.h
0x12 修改编译配置文件
文件复制完成后,还需要修改cmake等编译配置文件,详情参考ollvm与llvm的修改,主要为以下几个文件:
https://github.com/obfuscator-llvm/obfuscator/commit/adbe45b199d4e42400ee646ad62a781f34b07860
0x13 编译ollvm
由于在解压后的llvm项目文件夹内部编译会失败,所以需要在llvm项目外部新建一个文件夹再进行编译:
$ mkdir build
$ cd build
$ cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_CREATE_XCODE_TOOLCHAIN=ON ../llvm
$ make -j7
编译成功后会在build/bin
目录下生成clang
等可执行文件:
ls -al build_ollvm/bin
total 2625312
drwxr-xr-x 105 nirva staff 3360 Aug 4 21:48 .
drwxr-xr-x 27 nirva staff 864 Aug 4 19:34 ..
-rwxr-xr-x 1 nirva staff 620432 Aug 4 19:37 FileCheck
-rwxr-xr-x 1 nirva staff 24114228 Aug 4 21:25 arcmt-test
-rwxr-xr-x 1 nirva staff 66196376 Aug 4 21:48 bugpoint
-rwxr-xr-x 1 nirva staff 17852 Aug 4 21:48 c-arcmt-test
-rwxr-xr-x 1 nirva staff 26720068 Aug 4 21:48 c-index-test
lrwxr-xr-x 1 nirva staff 8 Aug 4 21:47 clang -> clang-10
lrwxr-xr-x 1 nirva staff 8 Aug 4 21:47 clang++ -> clang-10
-rwxr-xr-x 1 nirva staff 103971420 Aug 4 21:47 clang-10
-rwxr-xr-x 1 nirva staff 81577696 Aug 4 21:47 clang-check
lrwxr-xr-x 1 nirva staff 8 Aug 4 21:47 clang-cl -> clang-10
lrwxr-xr-x 1 nirva staff 8 Aug 4 21:47 clang-cpp -> clang-10
-rwxr-xr-x 1 nirva staff 24002768 Aug 4 21:25 clang-diff
-rwxr-xr-x 1 nirva staff 23743920 Aug 4 21:47 clang-extdef-mapping
-rwxr-xr-x 1 nirva staff 2383664 Aug 4 21:25 clang-format
-rwxr-xr-x 1 nirva staff 29467636 Aug 4 21:34 clang-import-test
-rwxr-xr-x 1 nirva staff 3406668 Aug 4 21:14 clang-offload-bundler
-rwxr-xr-x 1 nirva staff 2113732 Aug 4 21:24 clang-offload-wrapper
0x2 移植编译中遇到的问题
0x21 未定义TerminatorInst
类型
../llvm/lib/Transforms/Obfuscation/BogusControlFlow.cpp:531:11: error:
unknown type name 'TerminatorInst'
TerminatorInst * tbb= fi->getTerminator();
^
1 error generated.
未定义TerminatorInst
类型,根据上下文改为Instruction
0x22 未定义createLowerSwitchPass
../llvm/lib/Transforms/Obfuscation/Flattening.cpp:68:25: error:
use of undeclared identifier 'createLowerSwitchPass'; did you mean
'createLoopUnswitchPass'?
FunctionPass *lower = createLowerSwitchPass();
^~~~~~~~~~~~~~~~~~~~~
createLoopUnswitchPass
/Users/nirva/Desktop/source/llvm/llvm/include/llvm/Transforms/Scalar.h:179:7: note:
'createLoopUnswitchPass' declared here
Pass *createLoopUnswitchPass(bool OptimizeForSize = false,
^
../llvm/lib/Transforms/Obfuscation/Flattening.cpp:68:17: error:
cannot initialize a variable of type 'llvm::FunctionPass *' with an rvalue of type
'llvm::Pass *'
FunctionPass *lower = createLowerSwitchPass();
^ ~~~~~~~~~~~~~~~~~~~~~~~
createLowerSwitchPass是llvm的组件,但CMake配置文件中少链接了组件,导致在ld链接时,找不到函数的定义
搜索本地文件,找../llvm/lib/Transforms/Utils/LowerSwitch.cpp
中定义如下:
// createLowerSwitchPass - Interface to this file...
FunctionPass *llvm::createLowerSwitchPass() {
return new LowerSwitch();
}
对应头文件路径:../llvm/include/llvm/Transforms/Utils.h
故在../llvm/lib/Transforms/Obfuscation/Flattening.cpp
文件头中添加如下引用即可#include "llvm/Transforms/Utils.h"
0x23 constExpr
中间缺少空格
build/tools/clang/include/clang/AST/AbstractTypeWriter.inc:133:5: error:
use of undeclared identifier 'constExpr'; did you mean 'constexpr'?
constExpr* size = ( node->getSizeExpr() );
^~~~~~~~~
constexpr
这是编译时代码拼接的问题,constExpr
中间缺少空格,正确应该是const Expr
,类似缺少空格的问题还有很多
0x3 fla模式修复
通过上述方式移植的ollvm,编译完成后,使用ollvm进行混淆,其中bcf和sub模式都能正常使用,但fla模式编译文件会出现如下错误:
...
Stack dump:
0. Program arguments: ./build_ollvm/bin/clang-10 -cc1 -triple x86_64-apple-macosx10.15.0 -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -discard-value-names -main-file-name hello.c -mrelocation-model pic -pic-level 2 -mthread-model posix -mframe-pointer=all -fno-rounding-math -masm-verbose -munwind-tables -target-sdk-version=10.15.6 -target-cpu penryn -dwarf-column-info -debugger-tuning=lldb -target-linker-version 519 -v -resource-dir ./build_ollvm/lib/clang/10.0.0 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk -internal-isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/local/include -internal-isystem ./build_ollvm/lib/clang/10.0.0/include -internal-externc-isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include -fdebug-compilation-dir /Users/nirva/Desktop/source/llvm -ferror-limit 19 -fmessage-length 67 -stack-protector 1 -fblocks -fencode-extended-block-signature -fregister-global-dtors-with-atexit -fgnuc-version=4.2.1 -fobjc-runtime=macosx-10.15.0 -fmax-type-align=16 -fdiagnostics-show-option -fcolor-diagnostics -mllvm -fla -o /var/folders/vv/7tccm7_s0h526y9b54xzs5lc0000gq/T/hello-478ba5.o -x c hello.c
1. <eof> parser at end of file
2. Per-module optimization passes
3. Running pass 'Function Pass Manager' on module 'hello.c'.
4. Running pass 'Call graph flattening' on function '@main'
0 clang-10 0x0000000109c9f2e8 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 40
1 clang-10 0x0000000109c9e158 llvm::sys::RunSignalHandlers() + 248
2 clang-10 0x0000000109c9f8fd SignalHandler(int) + 285
3 libsystem_platform.dylib 0x00007fff73b675fd _sigtramp + 29
4 libsystem_platform.dylib 0xffffffffffffffff _sigtramp + 18446603338574826015
5 clang-10 0x000000010aa9c58e (anonymous namespace)::Flattening::runOnFunction(llvm::Function&) + 222
...
clang-10: error: unable to execute command: Segmentation fault: 11
clang-10: error: clang frontend command failed due to signal (use -v to see invocation)
Obfuscator-LLVM clang version 10.0.0
Target: x86_64-apple-darwin19.6.0
...
(待补充)
第三点fla模式修复要怎么修复
回复删除