簡介
OLLVM(Obfuscator-LLVM)是瑞士西北應用科技大學安全實驗室于2010年6月份發(fā)起的一個項目,該項目旨在提供一套開源的針對LLVM的代碼混淆工具,以增加對逆向工程的難度。github上地址是https://github.com/obfuscator-llvm/obfuscator赁咙,只不過僅更新到llvm的4.0钮莲,2017年開始就沒在更新免钻。
移植
OLLVM如果自己想拿最新版的LLVM和Clang進行移植功能其實也并不是很難姆怪,整理一下其實改動很小肥卡,接下來將會講一下移植的方法。
個人整理
先放一下個人移植好的版本地址https://github.com/heroims/obfuscator.git,個人fork原版后又加入了llvm5.0当宴,6.0捌年,7.0以及swift-llvm5.0的版本荠藤,應該能滿足大部分需求了,如果有新版本下面的講解,各位也可以自己動手去下載自己需要的llvm和clang進行移植。git上的提交每次都很獨立如下圖碍扔,方便各位cherry-pick溶耘。
下載LLVM
llvm地址:https://github.com/llvm-mirror
swift-llvm地址:https://github.com/apple
大家可以從上面的地址下載最新的自己需要的llvm和clang
#下載llvm源碼
wget https://codeload.github.com/llvm-mirror/llvm/zip/release_70
unzip llvm-release_70.zip
mv llvm-release_70 llvm
#下載clang源碼
wget https://codeload.github.com/llvm-mirror/clang/zip/release_70
unzip clang-release_70.zip
mv clang-release_70 llvm/tools/clang
添加混淆代碼
如果用git的話只需要執(zhí)行git cherry-pick xxxx
把xxxx換成對應的我的版本上的提交哈希填上即可。極度推薦用git搞定。
如果手動一點點加的話,第一步就是把我改過的OLLVM文件夾里/include/llvm/Transforms/Obfuscation
和/lib/Transforms/Obfuscation
移動到剛才下載好的llvm源碼文件夾相同的位置寥粹。
git clone https://github.com/heroims/obfuscator.git
cd obfuscator
git checkout llvm-7.0
cp include/llvm/Transforms/Obfuscation llvm/include/llvm/Transforms/Obfuscation
cp lib/Transforms/Obfuscation llvm/lib/Transforms/Obfuscation
然后手動修改8個文件如下:
編譯
mkdir build
cd build
#如果不想跑測試用例加上-DLLVM_INCLUDE_TESTS=OFF
cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_CREATE_XCODE_TOOLCHAIN=ON ../obfuscator/
make -j7
使用
這里原版提供了3種混淆方式分別是控制流扁平化,指令替換,虛假控制流程,用起來都是加cflags的方式。下面簡單說下這幾種模式。
控制流扁平化
這個模式主要是把一些if-else語句垮刹,嵌套成do-while語句
-mllvm -fla:激活控制流扁平化
-mllvm -split:激活基本塊分割契耿。在一起使用時改善展平撵术。
-mllvm -split_num=3:如果激活了傳遞架专,則在每個基本塊上應用3次。默認值:1
指令替換
這個模式主要用功能上等效但更復雜的指令序列替換標準二元運算符(+ , – , & , | 和 ^)
-mllvm -sub:激活指令替換
-mllvm -sub_loop=3:如果激活了傳遞怔鳖,則在函數(shù)上應用3次肩刃。默認值:1
虛假控制流程
這個模式主要嵌套幾層判斷邏輯,一個簡單的運算都會在外面包幾層if-else,所以這個模式加上編譯速度會慢很多因為要做幾層假的邏輯包裹真正有用的代碼遣钳。
另外說一下這個模式編譯的時候要浪費相當長時間包哪幾層不是鬧得蒋畜!
-mllvm -bcf:激活虛假控制流程
-mllvm -bcf_loop=3:如果激活了傳遞佣渴,則在函數(shù)上應用3次砂竖。默認值:1
-mllvm -bcf_prob=40:如果激活了傳遞锋八,基本塊將以40%的概率進行模糊處理淤袜。默認值:30
上面說完模式下面講一下幾種使用方式
直接用二進制文件
直接使用編譯的二進制文件build/bin/clang test.c -o test -mllvm -sub -mllvm -fla -mllvm -bcf
NDK集成
這里分為工具鏈的制作和項目里的配置。
制作Toolchains
這里以修改最新的ndk r18為例铡羡,老的ndk版本比這更容易都在ndk-bundle/toolchains里放著需要修改的文件积蔚。
#復制ndk的toolschain里的llvm
cp -r Android/sdk/ndk/xx.x.xxxxxx/toolchains/llvm Android/sdk/ndk/xx.x.xxxxxx/toolchains/ollvm
#刪除prebuilt文件夾下的文件夾的bin和lib64,prebuilt文件夾下根據(jù)系統(tǒng)不同命名也不同
rm -rf Android/sdk/ndk/xx.x.xxxxxx/toolchains/ollvm/prebuilt/darwin-x86_64/bin
rm -rf Android/sdk/ndk/xx.x.xxxxxx/toolchains/ollvm/prebuilt/darwin-x86_64/lib64
#把我們之前編譯好的ollvm下的bin和lib移到我們剛才刪除bin和lib64的目錄下
mv build/bin Android/sdk/ndk/xx.x.xxxxxx/toolchains/ollvm/prebuilt/darwin-x86_64/bin
mv build/lib Android/sdk/ndk/xx.x.xxxxxx/toolchains/ollvm/prebuilt/darwin-x86_64/lib64
#復制Android/sdk/ndk/xx.x.xxxxxx?/?build?/?core?/?toolchains的文件夾烦周,這里根據(jù)自己對CPU架構(gòu)的需求自己復制然后修改
cp -r Android/sdk/ndk/xx.x.xxxxxx?/?build?/?core?/?toolchains/aarch64-linux-android-clang? Android/sdk/ndk/xx.x.xxxxxx/?build?/?core?/?toolchains/aarch64-linux-android-clang-ollvm
cp -r Android/sdk/ndk/xx.x.xxxxxx/?build?/?core?/?toolchains/arm-linux-androideabi-clang? Android/sdk/ndk/xx.x.xxxxxx/build?/?core?/?toolchains/arm-linux-androideabi-clang-ollvm
cp -r Android/sdk/ndk/xx.x.xxxxxx/?build?/?core?/?toolchains/x86_64-clang Android/sdk/ndk/xx.x.xxxxxx/build?/?core?/?toolchains/x86_64-clang-ollvm
cp -r Android/sdk/ndk/xx.x.xxxxxx/?build?/?core?/?toolchains/x86-clang-clang? Android/sdk/ndk/xx.x.xxxxxx/build?/?core?/?toolchains/x86-clang-ollvm
最后把xxxxxxxxx-ollvm里的setup.mk文件進行修改
TOOLCHAIN_NAME := ollvm
TOOLCHAIN_ROOT := $(call get-toolchain-root,$(TOOLCHAIN_NAME))
TOOLCHAIN_PREFIX := $(TOOLCHAIN_ROOT)/bin
config.mk里是CPU架構(gòu),剛才是復制出來的所以不用修改尽爆,但如果要添加其他的自定義架構(gòu)需要嚴格按照格式規(guī)范命名最初的文件夾,如mips的需要添加文件夾mipsel-linux-android-clang-ollvm读慎,setup.mk和剛才的修改一樣即可漱贱。
修改Android/sdk/ndk/xx.x.xxxxxx/?build?/?core?/?toolchains/setup-toolchain.mk里
ifneq ($(words $(TARGET_TOOLCHAIN_LIST)),1)
$(call __ndk_error,Expected two items in TARGET_TOOLCHAIN_LIST, \
found "$(TARGET_TOOLCHAIN_LIST)")
endif
改為
ifneq ($(words $(TARGET_TOOLCHAIN_LIST)),2)
$(call __ndk_error,Expected two items in TARGET_TOOLCHAIN_LIST, \
found "$(TARGET_TOOLCHAIN_LIST)")
endif
項目中配置
到了項目里還需要修改兩個文件:
在Android.mk 中添加混淆編譯參數(shù)
LOCAL_CFLAGS += -mllvm -sub -mllvm -bcf -mllvm -fla
Application.mk中配置NDK_TOOLCHAIN_VERSION
#根據(jù)需要添加
APP_ABI := x86 armeabi-v7a x86_64 arm64-v8a mips armeabi mips64
#使用剛才我們做好的編譯鏈
NDK_TOOLCHAIN_VERSION := ollvm
Visual Studio集成
編譯ollvm的時候,使用cmake-gui選擇Visual Studio2015或者命令行選擇cmake -G "Visual Studio 14 2015" -DCMAKE_BUILD_TYPE=Release ../obfuscator/
然后cmake會產(chǎn)生一個visual studio工程夭委,用vs編譯即可幅狮!
至于將Visual Studio的默認編譯器換成clang編譯,參考https://www.ishani.org/projects/ClangVSX/
Visual Studio2015起官方開始支持Clang株灸,具體做法:
文件->新建->項目->已安裝->Visual C++->跨平臺->安裝Clang with Microsoft CodeGen
Clang是一個完全不同的命令行工具鏈崇摄,這時候可以在工程配置中,平臺工具集選項里找到Clang慌烧,然后使用ollvm的clang替換該clang即可逐抑。
XCode集成
XCode里集成需要看版本,XCode10之前和之后是一個分水嶺屹蚊,XCode9之前和之后有一個小配置不同厕氨。
XCode10以前
$ 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
修改:
<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>
執(zhí)行:
$ sudo plutil -convert binary1 Info.plist
$ cd Resources/
$ sudo mv Clang\ LLVM\ 1.0.xcspec Obfuscator.xcspec
$ sudo vim Obfuscator.xcspec
修改:
<key>Description</key>
<string>Apple LLVM 8.0 compiler</string> -> <string>Obfuscator 4.0 compiler</string>
<key>ExecPath</key>
<string>clang</string> -> <string>/path/to/obfuscator_bin/clang</string>
<key>Identifier</key>
<string>com.apple.compilers.llvm.clang.1_0</string> -> <string>com.apple.compilers.llvm.obfuscator.4_0</string>
<key>Name</key>
<string>Apple LLVM 8.0</string> -> <string>Obfuscator 4.0</string>
<key>Vendor</key>
<string>Apple</string> -> <string>HEIG-VD</string>
<key>Version</key>
<string>7.0</string> -> <string>4.0</string>
執(zhí)行:
$ cd English.lproj/
$ sudo mv Apple\ LLVM\ 5.1.strings "Obfuscator 3.4.strings"
$ sudo plutil -convert xml1 Obfuscator\ 3.4.strings
$ sudo vim Obfuscator\ 3.4.strings
修改:
<key>Description</key>
<string>Apple LLVM 8.0 compiler</string> -> <string>Obfuscator 4.0 compiler</string>
<key>Name</key>
<string>Apple LLVM 8.0</string> -> <string>Obfuscator 4.0</string>
<key>Vendor</key>
<string>Apple</string> -> <string>HEIG-VD</string>
<key>Version</key>
<string>7.0</string> -> <string>4.0</string>
執(zhí)行:
$ sudo plutil -convert binary1 Obfuscator\ 3.4.strings
XCode9之后要設(shè)置Enable Index-While-Building
成NO
XCode10之后
xcode10之后無法使用添加ideplugin的方法,但添加編譯鏈跑的依然可行汹粤,另外網(wǎng)上一些人說不能開bitcode命斧,不能提交AppStore,用原版llvm改的ollvm的確有可能出現(xiàn)上述情況玄括,所以我用蘋果的swift-llvm改了一版暫時沒去試著提交冯丙,或許可以肉瓦,有興趣的也可以自己下載使用試試obfuscator這版遭京,特別備注由于修改沒有針對swift部分所以用swift寫的代碼沒混淆,回頭有空的話再弄泞莉。
創(chuàng)建XCode的toolchain然后把生成的文件夾放到/Library/Developer/
下
cd build
sudo make install-xcode-toolchain
mv /usr/local/Toolchains /Library/Developer/
Toolchains下的.xctoolchain文件就是一個文件夾哪雕,進去修改info.plist
<key>CFBundleIdentifier</key>
<string>org.llvm.7.0.0svn</string> -> <string>org.ollvm-swift.5.0</string>
修改完在XCode的Toolchains下就會顯示相應的名稱
然后如圖打開XCode選擇Toolchaiins
按這些配置好后就算是可以用了。
最后
簡單展示一下混淆后的成果
源碼
反編譯未混淆代碼
反編譯混淆后代碼
擴展:字符串混淆
原版是沒有這功能的本來,Armariris 提供了這個功能鲫趁,我這也移植過來了斯嚎,畢竟不難。
首先把StringObfuscation
的.h,.cpp文件放到對應的Obfuscation
文件夾下,然后分別修改下面的文件堡僻。
用法
-mllvm -sobf:編譯時候添加選項開啟字符串加密
-mllvm -seed=0xdeadbeaf:指定隨機數(shù)生成器種子
效果
看個添加了-mllvm -sub -mllvm -sobf -mllvm -fla -mllvm -bcf
這么一串的效果糠惫。
源碼
反編譯未混淆代碼
反編譯混淆后代碼