代码混淆android.mk,利用ollvm进行代码混淆
OLLVM簡(jiǎn)介
OLLVM(Obfuscator-LLVM)是瑞士西北應(yīng)用科技大學(xué)于2010年6月份發(fā)起的一個(gè)項(xiàng)目,該項(xiàng)目旨在提供一套開(kāi)源的針對(duì)LLVM的代碼混淆工具,以增加對(duì)逆向工程的難度。
OLLVM是基于LLVM實(shí)現(xiàn)的,LLVM是一個(gè)編譯器框架,它也采用經(jīng)典的三段式設(shè)計(jì)。前端可以使用不同的編譯工具對(duì)代碼文件做詞法分析以形成抽象語(yǔ)法樹(shù)AST,然后將分析好的代碼轉(zhuǎn)換成LLVM的中間表示IR(intermediate representation);中間部分的優(yōu)化器只對(duì)中間表示IR操作,通過(guò)一系列的Pass對(duì)IR做優(yōu)化;后端負(fù)責(zé)將優(yōu)化好的IR解釋成對(duì)應(yīng)平臺(tái)的機(jī)器碼。LLVM的優(yōu)點(diǎn)在于,不同的前端語(yǔ)言最終都轉(zhuǎn)換成同一種的IR。
OLLVM的混淆操作就是在中間表示IR層,通過(guò)編寫(xiě)Pass來(lái)混淆IR,然后后端依據(jù)IR來(lái)生成的目標(biāo)代碼也就被混淆了。得益于LLVM的設(shè)計(jì),OLLVM適用LLVM支持的所有語(yǔ)言(C, C++, Objective-C, Ada 和 Fortran)和目標(biāo)平臺(tái)(x86, x86-64, PowerPC, PowerPC-64, ARM, Thumb, SPARC, Alpha, CellSPU, MIPS, MSP430, SystemZ, 和 XCore)。
OLLVM的幾種混淆方式
OLLVM默認(rèn)支持 -fla -sub -bcf 三個(gè)混淆參數(shù),這三個(gè)參數(shù)可以單獨(dú)使用,也可以配合著使用。-fla 參數(shù)表示使用控制流平展(Control Flow Flattening)模式,-sub參數(shù)表示使用指令替換(Instructions Substitution)模式,-bcf參數(shù)表示使用控制流偽造(Bogus Control Flow)模式
-sub instruction substitution(指令替換)
-fla control flow flattening(控制流平坦化)
-bcf bogus control flow(控制流偽造)
此外,OLLVM支持對(duì)單個(gè)函數(shù)進(jìn)行混淆,即Functions annotations模式
以下分別介紹這幾種方式并舉例說(shuō)明:
instruction substitution(指令替換)
指令替換是一種比較簡(jiǎn)單的混淆方式,OLLVM將一些簡(jiǎn)單的運(yùn)算復(fù)雜化,但這種方式容易被代碼優(yōu)化給去除,目前OLLVM只實(shí)現(xiàn)對(duì)整數(shù)運(yùn)算的混淆。
加法混淆
例如 a = b + c 可以被混淆為:
1
2
3
41. a = b - (-c)
2. a = -(-b + (-c))
3. r = rand (); a = b + r; a = a + c; a = a - r
4. r = rand (); a = b - r; a = a + b; a = a + r
減法混淆
例如 a = b-c 可以被混淆為:
1
2
31. a = b + (-c)
2. r = rand (); a = b + r; a = a - c; a = a - r
3. r = rand (); a = b - r; a = a - c; a = a + r
AND運(yùn)算混淆
a = b & c => a = (b ^ ~c) & b
OR運(yùn)算混淆
a = b | c => a = (b & c) | (b ^ c)
XOR運(yùn)算混淆
a = a ^ b => a = (~a & b) | (a & ~b)
如果一種運(yùn)算對(duì)應(yīng)多種混淆方式,OLLVM將會(huì)隨機(jī)選擇一種,以下為使用OLLVM進(jìn)行指令替換后的前后對(duì)比:
源碼:1
2
3
4
5int test(int a,int b)
{
int c = a + b;
return c+2;
}
sub前:
sub后
分析匯編指令得出,a+b+2 運(yùn)算變成了 -(-b-(a+2))
control flow flattening(控制流平坦化)
control flow flattening(控制流平坦化)通過(guò)多個(gè)case-swich結(jié)構(gòu)將程序的控制流變成扁平形狀,打破原有的邏輯結(jié)構(gòu),增加逆向的難度。
例如對(duì)于以下代碼:
1
2
3
4
5
6
7
8
9#include
int main(int argc, char** argv) {
int a = atoi(argv[1]);
if(a == 0)
return 1;
else
return 10;
return 0;
}
OLLVM將把它變?yōu)槿缦陆Y(jié)構(gòu):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#include
int main(int argc, char** argv) {
int a = atoi(argv[1]);
int b = 0;
while(1) {
switch(b) {
case 0:
if(a == 0)
b = 1;
else
b = 2;
break;
case 1:
return 1;
case 2:
return 10;
default:
break;
}
}
return 0;
}
從代碼中可以看到,OLLVM將源代碼分割為幾個(gè)基本塊,并放在一個(gè)while循環(huán)結(jié)構(gòu)中無(wú)線循環(huán),程序的流程由變量b控制。
以下是使用OLLVM進(jìn)行控制混淆后的前后對(duì)比:
源碼1
2
3
4
5
6
7
8
9#include
int main(int argc, char** argv) {
int a = atoi(argv[1]);
if(a == 0)
return 1;
else
return 10;
return 0;
}
fla之前:
fla之后:
F5之后的代碼:
由此可見(jiàn),fla之后的控制流比較復(fù)雜,通過(guò)分析fla之后的代碼,我們發(fā)現(xiàn)代碼中的result僅僅受v7的影響,但分析起來(lái)著實(shí)費(fèi)力。
bogus control flow(控制流偽造)
bogus control flow通過(guò)在源程序的控制流中添加一些基本塊,這些基本塊僅僅起了連接作用,并不影響實(shí)際的執(zhí)行邏輯。
以下為使用OLLVM進(jìn)行控制流偽造后的對(duì)比:
源碼
1
2
3
4
5
6
7
8
9#include
int main(int argc, char** argv) {
int a = atoi(argv[1]);
if(a == 0)
return 1;
else
return 10;
return 0;
}
bcf之前:

bcf之后:

F5之后的代碼:

由此看出,bcf的方式在程序中增加了一個(gè)代碼塊,這個(gè)代碼塊對(duì)函數(shù)返回值沒(méi)有任何影響,但對(duì)于逆向人員來(lái)說(shuō),增加了其逆向分析的無(wú)用功。
Functions annotations
有時(shí)候?yàn)榱颂岣咝?#xff0c;開(kāi)發(fā)者僅需要對(duì)指定的函數(shù)進(jìn)行混淆,OLLVM的Functions annotations模式支持對(duì)單個(gè)函數(shù)進(jìn)行混淆。比如,想對(duì)函數(shù)func()使用bcf混淆,只需要給函數(shù)func()增加bcf屬性即可。
1int func() __attribute((__annotate__(("bcf"))));
OLLVM的fla,sub和bcf三個(gè)屬性可以搭配使用,只需要添加對(duì)應(yīng)的編譯選項(xiàng)即可。
利用OLLVM進(jìn)行Android native代碼混淆
1.下載并編譯ollvm1
2
3
4
5$ git clone -b llvm-4.0 https://github.com/obfuscator-llvm/obfuscator.git
$ mkdir build
$ cd build
$ cmake -DCMAKE_BUILD_TYPE=Release ../obfuscator/
$ make -j7
2.配置NDK以支持ollvm新建編譯鏈
在 android-ndk-r14b/toolchains 下新建目錄 ollvm-4.0/prebuilt/darwin-x86_64(我的環(huán)境是mac),把前一步編譯生成的結(jié)果拷貝到此目錄下(主要是bin和lib)
配置編譯鏈
在 android-ndk-r14b/build/core/toolchains 目錄下,新建目錄 arm-linux-androideabi-clang-ollvm4.0,拷貝目錄 arm-linux-androideabi-clang 下的文件 config.mk 與 setup.mk 到 arm-linux-androideabi-clang-ollvm4.0 中,修改setup.mk文件。1
2
3
4
5
6
7
8
9############################ 原始配置 ############################
#LLVM_TOOLCHAIN_PREBUILT_ROOT := $(call get-toolchain-root,llvm)
#LLVM_TOOLCHAIN_PREFIX := $(LLVM_TOOLCHAIN_PREBUILT_ROOT)/bin/
#################################################################
############################ 修改后 #############################
OLLVM_NAME := ollvm-4.0
LLVM_TOOLCHAIN_PREBUILT_ROOT := $(call get-toolchain-root,$(OLLVM_NAME))
LLVM_TOOLCHAIN_PREFIX := $(LLVM_TOOLCHAIN_PREBUILT_ROOT)/bin/
#其他配置不做修改
3.使用ollvm進(jìn)行編譯
使用 ollvm 進(jìn)行 ndk 的編譯需要對(duì) Application.mk 和 Android.mk 文件做相應(yīng)的修改。
Android.mk 中添加混淆編譯參數(shù):
1LOCAL_CFLAGS += -mllvm -sub -mllvm -bcf -mllvm -fla
Application.mk 中配置 NDK_TOOLCHAIN_VERSION
1
2APP_ABI := x86 armeabi-v7a x86_64 arm64-v8a armeabi mips64
NDK_TOOLCHAIN_VERSION := clang-ollvm-4.0
參考資料:
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的代码混淆android.mk,利用ollvm进行代码混淆的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 潍坊经贸每年单招计算机的成绩,2018潍
- 下一篇: ue4插件导入导出_Blender到UE