一、LLVM是什麼
LLVM最初是Low Level Virtual Machine的縮寫,定位是一個,但是是比較底層的虛擬機。然而LLVM本身並不是一個完整的編譯器,LLVM是一個編譯器基礎架構(infrastructure),把很多編譯器需要的功能以可調用的模塊形式實現出來幷包裝成庫,供其他編譯器實現者可以根據自己的需要選擇使用或者擴展。主要聚焦於編譯器後端功能,如代碼生成、代碼優化、JIT等。
編譯器前端和後端就是編譯器經典的三段式設計中的組成。如下圖所示
LLVM是一個優秀的編譯器框架,它也採用經典的三段式設計。前端可以使用不同的編譯工具對代碼文件做詞法分析以形成抽象語法樹AST,然後將分析好的代碼轉換成LLVM的中間表示IR(intermediate representation);中間部分的優化器只對中間表示IR操作,通過一系列的Pass對IR做優化;後端負責將優化好的IR解釋成對應平臺的機器碼。LLVM的優點在於,中間表示IR代碼編寫良好,而且不同的前端語言最終都轉換成同一種的IR。如下圖所示
從源碼角度分析,如果你下載LLVM的代碼,那麼它就是一個IR到ARM/機器碼的編譯器。比如bin/opt就是對IR的優化器,bin/llc就是IR->ASM的翻譯,bin/llvm-mc就是彙編器。如果你再從http://llvm.org下載Clang,那麼就有了C->IR的翻譯以及完整的編譯器Driver。GDB是GNU的調試器。只要編譯器支持DWARF格式,就可以用GDB調試。
LLVM IR是LLVM的中間表示,優化器就是對IR進行操作的,具體的優化操作由一些列的Pass來完成,當前端生成初級IR後,Pass會依次對IR進行處理,最終生成後端可用的IR。具體過程見第二部分介紹Clang與LLVM關係。
三、Clang與LLVM關係
LLVM與Clang是C/C++編譯器套件。對於整個LLVM的框架來說,包含了Clang,因爲Clang是LLVM的框架的一部分,是它的一個C/C++的前端(第一部分有講到)。Clang使用了LLVM中的一些功能,目前所知道的主要就是對中間格式代碼的優化,或許還有一部分生成代碼的功能。從源代碼角度來講,Clang和LLVM的源碼位置可以看出,Clang是基於LLVM的一個工具。而從功能的角度來說, LLVM可以認爲是一個編譯器的後端,而Clang是一個編譯器的前端,它們的關係就更加的明瞭了,一個編譯器前端想要程序最終變成可執行文件,是缺少不了對編譯器後端的介紹的。
三、OLLVM是什麼
OLLVM(Obfuscator-LLVM)是瑞士西北應用科技大學安全實驗室於2010年6月份發起的一個項目,這個項目的目標是提供一個LLVM編譯套件的開源分支,能夠通過代碼混淆和防篡改,增加對逆向工程的難度,提供更高的軟件安全性。目前,OLLVM已經支持LLVM-4.0.1版本。
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)
Linux下首先下載源碼,編譯OLLVM混淆器,方法如下
用cmake編譯的過程中,可能會出現如下問題
CMake Error at cmake/modules/AddLLVM.cmake:1163 (add_custom_target):
add_custom_target cannot create target "check-llvm-bindings-ocaml" because
another target with the same name already exists. The existing target is a
custom target created in source directory
"/home/xxx/obfuscator/test". See documentation
for policy CMP0002 for more details.
Call Stack (most recent call first):
cmake/modules/AddLLVM.cmake:1226 (add_lit_target)
test/CMakeLists.txt:150 (add_lit_testsuites)
修改爲以下命令再嘗試編譯可順利通過
cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_INCLUDE_TESTS=OFF ../fuscator/
下載的源碼裏已經包含了LLVM和Clang,編譯完成後,編譯好的二進制程序都存放在build/bin目錄下。
使用Obfuscator-LLVM最簡單的方法是將標誌(第一部分提到的PASS)傳遞給Clang的LLVM後端。 當前可用的標誌是:
1. -fla 控制流扁平化的PASS參數
2. -sub指令替換的PASS參數
3. -bcf虛假控制流的PASS參數
具體使用過程如下:
假設有一個命名爲test.c的源文件,如果要使用工具,在終端輸入如下命令
如果一次操作傳遞不止一個PASS,也可以這樣輸入命令
在多源文件項目中可以通過這樣修改MakeFile來使用OLLVM工具