IR(intermediate representation)是前端语言生成的中间代码表示,也是Pass操作的对象,它主要包含四个部分:
它们之间的关系如下图所示:
检查是否能够进行Substitution
混淆,混淆的具体操作主要通过调用substitute
函数进行的。
整个函数的功能主要是根据运算指令中的操作符进行相应的混淆操作,由于同一指令的混淆操作有很多种,因此通过llvm::cryptoutils->get_range
获取随机数来指定某种混淆操作。
由于这些运算混淆都大同小异,所以接下来以一个例子来进行Substitution
混淆的介绍。
主要是创建一个取反指令和一个整型减法指令来替换原有的指令。
一开始我不理解这些操作具体体现是什么,于是为了探究这些代码对IR进行了什么操作,因此在源码上进行打印调试,打印更改前后的IR。主要修改如下:
打印结果如下:
从结果上看,Create***
等指令创建函数会影响后面的IR代码,即后续代码会进行相应的调整以保证IR代码的正确性,至于其具体过程,本篇博客不进行介绍。replaceAllUsesWith
函数并不是真正的将源指令替换或删除,仅仅只是让后续IR代码中对源指令的结果的引用转变成对新指令的结果的引用,也就是说,源指令对后续的操作无任何作用,这样之后的优化应该会删除这种无效IR代码(如果指定了优化等级的话)。
至于其他的运算混淆,通过这个例子可以知其一而知其二。
进行一些类似的操作,然后是调用split
函数。
这部分主要是遍所有基本块,如果基本块中只含有一条指令或者含有PHI
节点,则不进行基本块拆分,同时调整分割次数以防止分割次数大于基本块中的指令数。接下来就是生成分割点,具体操作为对1~size-1
的有序vetor
打乱顺序,然后对前splitN
个进行从小到大的排序,这样做的目的一是随机分割,二是重排序以防止分割不会出错。最后,调整分割点,调用splitBasicBlock
进行分割。
先来看看PHI
节点是什么。
所有LLVM
指令都以静态单一赋值(SSA
)形式表示。从本质上讲,这意味着任何变量只能分配给一次。因此就存在如下情况的问题:
假设v
的值小于10,变量a
就会被赋值为2,但是a
已经被赋值了一次,由于SSA
性质的约束,不能继续给a
赋值了。为了解决这一问题,LLVM中引入了PHI
节点(PHI Node
),用于处理基本块之间的分支和合并。当一个基本块有多个前驱基本块时,PHI
节点可以用来表示从不同的前驱基本块中接收的值,这在处理分支和合并的情况下非常有用。
上述代码就会被转换成:
if
分支里面的赋值被转换成另一个变量,b
的赋值也就在两个变量之间选择,通过添加一个PHI Node
,让它来决定选择哪个变量赋值给b
。
以指令I
为分割点,所有在分割点之前的指令保留在原来的基本快中,分割点处的指令以及之后的指令保留到新的基本块中,并且在原来的基本块后面增加跳转到新的基本块的br
指令。之后是修正新基本块的后继基本块(同样也是分割之前的基本块的后继基本块)中的PHINode
,具体操作为替换PHINode
的前驱基本块(即分割之前的基本块)为新的基本块。
runOnFunction
函数没啥好看的,直接看重点:flatten
函数,将该函数分为以下几块进行讲解。(这一部分的理解可以参考Obfuscator-llvm源码分析 - 知乎 (zhihu.com)中的CFG图)
首先弄了一个随机数,这个不需要着重分析。
然后是创建LowerSwitchPass
并执行该Pass
。
LowerSwitchPass
的作用是将函数中的switch
指令转换成一系列连续的if-then
指令。具体的操作我没仔细看,也不打算深究。
接下来将函数f
的所有基本块存放一份到向量origBB
中,同时检查基本块中的终止指令,如果终止指令是Invoke
指令,则对整个函数f
不进行平坦化混淆。如果函数f
的基本块数量<1也不进行平坦化混淆。最后是将函数f
的第一个基本块从向量origBB
中删除。
接下来引入3个问题。
第一个问题:什么是Terminator?
在LLVM
的IR
中,每个基本块必须以Terminator
指令结尾,它标志着基本块的结束,用于控制接下来代码流进入到哪一个基本块中。Terminator
指令,它可以是分支指令(如BranchInst
)、返回指令(如ReturnInst
)或者抛出异常的指令(如InvokeInst
)等。
第二个问题:什么是InvokeInst?
InvokeInst
是一种特殊的调用指令,用于调用有异常处理的函数。与普通的CallInst
不同,如果函数调用期间抛出异常,则控制流会转移到指定的异常处理代码中,而不是继续执行后续的指令。InvokeInst
指令,这个指令有两个后继,但是一个是正常的基本块处,另一个是跳转到unwind
相关的逻辑中(异常处理),这个unwind
基本块的开头必须为LandingPadInst
,且只能通过InvokeInst
指令来到达。
第三个问题:为什么基本块中含有InvokeInst就对所在函数不进行平坦化处理?
由于unwind
基本块只能通过InvokeInst
指令来到达。所以当LandingPadInst
被插入到SwitchInst
中去的时候,由于不是通过InvokeInst
到达的,所以会报错。然而对所在函数不进行平坦化,感觉应该不太妥,对于这部分的优化可以参考OLLVM控制流平坦化的改进 - 知乎 (zhihu.com)。
对第一个基本块进行单独处理。
具体而言,如果该基本块的后续基本块有多个,则进行基本块拆分,将拆分出的新的基本块插入到origBB
中的第一个基本块之前。基本块拆分是为了保证第一个基本块只有一个后继基本块,以便后续跳转到loopEntry
基本块中。最后删除第一个基本块中的末尾指令(删除到后继基本块的跳转指令,后续会添加到loopEntry
基本块的跳转)。
构建一个循环switch-case
的框架,建立基本块之间的跳转连接。
具体来说是,在函数f
第一个基本块(拆分后)的末尾创建switchVar
路由变量并赋予随机值。接着创建loopEntry
、loopEnd
、swDefault
基本块。然后在loopEntry
基本块的末尾加载switchVar
路由变量,之后又在loopEntry
基本块的末尾创建SwitchInst
指令,设置默认分支为swDefault
基本块,设置case
分支数量为0,最后设置SwitchInst
指令的路由变量为load
指令加载的switchVar
。其余的BranchInst
则是建立基本块之间的跳转。
此时CFG
图如下:
将origBB
中所有的基本块按照case
索引值加入到switch-case
分支中。
看完整个Flattening
源码后,我还在想源码中并没有通过设置switchVar
来确保代码流在第一个基本块能够正确进入到原本的后续基本块中。后面我反复阅读源码后才发现,其实它们之间的跳转关系在这里就确定了!
注意看!!!初始switchVar
的值为:
origBB
中的第一个基本块的case
索引值为:
此时switchI->getNumCases()
的值就是0,这么一来,初始switchVar
的值恰好指向下一个正确的基本块。
此时CFG
图如下:
根据基本块的后继基本块数量,决定是否在基本块中添加更新switchVar
(路由变量)的指令,使代码流能够进入正确的基本块中。
将基本块分为三种类型进行处理:
此时CFG
图如下:
优化函数中的堆栈分配
对应具体代码如下:
这个函数处理了两种类型的指令:
PHI 指令
PHI 指令我们前面介绍过。因为PHI指令是基于前驱基本块的指令,前驱基本块被打乱了,PHI指令会出现错误,因此需要对PHI指令进行修复。
含有逃逸变量的指令
逃逸变量指的是在当前基本块中被定义,在其他的基本块中被引用了的变量。这类逃逸变量在编译(LLVM IR->目标平台机器代码)时会出现分不清定义和引用顺序的问题,因此也需要进行修复。
DemoteRegToStack
函数用于将存储指令结果值的虚拟寄存器替换为堆栈上的局部变量。具体而言,首先创建Alloca
指令,插入到函数的入口基本块中,然后如果该指令是Invoke
指令,则进行基本块分割,然后对于使用逃逸变量的基本块,采用Load
指令从堆栈中加载变量的值,最后创建Store
将逃逸变量的值存储到堆栈中。
DemotePHIToStack
函数用于将存储PHI
节点的结果值的虚拟寄存器替换为堆栈上的局部变量。具体而言是创建Alloca
指令,插入到函数的入口基本块中,对于PHI节点的每一个前驱基本块,插入一个Store
指令,将前驱基本块传递过来的值存储到堆栈中。之后在PHI
节点所在的位置插入一个Load
指令,将之前存储在堆栈中的值加载出来。
简而言之,DemotexxxToStack
函数就是使用Alloca
、Store
、Load
指令来代替这些需要待修复的指令。
从runOnFunction
函数入手看:
这部分主要是调用bogus
函数进行虚假控制流混淆,然后调用doF
函数替换在bogus
函数中创建的永真条件跳转指令。我们先来看bogus
函数然后再看doF
函数。
外面一层while
循环是循环虚假控制流混淆次数,对于每次混淆,先将函数的所有基本块加入到basicBlocks
中,然后内层while
循环遍历每个基本块,生成对应的混淆概率,如果满足预设混淆概率,就调用addBogusFlow
函数进行混淆。
首先是获取分割点,然后对要混淆的基本块进行基本块分割,新的基本块的名字为originalBB
。
此时,CFG
的情况如下:
然后是通过createAlteredBasicBlock
函数(这个函数主要是根据传入的基本块fork出新的基本块,然后进行修正和垃圾指令填充)创建一个名为alteredBB
基本块,删除alteredBB
和basicBlock
末尾的分支指令。
此时,CFG
的情况如下:
接下来是创建了一个永真的Fcmp
指令(因为1.0 == 1.0),并以该指令为条件码创建条件跳转指令,都插入到basicBlock
的末尾,如果为True
,跳转到originalBB
,否则跳转到alteredBB
。之后创建从alteredBB
跳转到originalBB
的跳转指令。
此时,CFG
的情况如下:
最后,以originalBB
的末尾跳转指令分割originalBB
,新的基本块名为originalBBpart2
,删除originalBB
末尾的跳转指令(跳转到originalBBpart2
),然后创建一个永真的Fcmp
指令,并以该指令为条件码创建条件跳转指令,都插入到originalBB
的末尾,如果为True
,跳转到originalBBpart2
,否则跳转到alteredBB
。
此时,CFG
的情况如下:
首先调用CloneBasicBlock
函数从basicBlock
中克隆alteredBB
,这个basicBlock
是待混淆的基本块通过splitBasicBlock
函数分割出来的新的基本块。
然后是修复alteredBB
,主要是重映射指令中的操作数和PHINode
的前驱基本块。
最后是往alteredBB
中添加垃圾指令。
首先是创建两个全局变量x
,y
,初始值为0。
然后是遍历指令,将永真条件跳转指令加入到toEdit
中,以及将对应的永真比较指令加入到toDelete
中。
接下来是遍历toEdit
中存放的永真条件跳转指令,创建条件码x*(x-1)%2 == 0 || y < 10
,以该条件码创建条件跳转分支,然后删除之前的永真条件跳转指令。最后删除toDelete
中存放的永真比较指令。
参考:
LLVM Concepts — llvmpy 0.9.0 documentation(phi node)
LLVM API 官方文档
Obfuscator-llvm源码分析 - 知乎 (zhihu.com)(有详细的CFG图)
[原创]基于LLVM Pass实现控制流平坦化-软件逆向-看雪-安全社区|安全招聘|kanxue.com(flatten混淆)
OLLVM控制流平坦化的改进 - 知乎 (zhihu.com)(flatten混淆)
[原创]OLLVM控制流平坦化之fixStack解析-软件逆向-看雪-安全社区|安全招聘|kanxue.com(fixStack函数)
https://bbs.kanxue.com/thread-266201.htm(BogusControlFlow混淆)
bool
Substitution::runOnFunction(Function &F) {
if
(ObfTimes <= 0) {
errs()<<
"Substitution application number -sub_loop=x must be x > 0"
;
return
false
;
}
Function *tmp = &F;
if
(toObfuscate(flag, tmp,
"sub"
)) {
substitute(tmp);
return
true
;
}
return
false
;
}
bool
Substitution::runOnFunction(Function &F) {
if
(ObfTimes <= 0) {
errs()<<
"Substitution application number -sub_loop=x must be x > 0"
;
return
false
;
}
Function *tmp = &F;
if
(toObfuscate(flag, tmp,
"sub"
)) {
substitute(tmp);
return
true
;
}
return
false
;
}
bool
Substitution::substitute(Function *f) {
Function *tmp = f;
int
times = ObfTimes;
do
{
for
(Function::iterator bb = tmp->begin(); bb != tmp->end(); ++bb) {
for
(BasicBlock::iterator inst = bb->begin(); inst != bb->end(); ++inst) {
if
(inst->isBinaryOp()) {
switch
(inst->getOpcode()) {
case
BinaryOperator::Add:
(
this
->*funcAdd[llvm::cryptoutils->get_range(NUMBER_ADD_SUBST)])(
cast<BinaryOperator>(inst));
++Add;
break
;
case
BinaryOperator::Sub:
(
this
->*funcSub[llvm::cryptoutils->get_range(NUMBER_SUB_SUBST)])(
cast<BinaryOperator>(inst));
++Sub;
break
;
...
}
}
}
}
}
while
(--times > 0);
return
false
;
}
bool
Substitution::substitute(Function *f) {
Function *tmp = f;
int
times = ObfTimes;
do
{
for
(Function::iterator bb = tmp->begin(); bb != tmp->end(); ++bb) {
for
(BasicBlock::iterator inst = bb->begin(); inst != bb->end(); ++inst) {
if
(inst->isBinaryOp()) {
switch
(inst->getOpcode()) {
case
BinaryOperator::Add:
(
this
->*funcAdd[llvm::cryptoutils->get_range(NUMBER_ADD_SUBST)])(
cast<BinaryOperator>(inst));
++Add;
break
;
case
BinaryOperator::Sub:
(
this
->*funcSub[llvm::cryptoutils->get_range(NUMBER_SUB_SUBST)])(
cast<BinaryOperator>(inst));
++Sub;
break
;
...
}
}
}
}
}
while
(--times > 0);
return
false
;
}
void
Substitution::addNeg(BinaryOperator *bo) {
BinaryOperator *op = NULL;
if
(bo->getOpcode() == Instruction::Add) {
op = BinaryOperator::CreateNeg(bo->getOperand(1),
""
, bo);
op = BinaryOperator::Create(Instruction::Sub, bo->getOperand(0), op,
""
, bo);
bo->replaceAllUsesWith(op);
}
}
void
Substitution::addNeg(BinaryOperator *bo) {
BinaryOperator *op = NULL;
if
(bo->getOpcode() == Instruction::Add) {
op = BinaryOperator::CreateNeg(bo->getOperand(1),
""
, bo);
op = BinaryOperator::Create(Instruction::Sub, bo->getOperand(0), op,
""
, bo);
bo->replaceAllUsesWith(op);
}
}
void
printBasicBlockInfo(BasicBlock* bb){
for
(BasicBlock::iterator inst = bb->begin(); inst != bb->end(); ++inst){
inst->print(errs());
errs() <<
"\n"
;
}
}
void
Substitution::addNeg(BinaryOperator *bo) {
BinaryOperator *op = NULL;
if
(bo->getOpcode() == Instruction::Add) {
errs() <<
"current BinaryOperator:"
;
bo->print(errs());
errs() <<
"\n"
;
BasicBlock* bb = bo->getParent();
errs() <<
"BasicBlock before CreateNeg: "
<<
"\n"
;
printBasicBlockInfo(bb);
op = BinaryOperator::CreateNeg(bo->getOperand(1),
""
, bo);
errs() <<
"BasicBlock after CreateNeg and before Create: "
<<
"\n"
;
printBasicBlockInfo(bb);
op = BinaryOperator::Create(Instruction::Sub, bo->getOperand(0), op,
""
, bo);
errs() <<
"BasicBlock after Create and before replaceAllUsesWith: "
<<
"\n"
;
printBasicBlockInfo(bb);
bo->replaceAllUsesWith(op);
errs() <<
"BasicBlock after replaceAllUsesWith: "
<<
"\n"
;
printBasicBlockInfo(bb);
}
}
void
printBasicBlockInfo(BasicBlock* bb){
for
(BasicBlock::iterator inst = bb->begin(); inst != bb->end(); ++inst){
inst->print(errs());
errs() <<
"\n"
;
}
}
void
Substitution::addNeg(BinaryOperator *bo) {
BinaryOperator *op = NULL;
if
(bo->getOpcode() == Instruction::Add) {
errs() <<
"current BinaryOperator:"
;
bo->print(errs());
errs() <<
"\n"
;
BasicBlock* bb = bo->getParent();
errs() <<
"BasicBlock before CreateNeg: "
<<
"\n"
;
printBasicBlockInfo(bb);
op = BinaryOperator::CreateNeg(bo->getOperand(1),
""
, bo);
errs() <<
"BasicBlock after CreateNeg and before Create: "
<<
"\n"
;
printBasicBlockInfo(bb);
op = BinaryOperator::Create(Instruction::Sub, bo->getOperand(0), op,
""
, bo);
errs() <<
"BasicBlock after Create and before replaceAllUsesWith: "
<<
"\n"
;
printBasicBlockInfo(bb);
bo->replaceAllUsesWith(op);
errs() <<
"BasicBlock after replaceAllUsesWith: "
<<
"\n"
;
printBasicBlockInfo(bb);
}
}
current Function: main
current BinaryOperator: %7 = add nsw i32 %5, %6
BasicBlock before CreateNeg:
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%3 = alloca i32, align 4
%4 = alloca i32, align 4
store i32 0, i32* %1, align 4
store i32 1, i32* %3, align 4
store i32 2, i32* %4, align 4
%5 = load i32, i32* %3, align 4
%6 = load i32, i32* %4, align 4
%7 = add nsw i32 %5, %6
store i32 %7, i32* %2, align 4
ret i32 0
BasicBlock after CreateNeg and before Create:
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%3 = alloca i32, align 4
%4 = alloca i32, align 4
store i32 0, i32* %1, align 4
store i32 1, i32* %3, align 4
store i32 2, i32* %4, align 4
%5 = load i32, i32* %3, align 4
%6 = load i32, i32* %4, align 4
%7 = sub i32 0, %6
%8 = add nsw i32 %5, %6
store i32 %8, i32* %2, align 4
ret i32 0
BasicBlock after Create and before replaceAllUsesWith:
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%3 = alloca i32, align 4
%4 = alloca i32, align 4
store i32 0, i32* %1, align 4
store i32 1, i32* %3, align 4
store i32 2, i32* %4, align 4
%5 = load i32, i32* %3, align 4
%6 = load i32, i32* %4, align 4
%7 = sub i32 0, %6
%8 = sub i32 %5, %7
%9 = add nsw i32 %5, %6
store i32 %9, i32* %2, align 4
ret i32 0
BasicBlock after replaceAllUsesWith:
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%3 = alloca i32, align 4
%4 = alloca i32, align 4
store i32 0, i32* %1, align 4
store i32 1, i32* %3, align 4
store i32 2, i32* %4, align 4
%5 = load i32, i32* %3, align 4
%6 = load i32, i32* %4, align 4
%7 = sub i32 0, %6
%8 = sub i32 %5, %7
%9 = add nsw i32 %5, %6
store i32 %8, i32* %2, align 4
ret i32 0
current Function: main
current BinaryOperator: %7 = add nsw i32 %5, %6
BasicBlock before CreateNeg:
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%3 = alloca i32, align 4
%4 = alloca i32, align 4
store i32 0, i32* %1, align 4
store i32 1, i32* %3, align 4
store i32 2, i32* %4, align 4
%5 = load i32, i32* %3, align 4
%6 = load i32, i32* %4, align 4
%7 = add nsw i32 %5, %6
store i32 %7, i32* %2, align 4
ret i32 0
BasicBlock after CreateNeg and before Create:
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%3 = alloca i32, align 4
%4 = alloca i32, align 4
store i32 0, i32* %1, align 4
store i32 1, i32* %3, align 4
store i32 2, i32* %4, align 4
%5 = load i32, i32* %3, align 4
%6 = load i32, i32* %4, align 4
%7 = sub i32 0, %6
%8 = add nsw i32 %5, %6
store i32 %8, i32* %2, align 4
ret i32 0
BasicBlock after Create and before replaceAllUsesWith:
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%3 = alloca i32, align 4
%4 = alloca i32, align 4
store i32 0, i32* %1, align 4
store i32 1, i32* %3, align 4
store i32 2, i32* %4, align 4
%5 = load i32, i32* %3, align 4
%6 = load i32, i32* %4, align 4
%7 = sub i32 0, %6
%8 = sub i32 %5, %7
%9 = add nsw i32 %5, %6
store i32 %9, i32* %2, align 4
ret i32 0
BasicBlock after replaceAllUsesWith:
%1 = alloca i32, align 4
%2 = alloca i32, align 4
%3 = alloca i32, align 4
%4 = alloca i32, align 4
store i32 0, i32* %1, align 4
store i32 1, i32* %3, align 4
store i32 2, i32* %4, align 4
%5 = load i32, i32* %3, align 4
%6 = load i32, i32* %4, align 4
%7 = sub i32 0, %6
%8 = sub i32 %5, %7
%9 = add nsw i32 %5, %6
store i32 %8, i32* %2, align 4
ret i32 0
bool
SplitBasicBlock::runOnFunction(Function &F) {
if
(!((SplitNum > 1) && (SplitNum <= 10))) {
errs()<<
"Split application basic block percentage -split_num=x must be 1 < x <= 10"
;
return
false
;
}
Function *tmp = &F;
if
(toObfuscate(flag, tmp,
"split"
)) {
split(tmp);
++Split;
}
return
false
;
}
bool
SplitBasicBlock::runOnFunction(Function &F) {
if
(!((SplitNum > 1) && (SplitNum <= 10))) {
errs()<<
"Split application basic block percentage -split_num=x must be 1 < x <= 10"
;
return
false
;
}
Function *tmp = &F;
if
(toObfuscate(flag, tmp,
"split"
)) {
split(tmp);
++Split;
}
return
false
;
}
void
SplitBasicBlock::split(Function *f) {
std::vector<BasicBlock *> origBB;
int
splitN = SplitNum;
for
(Function::iterator I = f->begin(), IE = f->end(); I != IE; ++I) {
origBB.push_back(&*I);
}
for
(std::vector<BasicBlock *>::iterator I = origBB.begin(),IE = origBB.end();I != IE; ++I) {
BasicBlock *curr = *I;
if
(curr->size() < 2 || containsPHI(curr)) {
continue
;
}
if
((
size_t
)splitN > curr->size()) {
splitN = curr->size() - 1;
}
std::vector<
int
> test;
for
(unsigned i = 1; i < curr->size(); ++i) {
test.push_back(i);
}
if
(test.size() != 1) {
shuffle(test);
std::sort(test.begin(), test.begin() + splitN);
}
BasicBlock::iterator it = curr->begin();
BasicBlock *toSplit = curr;
int
last = 0;
for
(
int
i = 0; i < splitN; ++i) {
for
(
int
j = 0; j < test[i] - last; ++j) {
++it;
}
last = test[i];
if
(toSplit->size() < 2)
continue
;
toSplit = toSplit->splitBasicBlock(it, toSplit->getName() +
".split"
);
}
++Split;
}
}
void
SplitBasicBlock::split(Function *f) {
std::vector<BasicBlock *> origBB;
int
splitN = SplitNum;
for
(Function::iterator I = f->begin(), IE = f->end(); I != IE; ++I) {
origBB.push_back(&*I);
}
for
(std::vector<BasicBlock *>::iterator I = origBB.begin(),IE = origBB.end();I != IE; ++I) {
BasicBlock *curr = *I;
if
(curr->size() < 2 || containsPHI(curr)) {
continue
;
}
if
((
size_t
)splitN > curr->size()) {
splitN = curr->size() - 1;
}
std::vector<
int
> test;
for
(unsigned i = 1; i < curr->size(); ++i) {
test.push_back(i);
}
if
(test.size() != 1) {
shuffle(test);
std::sort(test.begin(), test.begin() + splitN);
}
BasicBlock::iterator it = curr->begin();
BasicBlock *toSplit = curr;
int
last = 0;
for
(
int
i = 0; i < splitN; ++i) {
for
(
int
j = 0; j < test[i] - last; ++j) {
++it;
}
last = test[i];
if
(toSplit->size() < 2)
continue
;
toSplit = toSplit->splitBasicBlock(it, toSplit->getName() +
".split"
);
}
++Split;
}
}
a = 1;
if
(v < 10)
a = 2;
b = a;
a = 1;
if
(v < 10)
a = 2;
b = a;
a1 = 1;
if
(v < 10)
a2 = 2;
b = PHI(a1, a2);
a1 = 1;
if
(v < 10)
a2 = 2;
b = PHI(a1, a2);
BasicBlock *BasicBlock::splitBasicBlock(iterator I,
const
Twine &BBName) {
assert
(getTerminator() &&
"Can't use splitBasicBlock on degenerate BB!"
);
assert
(I != InstList.end() &&
"Trying to get me to create degenerate basic block!"
);
BasicBlock *New = BasicBlock::Create(getContext(), BBName, getParent(),
this
->getNextNode());
DebugLoc Loc = I->getDebugLoc();
New->getInstList().splice(New->end(),
this
->getInstList(), I, end());
BranchInst *BI = BranchInst::Create(New,
this
);
BI->setDebugLoc(Loc);
for
(succ_iterator I = succ_begin(New), E = succ_end(New); I != E; ++I) {
BasicBlock *Successor = *I;
PHINode *PN;
for
(BasicBlock::iterator II = Successor->begin(); (PN = dyn_cast<PHINode>(II)); ++II) {
int
IDX = PN->getBasicBlockIndex(
this
);
while
(IDX != -1) {
PN->setIncomingBlock((unsigned)IDX, New);
IDX = PN->getBasicBlockIndex(
this
);
}
}
}
return
New;
}
BasicBlock *BasicBlock::splitBasicBlock(iterator I,
const
Twine &BBName) {
assert
(getTerminator() &&
"Can't use splitBasicBlock on degenerate BB!"
);
assert
(I != InstList.end() &&
"Trying to get me to create degenerate basic block!"
);
BasicBlock *New = BasicBlock::Create(getContext(), BBName, getParent(),
this
->getNextNode());
DebugLoc Loc = I->getDebugLoc();
New->getInstList().splice(New->end(),
this
->getInstList(), I, end());
BranchInst *BI = BranchInst::Create(New,
this
);
BI->setDebugLoc(Loc);
for
(succ_iterator I = succ_begin(New), E = succ_end(New); I != E; ++I) {
BasicBlock *Successor = *I;
PHINode *PN;
for
(BasicBlock::iterator II = Successor->begin(); (PN = dyn_cast<PHINode>(II)); ++II) {
int
IDX = PN->getBasicBlockIndex(
this
);
while
(IDX != -1) {
PN->setIncomingBlock((unsigned)IDX, New);
IDX = PN->getBasicBlockIndex(
this
);
}
}
}
return
New;
}
char
scrambling_key[16];
llvm::cryptoutils->get_bytes(scrambling_key, 16);
char
scrambling_key[16];
llvm::cryptoutils->get_bytes(scrambling_key, 16);
FunctionPass *lower = createLowerSwitchPass();
lower->runOnFunction(*f);
FunctionPass *lower = createLowerSwitchPass();
lower->runOnFunction(*f);
for
(Function::iterator i = f->begin(); i != f->end(); ++i) {
BasicBlock *tmp = &*i;
origBB.push_back(tmp);
BasicBlock *bb = &*i;
if
(isa<InvokeInst>(bb->getTerminator())) {
return
false
;
}
}
if
(origBB.size() <= 1) {
return
false
;
}
origBB.erase(origBB.begin());
for
(Function::iterator i = f->begin(); i != f->end(); ++i) {
BasicBlock *tmp = &*i;
origBB.push_back(tmp);
BasicBlock *bb = &*i;
if
(isa<InvokeInst>(bb->getTerminator())) {
return
false
;
}
}
if
(origBB.size() <= 1) {
return
false
;
}
origBB.erase(origBB.begin());
Function::iterator tmp = f->begin();
BasicBlock *insert = &*tmp;
BranchInst *br = NULL;
if
(isa<BranchInst>(insert->getTerminator())) {
br = cast<BranchInst>(insert->getTerminator());
}
if
((br != NULL && br->isConditional()) || insert->getTerminator()->getNumSuccessors() > 1) {
BasicBlock::iterator i = insert->end();
--i;
if
(insert->size() > 1) {
--i;
}
BasicBlock *tmpBB = insert->splitBasicBlock(i,
"first"
);
origBB.insert(origBB.begin(), tmpBB);
}
insert->getTerminator()->eraseFromParent();
Function::iterator tmp = f->begin();
BasicBlock *insert = &*tmp;
BranchInst *br = NULL;
if
(isa<BranchInst>(insert->getTerminator())) {
br = cast<BranchInst>(insert->getTerminator());
}
if
((br != NULL && br->isConditional()) || insert->getTerminator()->getNumSuccessors() > 1) {
BasicBlock::iterator i = insert->end();
--i;
if
(insert->size() > 1) {
--i;
}
BasicBlock *tmpBB = insert->splitBasicBlock(i,
"first"
);
origBB.insert(origBB.begin(), tmpBB);
}
insert->getTerminator()->eraseFromParent();
switchVar =
new
AllocaInst(Type::getInt32Ty(f->getContext()), 0,
"switchVar"
, insert);
new
StoreInst(ConstantInt::get(Type::getInt32Ty(f->getContext()), llvm::cryptoutils->scramble32(0, scrambling_key)), switchVar, insert);
loopEntry = BasicBlock::Create(f->getContext(),
"loopEntry"
, f, insert);
loopEnd = BasicBlock::Create(f->getContext(),
"loopEnd"
, f, insert);
load =
new
LoadInst(switchVar,
"switchVar"
, loopEntry);
insert->moveBefore(loopEntry);
BranchInst::Create(loopEntry, insert);
BranchInst::Create(loopEntry, loopEnd);
BasicBlock *swDefault = BasicBlock::Create(f->getContext(),
"switchDefault"
, f, loopEnd);
BranchInst::Create(loopEnd, swDefault);
switchI = SwitchInst::Create(&*f->begin(), swDefault, 0, loopEntry);
switchI->setCondition(load);
f->begin()->getTerminator()->eraseFromParent();
BranchInst::Create(loopEntry, &*f->begin());
switchVar =
new
AllocaInst(Type::getInt32Ty(f->getContext()), 0,
"switchVar"
, insert);
new
StoreInst(ConstantInt::get(Type::getInt32Ty(f->getContext()), llvm::cryptoutils->scramble32(0, scrambling_key)), switchVar, insert);
loopEntry = BasicBlock::Create(f->getContext(),
"loopEntry"
, f, insert);
loopEnd = BasicBlock::Create(f->getContext(),
"loopEnd"
, f, insert);
load =
new
LoadInst(switchVar,
"switchVar"
, loopEntry);
insert->moveBefore(loopEntry);
BranchInst::Create(loopEntry, insert);
BranchInst::Create(loopEntry, loopEnd);
BasicBlock *swDefault = BasicBlock::Create(f->getContext(),
"switchDefault"
, f, loopEnd);
BranchInst::Create(loopEnd, swDefault);
switchI = SwitchInst::Create(&*f->begin(), swDefault, 0, loopEntry);
switchI->setCondition(load);
f->begin()->getTerminator()->eraseFromParent();
BranchInst::Create(loopEntry, &*f->begin());
for
(vector<BasicBlock *>::iterator b = origBB.begin(); b != origBB.end(); ++b) {
BasicBlock *i = *b;
ConstantInt *numCase = NULL;
i->moveBefore(loopEnd);
numCase = cast<ConstantInt>(ConstantInt::get(switchI->getCondition()->getType(),
llvm::cryptoutils->scramble32(switchI->getNumCases(), scrambling_key)));
switchI->addCase(numCase, i);
}
for
(vector<BasicBlock *>::iterator b = origBB.begin(); b != origBB.end(); ++b) {
BasicBlock *i = *b;
ConstantInt *numCase = NULL;
i->moveBefore(loopEnd);
numCase = cast<ConstantInt>(ConstantInt::get(switchI->getCondition()->getType(),
llvm::cryptoutils->scramble32(switchI->getNumCases(), scrambling_key)));
switchI->addCase(numCase, i);
}
llvm::cryptoutils->scramble32(0, scrambling_key))
llvm::cryptoutils->scramble32(0, scrambling_key))
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课