功能:
是为函数增加新的虚假控制流和添加垃圾指令
入口函数:
BogusControlFlow继承了FunctionPass,因此它的入口函数即为runOnFunction该入口函数进来先判断两个参数的值:ObfTimes和ObfProbRate ,分别代表bcf(BogusControlFlow)循环运行的次数和每个basic block被混淆的几率,它们的默认值分别为1和30%。可通过设置参数boguscf-loop、 boguscf-prob修改它们的默认值
例如:
if (!((ObfProbRate > 0) && (ObfProbRate <= 100)))
在编译程序代码时,若要启动bcf模块,需要带上参数“-mllvm -bcf”
if (toObfuscate(flag, &F, "bcf"))
最后调用bogus函数。bogus函数首先将本function的所有basicblock存放到一个list容器中,然后使用一个while循环调用addBogusFlow函数对选中的basicblock进行增加虚假控制流
核心函数:
-
bogus 函数
判断函数
首先判断ObfTimes和ObfProbRate 这两个参数
一个大循环包括下面的内容,这个大循环是ObfTimes 来控制循环运行的次数:
1:将函数中的所有BB 添加到list 中
添加到list
2: 判断上面的list 是否为空,将这个方法的内部的所有BB 根据混淆比例看是否去虚假流程
有概率的执行虚假流 -
addBogusFlow 函数
举个例子:
int func1(int a,int b)
{
return a+b;
}
编译完后的IR图
IR
addBogusFlow函数
1:调用getFirstNonPHIOrDbgOrLifetime函数获取本basicblock中第一个不是Phi、Dbg、Lifetime的指令的地址(在本例中,即为%a.addr = alloca i32, aling 4的地址)
2:调用splitBasicBlock函数。splitBasicBlock函数可根据上述指令的地址将一个basicblock一分为二(可称为first basicblock 和original basicblock),i1 是%a.addr = alloca i32, aling 4的地址,分割的时候是第二块是从i1开始到最后,i1 上面的部分为一块
分割过程
分割后此时IR 如下:
image.png
接着调用createAlteredBasicBlock函数对original basicblock进行拷贝生成一个名为“altered basicblock”的basicblock,并对该basicblock加入一些垃圾指令。加入垃圾指令的方法是遍历该basicblock中的所有OpCode【操作码】,若包含有Add、Sub、UDiv、SDiv、URem、SRem、Shl、LShr、AShr、And、Or、Xor以及FAdd、FSub、FMul、FDiv、FRem指令,则用随机生成一些指令来进行替换。由于该block在程序运行时并不会执行,因此无需担心插入的指令对原始程序运行的结果产生影响。拷贝original basicblock后,
image.png
IR图如图5所示。
image.png
这时,所有的basicblock已经准备完毕,一共存在有3个basicblock,需要调整他们之间的关系。首先清除first basicblock和altered basicblock跟父节点的关系,代码为:
basicBlock->getTerminator()->eraseFromParent();
alteredBB->getTerminator()->eraseFromParent();
清除完毕后的IR图如图6所示。
image.png
接着下一步的操作是增加basicblock之间的条件跳转指令。对于first basicblock(即为图中的entry),bcf源码的做法是先增加一条比较语句 1.0 = = 1.0 ,然后为真时跳转到original basicblock,为假则跳转到altered basicblock。可用伪代码如下表示:
if( 1.0 == 1. 0)
original basicblock
else
altered basicblock
对于altered basicblock模块,在它的尾部增加一条跳转指令,使得当它执行完毕之后(实际上它并不会执行),跳转到original basicblock模块。此时的IR图如图7所示。
image.png
image.png
最后,获取basicblock中最后一条指令的地址(在该例子中即ret指令的地址),调用splitBasicblock函数将original basicblock一分为二(original basicblok和originalBBpart2)
image.png
然后调用如下代码:
originalBB->getTerminator()->eraseFromParent();
消除original basicblok和originalBBpart2的关系后,再在original basicblock的末尾加入一个判断语句,为真时跳转到ret指令,为假则跳转到altered basicblock,伪代码如下所示:
if( 1.0 == 1. 0)
ret
else
altered basicblock
此时该func1函数的IR图如图8所示:
image.pngdoF函数 【和bogus 函数在位置相同】
该函数的功能是将Function中所有为真的判断语句进行替换,比如上一节中的“1.0 == 1.0 ”。它的思想是定义两个全局变量x、y并且初始化为0,然后遍历Module内的所有指令,并将所有的FCMP_TRUE分支指令替换为“y<10 || xx(x-1)%2 ==0”。替换完毕后func1函数的IR流程图如图9所示: image.png
至此,对func1函数的一次bcf混淆过程就完成了
网友评论