虚假控制流
程序先收集函数中所有的 BasicBlock 和 alloca 指令,然后再随机挑选 BasicBlock 加上虚假控制流。这个 Pass 通过被选中的 BasicBlock 生成虚假的 BasicBlock,然后再使用不透明谓词将这两个 BasicBlock 连在一起。
在构建虚假BasicBlock时,首先复制原来的original BasicBlock,然后再修复虚假的 BasicBlock,例如修复 phi 节点和编译时生成的 metadata。
构造虚假BasicBlock的思路是首先拷贝生成一个alteredBasicBlock,并在BasicBlock中加入一些垃圾指令。加入垃圾指令的方法是遍历该basicblock中的所有OpCode操作码,若包含有Add、Sub、UDiv、SDiv、URem、SRem、Shl、LShr、AShr、And、Or、Xor以及FAdd、FSub、FMul、FDiv、FRem指令,则用随机生成一些指令来进行替换。由于该block在程序运行时并不会执行,因此无需担心插入的指令对原始程序运行的结果产生影响。
接下来,调整3个BasicBlock的关系。对于entry block 首先增加一条比较的指令,使它为真时跳转到original BasicBlock,为假时跳转到alteredBasicBlock。
if( true )
original basicblock
else
altered basicblock
对于altered basicblock模块,在它的尾部增加一条跳转指令,使得当它执行完毕之后(实际上它并不会执行),跳转到original basicblock模块。
最后,获取basicblock中最后一条指令的地址(在该例子中即ret指令的地址),调用splitBasicblock函数将original basicblock一分为二(original basicblok和originalBBpart2)
然后消除original basicblok和originalBBpart2的关系,再在original basicblock的末尾加入一个判断语句,为真时跳转到ret指令,为假则跳转到altered basicblock,伪代码如下所示:
if( true )
ret
else
altered basicblock
最终得到混淆后的控制流图:
多次跳转,在末尾跳转循环跳到alteredBB。
不完整的指令?