O-MVLL介紹
O-MVLL的開發靈感來自于另一個著名的基于LLVM的代碼混淆專案ollvm,并在其基礎上做了創新和改進,O-MVLL的混淆邏輯實作方式也是通過LLVM Pass,支持也僅會支持ARM64架構,根據作者所說,這是由于當初的設計選擇,此外,作者還使用了pybind11,用戶可以使用python腳本來對O-MVLL進行配置,從而靈活的運用作者封裝好的各種代碼混淆方式,
混淆后的可執行檔案相比于正常編譯的可執行檔案來說,抵抗逆向工程的能力增強,但與源代碼的功能相同,能夠在一定程度上保護源代碼和程式,增加逆向工程的分析成本,
作者的介紹檔案: O-MVLL Documentation (obfuscator.re)
開源專案github地址: GitHub - open-obfuscator/o-mvll: O-MVLL is a LLVM-based obfuscator for native code (Android & iOS)
作者的作業郵箱: [email protected](可以向他提交bug和issues,也可以問他一些專案的問題,回復的都很快,贊)
目前專案包含了7種代碼混淆方式,它們分別是:Anti-Hooking,Arithmetic Obfuscation,Control-Flow Breaking,Control-Flow Flattening,Opaque Constants,Opaque Fields Access Strings Encoding,它們的實作細節分析見下一篇隨筆,
專案編譯安裝
編譯方式可見作者的介紹檔案中,Compilation一欄,作者提供了Linux、macOS兩個平臺的編譯方式,并且提供了docker file,這里簡單介紹下使用docker 的編譯安裝方式
拉取docker鏡像并下載依賴
$ docker pull openobfuscator/omvll-ndk $ git clone https://github.com/open-obfuscator/o-mvll.git $ curl -LO https://data.romainthomas.fr/omvll-deps-ndk-r25.tar $ mkdir -p ./third-party $ tar xvf omvll-deps-ndk-r25.tar -C ./third-party $ docker run -it openobfuscator/omvll-ndk
進入docker容器內部,將下載的依賴和檔案復制過來
$ docker cp ./third-party $你的容器id:/ $ docker cp ./o-mvll $你的容器id:/
之后給予檔案運行權限并運行
$ chmod +x /o-mvll/scripts/docker/ndk_r25_compile.sh
$ sh /o-mvll/scripts/docker/ndk_r25_compile.sh
此時完成整個專案的構建,
下載Clang from NDK
專案構建完成后,需要使用ndk的clang來呼叫該專案作為編譯程序中的插件,因此還需要安裝ndk clang,可以在此處下載:NDK 下載 | Android NDK | Android Developers (google.cn)
選擇Linux64位的下載,解壓后復制到docker容器中,解壓后的檔案夾中的toolchains/llvm/prebuilt/linux-x86_x64/bin中包含有ndk所使用的clang,為了方便呼叫,可以將該路徑加入到環境變數當中,之后在命令列中使用clang,即表示使用該路徑下的ndk的clang,
基本使用
現在我們撰寫了一個檔案名為main.c的程式,將要使用O-MVLL對其進行混淆,可以使用如下指令得到一份混淆后的可執行檔案main:
$ clang --target=aarch64-linux-android21 -fpass-plugin=libOMVLL.so main.c -o main
其中,-fpass-plugin指定的元件即為O-MVLL專案編譯出來的檔案,其位置應該處于o-mvll/src/build_ndk_r25當中,由于O-MVLL僅支持aarch64,因此還需要使用--target指明目標架構,或者也可以直接使用
$ aarch64-linux-android21-clang -fpass-plugin=libOMVLL.so main.c -o main
這樣就不用顯式地使用target指明目標架構了
組態檔omvll_config.py
之前提到,O-MVLL做出的創新是使用pybind11提供了pythonAPI,以供用戶配置代碼混淆的方式,因此在執行上述指令之前,需要配置好omvll_config.py檔案,
O-MVLL將會嘗試在呼叫clang的目錄下尋找該檔案,如果找不到該檔案,就會報錯
...
error: ModuleNotFoundError: No module named 'omvll_config'
make: *** [Makefile:31: strings.bin] Error 1
可以通過環境變數來指明omvll_config.py的路徑和檔案名,例如export OMVLL_CONFIG=~/project/obfu/config_test.py,這樣O-MVLL就會去尋找~/project/obfu/config_test.py作為混淆的組態檔
組態檔中必須要實作一個名為omvll_get_config的函式,和一個繼承自omvll.ObfuscationConfig的類,omvll_get_config的回傳值必須是這個類才行,
這個函式由pass呼叫,從而訪問用戶定義的混淆方案,因為混淆的配置必須是唯一的,因此作者強烈建議使用@functools來包裝這個函式:
import omvll from functools import lru_cache class MyConfig(omvll.ObfuscationConfig): def __init__(self): super().__init__() @lru_cache(maxsize=1) def omvll_get_config() -> omvll.ObfuscationConfig: """ Return an instance of `ObfuscationConfig` which aims at describing the obfuscation scheme """ return MyConfig()
現在,我們可以在MyConfig中配置我們的混淆方案了,例如呼叫字串混淆時,就需要重寫obfuscate_string(self, module: omvll.Module, func: omvll.Function, string: bytes)這個函式,
該函式的輸入為繼承自llvm:Module的omvll:Modul,繼承自llvm:Function的omvll:Fcuntion以及傳入的字串,它會遍歷每個模塊當中每個函式中呼叫的字串,當函式的回傳值為true或者某個字串時,啟動字串混淆
class MyConfig(omvll.ObfuscationConfig): def __init__(self): super().__init__() def obfuscate_string(self, module: omvll.Module, func: omvll.Function, string: bytes): if func.name == "hello": return True if b"debug.cpp" in string: return "<REMOVED>" return False
上述配置,就會將函式名為hello的函式中的字串進行加密,并且將包含debug.cpp的字串替換為<REMOVED>
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/537736.html
標籤:其他
