iOS混淆--OLLVM在iOS中的實(shí)踐(邏輯混淆)

OLLVM簡(jiǎn)介

OLLVM(Obfuscator-LLVM)是瑞士西北應(yīng)用科技大學(xué)安全實(shí)驗(yàn)室于2010年6月份發(fā)起的一個(gè)項(xiàng)目,該項(xiàng)目旨在提供一套開源的針對(duì)LLVM的代碼混淆工具,以增加對(duì)逆向工程的難度。后期轉(zhuǎn)向商業(yè)項(xiàng)目strong.protect。目前,OLLVM已經(jīng)支持LLVM-4.0版本。

LLVM是一個(gè)優(yōu)秀的編譯器框架,它也采用經(jīng)典的三段式設(shè)計(jì)。前端可以使用不同的編譯工具對(duì)代碼文件做詞法分析以形成抽象語法樹AST,然后將分析好的代碼轉(zhuǎn)換成LLVM的中間表示IR(intermediate representation);中間部分的優(yōu)化器只對(duì)中間表示IR操作,通過一系列的Pass對(duì)IR做優(yōu)化;后端負(fù)責(zé)將優(yōu)化好的IR解釋成對(duì)應(yīng)平臺(tái)的機(jī)器碼。LLVM的優(yōu)點(diǎn)在于,中間表示IR代碼編寫良好,而且不同的前端語言最終都轉(zhuǎn)換成同一種的IR。

LLVM IR 是LLVM的中間表示,優(yōu)化器就是對(duì)IR進(jìn)行操作的,具體的優(yōu)化操作由一些列的Pass來完成,當(dāng)前端生成初級(jí)IR后,Pass會(huì)依次對(duì)IR進(jìn)行處理,最終生成后端可用的IR。下圖可以說明這個(gè)過程:

OLLVM的混淆操作就是在中間表示IR層,通過編寫Pass來混淆IR,然后后端依據(jù)IR來生成的目標(biāo)代碼也就被混淆了。得益于LLVM的設(shè)計(jì),OLLVM適用LLVM支持的所有語言(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 iOS編譯環(huán)境搭建

以下,介紹OLLVM iOS環(huán)境的插件創(chuàng)建過程。
首先下載源碼,編譯OLLVM混淆器,這里采用LLVM的版本是4.0。下載編譯過程如下:

$ 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

下載的源碼里已經(jīng)包含了LLVM和Clang,編譯完成后,編譯好的二進(jìn)制程序都存在在build/bin目錄下。

依據(jù)github上的wiki,bin目錄下編譯好的工具鏈可以直接用來編譯混淆linux下的程序,就像我們常用的gcc那樣。若想使用OLLVM來混淆iOS程序,還需將bin目錄下的工具鏈整合進(jìn)Xcode插件中,具體步驟如下。

配置Xcode–新建Obfuscator插件

$ cd /Applications/Xcode.app/Contents/PlugIns/Xcode3Core.ideplugin/Contents/SharedSupport/Developer/Library/Xcode/Plug-ins/  
$ sudo cp -r Clang\ LLVM\ 1.0.xcplugin/ Obfuscator.xcplugin  
$ cd Obfuscator.xcplugin/Contents/  
$ sudo plutil -convert xml1 Info.plist  
$ sudo vim Info.plist

修改Info.plist中的對(duì)應(yīng)內(nèi)容:

<string>com.apple.compilers.clang</string> -> <string>com.apple.compilers.obfuscator</string>  
<string>Clang LLVM 1.0 Compiler Xcode Plug-in</string> -> <string>Obfuscator Xcode Plug-in</string>

修改Obfuscator.xcspec文件

$ sudo plutil -convert binary1 Info.plist  
$ cd Resources/  
$ sudo mv Clang\ LLVM\ 1.0.xcspec Obfuscator.xcspec  
$ sudo vim Obfuscator.xcspec

修改ExecPath的地址為當(dāng)前build/bin的地址(!重點(diǎn))

Identifier = "com.apple.compilers.llvm.clang.1_0"; -> Identifier = "com.apple.compilers.llvm.obfuscator.4_0";  
Name = "Apple LLVM 8.0"; -> Name = "Obfuscator 4.0";  
Description = "Apple LLVM 8.0 compiler"; -> Description = "Obfuscator 4.0";  
Vendor = Apple; -> Vendor = HEIG-VD;  
Version = "7.0"; -> Version = "4.0";  
ExecPath = "clang"; -> ExecPath = "/path/to/obfuscator_bin/clang";

修改 Obfuscator 4.0 Strings

$ cd English.lproj/  
$ sudo mv Apple\ LLVM\ 8.0.strings "Obfuscator 4.0.strings"  
$ sudo plutil -convert xml1 Obfuscator\ 4.0.strings  
$ sudo vim Obfuscator\ 4.0.strings

"Description" = "Apple LLVM 8.0 Compiler"; -> "Description" = "Obfuscator 4.0";  
"Name" = "Apple LLVM 8.0"; -> "Name" = "Obfuscator 4.0";  
"Vendor" = "Apple"; -> "Vendor" = "HEIG-VD";  
"Version" = "8.0"; -> "Version" = "4.0";

sudo plutil -convert binary1 Obfuscator\ 4.0.strings
現(xiàn)在,你可以打開Xcode在項(xiàng)目配置里來選擇新的編譯器,并且可以在C Flags或C++ Flags下添加混淆標(biāo)簽。

選擇編輯器.png

混淆標(biāo)簽.png

這樣配置完成后,就可以編譯項(xiàng)目生成混淆后的程序。

ollvm混淆使用

接下來使用以下demo介紹混淆功能的具體使用。

int main(){  
    int a = 1;  
    int b = 0;  
    int c = 0;  
    if(a > b){  
        a = 100;    
        b = 50;    
        c = a - b;    
        int d = a + b;    
        int e = a & b;    
        int f = a ^ b;    
        printf("c = %d\n",c);    
        printf("d = %d\n",d);    
        printf("e = %d\n",e);    
        printf("f = %d\n",f);    
        printf("a > b\n");    
    }else{  
        printf("a < b\n");    
    }  
    return 0;  
}

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)模式。

Instructions Substitution
指令替換模式主要是將正常的運(yùn)算操作(+,-,&,|等)替換成功能相等但表述更復(fù)雜的形式。比如,對(duì)于表達(dá)式 a = b + c,它的等價(jià)式可以有 a = – ( -b – c), a = b – (-c) 或 a = -(-b) + c 等,原表達(dá)式可以替換成任意相等式,或者通過隨機(jī)數(shù)在多個(gè)相等式中做選擇。SUB模式目前只支持整數(shù)運(yùn)算操作,支持 + , – , & , | 和 ^ 操作,還是比較局限的。編譯時(shí),使用 -mllvm -sub 參數(shù)即可。

-mllvm -sub: 啟用instructions substitution  
-mllvm -sub_loop=3: 對(duì)每個(gè)函數(shù)混淆3次,默認(rèn)1詞  !
1.png
2.png

Control Flow Flattening

控制流平展模式可以完全改變程序原本的控制流圖。如下示例代碼是簡(jiǎn)單的if-else分支語句,正常編譯后其控制流圖在IDA中下圖所示,是正常的if-else分支,使用 -mllvm -fla參數(shù)混淆后,在IDA中顯示的控制流圖如下:


3.png

4.png

經(jīng)FLA模式混淆后,程序的執(zhí)行流程已經(jīng)被打亂,出現(xiàn)許多代碼分支。通過仔細(xì)對(duì)比程序混淆前后,可以發(fā)現(xiàn)上圖著色區(qū)域是相對(duì)應(yīng)的,也就是說,F(xiàn)LA模式只去更改代碼分支,而不會(huì)對(duì)單個(gè)代碼塊做處理。

-mllvm -fla: 啟用control flow flattening
-mllvm -split: 啟用block切分,提升平展程度
-mllvm -split_num=3: 對(duì)每個(gè)block混淆3次,默認(rèn)1詞

Bogus Control Flow

控制流偽造模式也是對(duì)程序的控制流做操作,不同的是,BCF模式會(huì)在原代碼塊的前后隨機(jī)插入新的代碼塊,新插入的代碼塊不是確定的,然后新代碼塊再通過條件判斷跳轉(zhuǎn)到原代碼塊中。更要命地是,原代碼塊可能會(huì)被克隆并插入隨機(jī)的垃圾指令。這么多不確定性,就導(dǎo)致對(duì)同一份代碼多次做BCF模式的混淆時(shí),得到的是不同的混淆效果??梢?,BCF混淆模式還是很強(qiáng)大的,不同于FLA那種較確定的混淆模式。使用BCF模式編譯時(shí)配置參數(shù) -mllvm -bcf即可,此外,BCF模式還支持其它幾個(gè)參數(shù),下面參數(shù)與-mllvm -bcf參數(shù)配合使用。

-mllvm -bcf: 啟用 bogus control flow
-mllvm -bcf_loop=3: 對(duì)一個(gè)函數(shù)混淆3次,默認(rèn)1次
-mllvm -bcf_prob=40: 代碼塊被混淆的概率是40%,默認(rèn)30%

如上圖,下面兩個(gè)著色的代碼塊就是有上面兩個(gè)代碼塊克隆而來,而且其中被插入了一些垃圾指令,類似于這樣:

當(dāng)然,上述介紹的三種混淆模式可以搭配使用,同時(shí)使用三個(gè)參數(shù)混淆后,原本簡(jiǎn)單的if-else分支代碼將會(huì)變得異常復(fù)雜,這無疑給逆向分析增加巨大的難度。

Functions annotations

有的時(shí)候,由于效率或其他原因的考慮,我們只想給指定的函數(shù)混淆或不混淆該函數(shù),OLLVM也提供了對(duì)這一特性的支持,你只需要給對(duì)應(yīng)的函數(shù)添加attributes即可。比如,想對(duì)函數(shù)foo()使用fla混淆,只需要給函數(shù)foo()增加fla屬性即可。

int foo() __attribute((__annotate__(("fla"))));
int foo() {
   return 2;
}

你可以給函數(shù)添加一個(gè)或多個(gè)注釋。如果你不想混淆某個(gè)函數(shù),你可以使用否定標(biāo)簽。例如如果不想對(duì)func()函數(shù)使用bcf屬性,那標(biāo)記為“nobcf”即可。

錯(cuò)誤處理

1.編譯時(shí)報(bào)錯(cuò),提示信息如下:

clang-3.6: error: unknown argument: '-gmodules'
clang-3.6: error: unknown argument: '-fembed-bitcode-marker'
Command /Users/dream/ollvm/build/bin/clang failed with exit code 1

在Build Settings中搜索并修改:
-gmodules: Obfuscator 4.0 - Code Generation: Generate Debug Symbols: 原來yes,改成no
-fembed-bitcode-marker: Build Option: Enable Bitcode: 原來yes,改成no

你可以在該 git地址下找到最新的插件和build編譯器文件,該編譯器所使用的Xcode版本是8.3.3。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 原文鏈接:http://fighting300.com.... OLLVM簡(jiǎn)介 OLLVM(Obfuscator-...
    fighting300閱讀 21,231評(píng)論 65 35
  • 前言 相信大部分的第一感覺就是覺得jni居然也可以混淆???!是的,在沒有接觸這塊的時(shí)候我和大家是一樣的懵逼,居然還...
    海闊sun天空閱讀 19,854評(píng)論 35 20
  • 項(xiàng)目原因研究Android的So庫代碼混淆,增加IDA工具查看的復(fù)雜度。簡(jiǎn)單接觸了ollvm 混淆組件。網(wǎng)上查看了...
    小子不壞_sprite閱讀 5,070評(píng)論 2 9
  • 1. 加固的緣由? 我們都知道,在越獄機(jī)型上,如果程序的可執(zhí)行文件被獲取到,就可以通過一些逆向工具來反編譯我們的程...
    純情_小火雞閱讀 4,001評(píng)論 1 8
  • 簡(jiǎn)介 OLLVM(Obfuscator-LLVM)是瑞士西北應(yīng)用科技大學(xué)安全實(shí)驗(yàn)室于2010年6月份發(fā)起的一個(gè)項(xiàng)目...
    heroims閱讀 52,776評(píng)論 42 83

友情鏈接更多精彩內(nèi)容