功能:
是為函數(shù)增加新的虛假控制流和添加垃圾指令
入口函數(shù):
BogusControlFlow繼承了FunctionPass,因此它的入口函數(shù)即為runOnFunction該入口函數(shù)進(jìn)來(lái)先判斷兩個(gè)參數(shù)的值:ObfTimes和ObfProbRate 边锁,分別代表bcf(BogusControlFlow)循環(huán)運(yùn)行的次數(shù)和每個(gè)basic block被混淆的幾率誊册,它們的默認(rèn)值分別為1和30%〖鼋。可通過(guò)設(shè)置參數(shù)boguscf-loop酱畅、 boguscf-prob修改它們的默認(rèn)值
例如:
if (!((ObfProbRate > 0) && (ObfProbRate <= 100)))
在編譯程序代碼時(shí)琳袄,若要啟動(dòng)bcf模塊,需要帶上參數(shù)“-mllvm -bcf”
if (toObfuscate(flag, &F, "bcf"))
最后調(diào)用bogus函數(shù)纺酸。bogus函數(shù)首先將本function的所有basicblock存放到一個(gè)list容器中窖逗,然后使用一個(gè)while循環(huán)調(diào)用addBogusFlow函數(shù)對(duì)選中的basicblock進(jìn)行增加虛假控制流
核心函數(shù):
-
bogus 函數(shù)
首先判斷ObfTimes和ObfProbRate 這兩個(gè)參數(shù)
判斷函數(shù)
一個(gè)大循環(huán)包括下面的內(nèi)容,這個(gè)大循環(huán)是ObfTimes 來(lái)控制循環(huán)運(yùn)行的次數(shù):
1:將函數(shù)中的所有BB 添加到list 中
添加到list
2: 判斷上面的list 是否為空餐蔬,將這個(gè)方法的內(nèi)部的所有BB 根據(jù)混淆比例看是否去虛假流程
有概率的執(zhí)行虛假流 addBogusFlow 函數(shù)
舉個(gè)例子:
int func1(int a,int b)
{
return a+b;
}
編譯完后的IR圖
addBogusFlow函數(shù)
1:調(diào)用getFirstNonPHIOrDbgOrLifetime函數(shù)獲取本basicblock中第一個(gè)不是Phi碎紊、Dbg、Lifetime的指令的地址(在本例中樊诺,即為%a.addr = alloca i32, aling 4的地址)
2:調(diào)用splitBasicBlock函數(shù)仗考。splitBasicBlock函數(shù)可根據(jù)上述指令的地址將一個(gè)basicblock一分為二(可稱為first basicblock 和original basicblock),i1 是%a.addr = alloca i32, aling 4的地址词爬,分割的時(shí)候是第二塊是從i1開(kāi)始到最后秃嗜,i1 上面的部分為一塊
分割后此時(shí)IR 如下:
接著調(diào)用createAlteredBasicBlock函數(shù)對(duì)original basicblock進(jìn)行拷貝生成一個(gè)名為“altered basicblock”的basicblock,并對(duì)該basicblock加入一些垃圾指令顿膨。加入垃圾指令的方法是遍歷該basicblock中的所有OpCode【操作碼】锅锨,若包含有Add、Sub虽惭、UDiv橡类、SDiv、URem芽唇、SRem顾画、Shl、LShr匆笤、AShr研侣、And、Or炮捧、Xor以及FAdd庶诡、FSub、FMul咆课、FDiv末誓、FRem指令,則用隨機(jī)生成一些指令來(lái)進(jìn)行替換书蚪。由于該block在程序運(yùn)行時(shí)并不會(huì)執(zhí)行喇澡,因此無(wú)需擔(dān)心插入的指令對(duì)原始程序運(yùn)行的結(jié)果產(chǎn)生影響∈庑#拷貝original basicblock后晴玖,
IR圖如圖5所示。
這時(shí),所有的basicblock已經(jīng)準(zhǔn)備完畢呕屎,一共存在有3個(gè)basicblock让簿,需要調(diào)整他們之間的關(guān)系。首先清除first basicblock和altered basicblock跟父節(jié)點(diǎn)的關(guān)系秀睛,代碼為:
basicBlock->getTerminator()->eraseFromParent();
alteredBB->getTerminator()->eraseFromParent();
清除完畢后的IR圖如圖6所示尔当。
接著下一步的操作是增加basicblock之間的條件跳轉(zhuǎn)指令。對(duì)于first basicblock(即為圖中的entry)琅催,bcf源碼的做法是先增加一條比較語(yǔ)句 1.0 = = 1.0 居凶,然后為真時(shí)跳轉(zhuǎn)到original basicblock,為假則跳轉(zhuǎn)到altered basicblock藤抡。可用偽代碼如下表示:
if( 1.0 == 1. 0)
original basicblock
else
altered basicblock
對(duì)于altered basicblock模塊抹估,在它的尾部增加一條跳轉(zhuǎn)指令缠黍,使得當(dāng)它執(zhí)行完畢之后(實(shí)際上它并不會(huì)執(zhí)行),跳轉(zhuǎn)到original basicblock模塊药蜻。此時(shí)的IR圖如圖7所示瓷式。
最后,獲取basicblock中最后一條指令的地址(在該例子中即ret指令的地址)语泽,調(diào)用splitBasicblock函數(shù)將original basicblock一分為二(original basicblok和originalBBpart2)
然后調(diào)用如下代碼:
originalBB->getTerminator()->eraseFromParent();
消除original basicblok和originalBBpart2的關(guān)系后贸典,再在original basicblock的末尾加入一個(gè)判斷語(yǔ)句,為真時(shí)跳轉(zhuǎn)到ret指令踱卵,為假則跳轉(zhuǎn)到altered basicblock廊驼,偽代碼如下所示:
if( 1.0 == 1. 0)
ret
else
altered basicblock
此時(shí)該func1函數(shù)的IR圖如圖8所示:
doF函數(shù) 【和bogus 函數(shù)在位置相同】
該函數(shù)的功能是將Function中所有為真的判斷語(yǔ)句進(jìn)行替換,比如上一節(jié)中的“1.0 == 1.0 ”惋砂。它的思想是定義兩個(gè)全局變量x妒挎、y并且初始化為0,然后遍歷Module內(nèi)的所有指令西饵,并將所有的FCMP_TRUE分支指令替換為“y<10 || xx(x-1)%2 ==0”酝掩。替換完畢后func1函數(shù)的IR流程圖如圖9所示:
至此,對(duì)func1函數(shù)的一次bcf混淆過(guò)程就完成了