警告
本文最后更新于 2023-03-30,文中内容可能已过时。
goron使用的控制流平坦化是ollvm原生的
1
2
3
4
|
// SCRAMBLER
char scrambling_key[16];
llvm::cryptoutils->get_bytes(scrambling_key, 16);
// END OF SCRAMBLER
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
// Lower switch
#if LLVM_VERSION_MAJOR * 10 + LLVM_VERSION_MINOR >= 90
FunctionPass *lower = createLegacyLowerSwitchPass();
#else
FunctionPass *lower = createLowerSwitchPass();
#endif
lower->runOnFunction(*f);
bool LowerSwitch::runOnFunction(Function &F) {
bool Changed = false;
SmallPtrSet<BasicBlock*, 8> DeleteList;
// 遍历function获取基本块
for (Function::iterator I = F.begin(), E = F.end(); I != E; ) {
BasicBlock *Cur = &*I++; // Advance over block so we don't traverse new blocks
// If the block is a dead Default block that will be deleted later, don't
// waste time processing it.
if (DeleteList.count(Cur))
continue;
// 如果块的末尾指令是switch指令,则需要处理
if (SwitchInst *SI = dyn_cast<SwitchInst>(Cur->getTerminator())) {
Changed = true;
processSwitchInst(SI, DeleteList);
}
}
for (BasicBlock* BB: DeleteList) {
DeleteDeadBlock(BB);
}
return Changed;
}
|
Lower switch的目的是去除原生函数的switch结构降级成if结构
1
2
3
4
5
6
7
8
9
10
|
// Save all original BB
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;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
// Remove first BB
// 删除第一个块并做一些处理
origBB.erase(origBB.begin());
// Get a pointer on the first BB
// 获取第一个块指针
Function::iterator tmp = f->begin(); //++tmp;
BasicBlock *insert = &*tmp;
// If main begin with an if
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;
}
// 将条件跳转的语句切割出来,成为一个新的基本块,并插入到vector开头
BasicBlock *tmpBB = insert->splitBasicBlock(i, "first");
origBB.insert(origBB.begin(), tmpBB);
}
// Remove jump
// 删除第一个基本块最后的末尾跳转
insert->getTerminator()->eraseFromParent();
|
因为平坦化要求第一个基本块只能有一个后继基本块,如果第一个基本块末尾就是条件跳转(有两个或多个后继块)就无法进行后面的平坦化操作
1
2
3
4
5
6
7
8
|
// Create switch variable and set as it
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);
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
// Create main loop
// 创建loopEntry、loopEntry两个基本块
loopEntry = BasicBlock::Create(f->getContext(), "loopEntry", f, insert);
loopEnd = BasicBlock::Create(f->getContext(), "loopEnd", f, insert);
// load switchVar 变量
load = new LoadInst(switchVar, "switchVar", loopEntry);
// Move first BB on top
insert->moveBefore(loopEntry);
// 构建顺序insert->loopEntry
BranchInst::Create(loopEntry, insert);
// loopEnd jump to loopEntry
// 构建顺序loopEnd->loopEntry
BranchInst::Create(loopEntry, loopEnd);
BasicBlock *swDefault =
BasicBlock::Create(f->getContext(), "switchDefault", f, loopEnd);
// 构建swDefault->loopEnd
BranchInst::Create(loopEnd, swDefault);
// Create switch instruction itself and set condition
switchI = SwitchInst::Create(&*f->begin(), swDefault, 0, loopEntry);
switchI->setCondition(load);
// Remove branch jump from 1st BB and make a jump to the while
f->begin()->getTerminator()->eraseFromParent();
// 构建顺序第一个块到loopEntry
BranchInst::Create(loopEntry, &*f->begin());
|
整体顺序就是第一个块->loopEntry,swDefault->loopEnd,loopEnd->loopEntry
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
// Put all BB in the switch
// 遍历每个块
for (vector<BasicBlock *>::iterator b = origBB.begin(); b != origBB.end();
++b) {
BasicBlock *i = *b;
ConstantInt *numCase = NULL;
// 块放在loopEnd前面
// Move the BB inside the switch (only visual, no code logic)
i->moveBefore(loopEnd);
// 设置随机值并加入到switch结构中
// Add case to switch
numCase = cast<ConstantInt>(ConstantInt::get(
switchI->getCondition()->getType(),
llvm::cryptoutils->scramble32(switchI->getNumCases(), scrambling_key)));
switchI->addCase(numCase, i);
}
|
这里只是单纯的将块和随机变量绑定,并没有指定块的跳转顺序,下面要开始调整基本块之间的关系了
遍历每个块,分别对不同类型的块做处理,这里有三种情况
1
2
3
4
|
// Ret BB
if (i->getTerminator()->getNumSuccessors() == 0) {
continue;
}
|
如果这个块的末尾指令没有后继,则表明这个块是结束块,无需再回到分发器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
// If it's a non-conditional jump
// 如果这个块末尾指令不是条件指令
if (i->getTerminator()->getNumSuccessors() == 1) {
// Get successor and delete terminator
// 获取后继基本块
BasicBlock *succ = i->getTerminator()->getSuccessor(0);
// 删除该块到后继块的跳转
i->getTerminator()->eraseFromParent();
// Get next case
// 获取后继基本块的case值
numCase = switchI->findCaseDest(succ);
// 如果case为空,表示是default分支
// If next case == default case (switchDefault)
if (numCase == NULL) {
numCase = cast<ConstantInt>(
ConstantInt::get(switchI->getCondition()->getType(),
llvm::cryptoutils->scramble32(
switchI->getNumCases() - 1, scrambling_key)));
}
// numCase = MySecret - (MySecret - numCase)
// X = MySecret - numCase
Constant *X;
if (SecretInfo) {
X = ConstantExpr::getSub(SecretInfo->SecretCI, numCase);
} else {
X = ConstantExpr::getSub(Zero, numCase);
}
// 获取真实case值
Value *newNumCase = BinaryOperator::Create(Instruction::Sub, MySecret, X, "", i);
// Update switchVar and jump to the end of loop
// 末尾更新switchVar值
new StoreInst(newNumCase, load->getPointerOperand(), i);
// 跳转到loopEnd
BranchInst::Create(loopEnd, i);
continue;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
// If it's a conditional jump
// 如果末尾指令是分支指令
if (i->getTerminator()->getNumSuccessors() == 2) {
// Get next cases
// 获取两个后继的case值
ConstantInt *numCaseTrue =
switchI->findCaseDest(i->getTerminator()->getSuccessor(0));
ConstantInt *numCaseFalse =
switchI->findCaseDest(i->getTerminator()->getSuccessor(1));
// 判断defalut的情况
// Check if next case == default case (switchDefault)
if (numCaseTrue == NULL) {
numCaseTrue = cast<ConstantInt>(
ConstantInt::get(switchI->getCondition()->getType(),
llvm::cryptoutils->scramble32(
switchI->getNumCases() - 1, scrambling_key)));
}
if (numCaseFalse == NULL) {
numCaseFalse = cast<ConstantInt>(
ConstantInt::get(switchI->getCondition()->getType(),
llvm::cryptoutils->scramble32(
switchI->getNumCases() - 1, scrambling_key)));
}
// 获取真实值
Constant *X, *Y;
if (SecretInfo) {
X = ConstantExpr::getSub(SecretInfo->SecretCI, numCaseTrue);
Y = ConstantExpr::getSub(SecretInfo->SecretCI, numCaseFalse);
} else {
X = ConstantExpr::getSub(Zero, numCaseTrue);
Y = ConstantExpr::getSub(Zero, numCaseFalse);
}
Value *newNumCaseTrue = BinaryOperator::Create(Instruction::Sub, MySecret, X, "", i->getTerminator());
Value *newNumCaseFalse = BinaryOperator::Create(Instruction::Sub, MySecret, Y, "", i->getTerminator());
// Create a SelectInst
// 构造条件指令
BranchInst *br = cast<BranchInst>(i->getTerminator());
SelectInst *sel =
SelectInst::Create(br->getCondition(), newNumCaseTrue, newNumCaseFalse, "",
i->getTerminator());
// Erase terminator
// 删除结尾跳转指令
i->getTerminator()->eraseFromParent();
// Update switchVar and jump to the end of loop
// 末尾添加条件指令
new StoreInst(sel, load->getPointerOperand(), i);
// 跳转到loopEnd
BranchInst::Create(loopEnd, i);
continue;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
void fixStack(Function *f) {
// Try to remove phi node and demote reg to stack
std::vector<PHINode *> tmpPhi;
std::vector<Instruction *> tmpReg;
BasicBlock *bbEntry = &*f->begin();
do {
tmpPhi.clear();
tmpReg.clear();
for (Function::iterator i = f->begin(); i != f->end(); ++i) {
for (BasicBlock::iterator j = i->begin(); j != i->end(); ++j) {
if (isa<PHINode>(j)) {
PHINode *phi = cast<PHINode>(j);
tmpPhi.push_back(phi);
continue;
}
if (!(isa<AllocaInst>(j) && j->getParent() == bbEntry) &&
(valueEscapes(&*j) || j->isUsedOutsideOfBlock(&*i))) {
tmpReg.push_back(&*j);
continue;
}
}
}
for (unsigned int i = 0; i != tmpReg.size(); ++i) {
DemoteRegToStack(*tmpReg.at(i), f->begin()->getTerminator());
}
for (unsigned int i = 0; i != tmpPhi.size(); ++i) {
DemotePHIToStack(tmpPhi.at(i), f->begin()->getTerminator());
}
} while (tmpReg.size() != 0 || tmpPhi.size() != 0);
}
|
- 调用lower switch去除当前函数的switch结构
- 保存所有块并单独刨除第一个块
- 创建switch变量并设置初始值
- 设置基本骨架frist->loopEntry->switch->loopEnd->loopEntry
- 装入基本块
- 重新计算switchVar
- 栈修复