Android NDK混淆

項目原因研究Android的So庫代碼混淆,增加IDA工具查看的復雜度。簡單接觸了ollvm 混淆組件。網(wǎng)上查看了很多人的文章,簡單做個隨筆備忘。


1、ollvm下載編譯

我的是macbook環(huán)境。

參考obfuscator官網(wǎng):https://github.com/obfuscator-llvm/obfuscator/wiki

執(zhí)行下面的命令下載并編譯:

$ 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

cmake找不到的話,上cmake.org官網(wǎng)下載,并設置環(huán)境變量。

編譯成功后,生成的文件主要在build/bin 和 build/lib 這2個文件夾。

2、整合到NDK

網(wǎng)上別人有介紹在NDK目錄手動創(chuàng)建llvm之類的新文件夾,拷貝build/bin 和 build/lib2個文件夾,有編譯問題,懶得去折騰。

我的做法是:

找到Android SDK目錄中的 ../ndk-bundle/toolchains/llvm?文件夾,先備份下llvm文件夾,然后將obfuscator編譯好的build/bin 和 build/lib2個文件夾直接拷貝到../llvm/prebuilt/darwin-x86_64/文件夾下,直接覆蓋替換。

我使用最新的Android Studio編輯器,編譯so庫已經(jīng)集成cmake,不需要去修改config.mk 與 setup.mk也是正常的。

3、使用OLLVM

先嘗試在自己so庫工程的CMakeList.txt中加入:

SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -mllvm -fla")SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -mllvm -fla")

Release編譯修改成下面的配置:

SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -mllvm -fla")SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -mllvm -fla")

再使用IDA工具查看so文件,發(fā)現(xiàn)函數(shù)內(nèi)的代碼有產(chǎn)生混淆修改。

這里介紹下OLLVM的混淆參數(shù),上面的官網(wǎng)github的wiki有說明這些參數(shù):

1、-fla ? :for the?control flow flattening?pass

2、-sub ?:for the?instruction substitution?pass

3、-bcf ?: for the?bogus control flow?pass

-fla

表示使用控制流平展模式,最直觀的感受就是簡單的if-else語句,被嵌套成了while-switch語句,出現(xiàn)了很多干擾無用的分支,增加閱讀難度。

-mllvm -fla: activates control flow flattening

-mllvm -split: activates basic block splitting. Improve the flattening when applied together.

-mllvm -split_num=3: if the pass is activated, applies it 3 times on each basic block. Default: 1

-sub

表示使用指令替換模式,主要是將正常的運算操作(+,-,&,|等)替換成功能相等但表述更復雜的形式。

比如,對于表達式 a = b + c,它的等價式可以有 a = – ( -b – c), a = b – (-c) 或 a = -(-b) + c 等,原表達式可以替換成任意相等式,或者通過隨機數(shù)在多個相等式中做選擇。

SUB模式目前只支持整數(shù)運算操作,支持 + , – , & , | 和 ^ 操作,還是比較局限的。編譯時,使用 -mllvm -sub 參數(shù)即可。下面參數(shù)可與-mllvm -sub參數(shù)配合使用。

-mllvm -sub: activate instructions substitution

-mllvm -sub_loop=3: if the pass is activated, applies it 3 times on a function. Default: 1

?-bcf

表示使用控制流偽造模式,也是對程序的控制流做操作。BCF模式會在原代碼塊的前后隨機插入新的代碼塊,新插入的代碼塊不是確定的,然后新代碼塊再通過條件判斷跳轉(zhuǎn)到原代碼塊中。

更要命地是,原代碼塊可能會被克隆并插入隨機的垃圾指令。這么多不確定性,就導致對同一份代碼多次做BCF模式的混淆時,得到的是不同的混淆效果。可見,BCF混淆模式還是很強大的,不同于FLA那種較確定的混淆模式。使用BCF模式編譯時配置參數(shù) -mllvm -bcf即可,此外,BCF模式還支持其它幾個參數(shù),下面參數(shù)與-mllvm -bcf參數(shù)配合使用。

-mllvm -perBCF=20:?對所有函數(shù)都混淆的概率是20%,默認100%

-mllvm -bcf: activates the bogus control flow pass

-mllvm -bcf_loop=3:?對函數(shù)做3次混淆,默認1次

-mllvm -bcf_prob=40: ?代碼塊被混淆的概率是40%,默認30%


備注:

參數(shù)前都需要有-mllvm,比如,CMakeList.txt中添加:

SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -mllvm -fla -mllvm -bcf -mllvm -sub ")

有的時候,由于效率或其他原因的考慮,我們只想給指定的函數(shù)混淆,OLLVM也提供了對這一特性的支持。比如,想對函數(shù)func()使用bcf混淆,只需要給函數(shù)func()增加bcf屬性即可。

int func() ?__attribute__ ((__annotate__ (("bcf"))))

fla,sub和bcf三個屬性可以搭配使用。如果不想對func()函數(shù)使用bcf屬性,那標記為“nobcf”即可。

4、混淆代碼中的字符串常量

上海交大密碼與計算機安全實驗室GoSSIP小組開源了他們設計的基于LLVM 4.0的孤挺花混淆框架,實現(xiàn)了一個用于字符串加密的pass。

字符串加密的pass位于如下目錄:

????Armariris/include/llvm/Transforms/Obfuscation/StringObfuscation.h

????Armariris/lib/Transforms/Obfuscation/StringObfuscation.cpp

?提取出該文件,放到OLLVM相同目錄下,并將頭文件也復制到對應目錄下.

在Obfuscation下的cmakelists.txt將StringObfuscation.cpp添加到編譯庫中,

add_llvm_library(LLVMObfuscation

CryptoUtils.cpp

Substitution.cpp

StringObfuscation.cpp

BogusControlFlow.cpp

Utils.cpp

SplitBasicBlocks.cpp

Flattening.cpp

)

最后只需要在Transforms/IPO下的PassManagerBuilder.cpp將字符串加密的編譯選項添加進去即可

1. 在PassManagerBuilder.cpp中添加引用:

#include "llvm/Transforms/Obfuscation/StringObfuscation.h"

2. 在PassManagerBuilder.cpp中的合適的地方插入以下加粗的兩條函數(shù)聲明,即編譯時的編譯參數(shù)-mllvm -sobf:?

static cl::optEnableMLSM("mlsm", cl::init(true), cl::Hidden, cl::desc("Enable motion of merged load and store"));

static cl::opt Seed("seed", cl::init(""),cl::desc("seed for the random"));

static cl::opt StringObf("sobf", cl::init(false),cl::desc("Enable the string obfuscation"));

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

加粗的那一行代碼就是了。

void PassManagerBuilder::populateModulePassManager(

????legacy::PassManagerBase &MPM) {

...

?MPM.add(createForceFunctionAttrsLegacyPass());

MPM.add(createStringObfuscation(StringObf));

MPM.add(createSplitBasicBlock(Split));

...

}

參數(shù)用法:

編譯時候添加選項開啟字符串加密: ??-mllvm -sobf

開啟控制流扁平化:?-mllvm -fla

開啟指令替換:?-mllvm -sub

指定隨機數(shù)生成器種子: ?-mllvm -seed=0xdeadbeaf

最后命令調(diào)用:

#SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -mllvm -sobf")

#SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -mllvm -sobf")

IDA查看so庫,可以看到常量字符串被混淆成亂碼了。

5、OLLVM 5.0版本的參考:

https://github.com/qtfreet00/llvm-obfuscator

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

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

  • 原文鏈接:http://fighting300.com.... OLLVM簡介 OLLVM(Obfuscator-...
    fighting300閱讀 21,235評論 65 35
  • 近來,ollvm在國內(nèi)移動安全,尤其是安全加固上的使用越來越廣泛,ollvm的混淆和反混淆也被視為比較高等的知識之...
    that_is_this閱讀 3,206評論 4 0
  • 注:首發(fā)地址 1. 前言 當在做 Android NDK 開發(fā)時,如果不熟悉用 CMake 來構(gòu)建,讀不懂 CMa...
    cfanr閱讀 24,795評論 1 53
  • 今天讀《三國志·蜀志》之《先主傳》、《后主傳》、《二主妃子傳》,深感人生滄桑,變化無常,究難預測。當時認真、在乎、...
    自由心空閱讀 475評論 13 7
  • 器識為先,文藝其從,立德立言,無問西東。 在四個時空交錯的劇情中,每個主角都有著自己的無奈。 二十年代的吳嶺瀾,因...
    夏小禾閱讀 1,175評論 8 33

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