來自YSRC:孤挺花字元串混淆功能分析

2017年6月,我們啟動了Gossamer Project,寓意國內的安全研究團隊能像蛛網一樣鏈接起來,互相分享和復用研究成果。同月,我們開放了孤挺花LLVM混淆框架,為程序安全防護提供基本的開源工具。沒有想到,僅僅5天之後,來自同程安全應急響應中心的同行qtfreet00就為大家提供了一份高質量的引用:《為OLLVM添加字元串混淆功能》。在學術界,我們希望一篇論文能夠幫助後續的研究人員更好地開展相關研究,在安全工業界,我們也非常高興能看到有同行能夠關注我們的微小的工作,幫助我們做得更好!這裡我們特地致謝qtfreet00和YSRC,希望未來能夠有更多交流,也希望更多的安全研究同行能夠在研究主題上開展合作。GoSSIP小組和LoCCS實驗室歡迎一切形式的合作交流~

下面我們也轉發這篇分析文章(為OLLVM添加字元串混淆功能),希望能夠讓更多人了解孤挺花混淆框架,再次感謝qtfreet00@YSRC的工作!

======================================================================

為OLLVM添加字元串混淆功能

原創 2017-07-04 qtfreet00@YSRC 同程安全應急響應中心

本文簡單介紹了下使用上海交大GoSSIP小組開源的「孤挺花」混淆框架來給OLLVM加上字元串混淆的功能。

0x01 OLLVM 4.0

OLLVM(Obfuscator-LLVM)是瑞士西北應用科技大學安全實驗室於2010年6月份發起的一個針對LLVM代碼混淆項目,主要作用是增加逆向難度,從而一定程度上保護代碼的安全。因為後期轉向了商業項目strong.protect,所以項目的進度一度停滯,而在17年3月,LLVM已經更新到了4.0版本,新版本的一些特性導致老版本的OLLVM存在一定的局限性。

幾天前,上海交大密碼與計算機安全實驗室GoSSIP小組開源了他們設計的基於LLVM 4.0的孤挺花混淆框架,功能包含字元串加密,控制流扁平化和指令替換。出於穩定性考慮,目前開源的代碼僅包括對編譯源代碼中的常量字元串加密一項基本功能(相關簡介)。給上海交大的同學點贊 : )

YSRC簡單的做了下分析,發現該功能主要是實現了一個用於字元串加密的pass,具體什麼是pass,可以參考如下文章(① ,②),本文主要介紹將孤挺花的字元串加密pass集成到OLLVM 4.0中。(官方分支暫時還未支持Constants encryption)

0x02 pass集成

字元串加密的pass位於如下目錄

提取出該文件,放到OLLVM相同目錄下,並將頭文件也複製到對應目錄下

在Obfuscation下的cmakelists.txt將StringObfuscation.cpp添加到編譯庫中,最後只需要在Transforms/IPO下的PassManagerBuilder.cpp將字元串加密的編譯選項添加進去即可

  1. 添加#include 「llvm/Transforms/Obfuscation/StringObfuscation.h」引用

  2. 在合適的地方插入以下兩條函數聲明,即編譯時的編譯參數-mllvm -sobf:

    static cl::opt<std::string> Seed("seed", cl::init(""),

    cl::desc("seed for the random"));

    static cl::opt<bool> StringObf("sobf", cl::init(false),

    cl::desc("Enable the string obfuscation"));

  3. 在PassManagerBuilder::PassManagerBuilder()構造函數中添加隨機數因子的初始化

  1. 最後將該pass添加進void PassManagerBuilder::populateModulePassManager中即可

0x03 Windows下編譯OLLVM

這裡編譯環境選擇的是windows,其它平台類似

編譯器:

  • MinGW64 for Windows

  • Cmake 3.9 rc5 for Windows x64

    這裡注意下套件都是選擇的64位版本的,並且要注意最好清除下系統變數中之前配置的變數。

官方編譯命令:

  • git clone -b llvm-4.0 obfuscator-llvm/obfuscator

  • mkdir build

  • cd build

  • cmake -DCMAKE_BUILD_TYPE=Release ../obfuscator/

  • make -j7

如果cmake如果不指定參數的話,會默認去選擇當前電腦里已有的編譯器,如果安裝了vs的話,會自動去查找vs的編譯器

如果打算使用vs編譯

cmake -DCMAKE_BUILD_TYPE=Release ../obfuscator/

會生成32位的依賴版本

cmake -G 「Visual Studio 15 2017 Win64」 -DCMAKE_BUILD_TYPE=Release ../obfuscator/

上面這種方法就會生成64位版本的編譯環境,不過在測試編譯時,32位正常編譯通過,64位踩了很多坑,所以還是不建議使用vs編譯。

使用MinGw編譯時,需要加上參數

cmake -G 「MinGW Makefiles」 -DCMAKE_BUILD_TYPE=Release ../obfuscator/

最後再執行make -j7 即可,數字可根據電腦配置進行選擇,編譯完成後,會在build/bin下看到編譯完成的二進位文件。

0x04 NDK使用OLLVM

將編譯好的clang.exe , clang++.exe 以及上級目錄下 lib/clang下的文件夾拷貝出來,我這裡使用的是ndk 13,直接將這些文件拷貝到toolchainsllvmprebuiltwindows-x86_64,其中exe文件複製到bin目錄下,lib文件夾直接複製到windows-x86_64目錄下即可。

新建一個Android Studio工程測試下效果,開啟字元串加密編譯選項

編寫測試函數

在函數前添加了fla屬性,該屬性代表ollvm的Control Flow Flattening ,具體可見ollvm項目的wiki,編譯運行查看結果。

使用IDA打開編譯後的so文件,可以看到函數中的字元串已經不顯示了,

而Test函數的流程也被進行了混淆。

F5後:

0x05 總結

在項目中合理的使用ollvm可以幫助增加逆向難度,並且針對關鍵的函數混淆對性能的影響也比較小。


推薦閱讀:

歷史上出現過的主流C/C++ 編譯器都有哪些?
Clang 比 GCC 好在哪裡?
Partial Evaluation, Constant Propagation, AI的關係是什麼?

TAG:软件安全 | 编译器 |