时时勤拂拭,勿使惹尘埃

TOC

Categories

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



https://github.com/obfuscator-llvm/obfuscator/commit/58487c725b15a35e6267b425ddb9e34eddc03327#diff-95c3a11f8ae9cf683bdec9bc4571391a
注:截图中少删了}符号

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
...

(待补充) 

1 条评论: