控制流平坦化——Flattening Control Flow

过程如图,即将正常控制流中基本块之间的跳转关系删除,用一个集中的分发块来调度基本块的执行顺序。

1666845747713

具体代码实现原理

1666845861750

在写具体的控制流平坦化的代码实现之前,我们需要进行一些宏定义来让我们写起来更加方便

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#ifndef _UTILS_H_
#define _UTILS_H_

#include "llvm/IR/Function.h"
#define INIT_CONTEXT(F) CONTEXT = &F.getContext()
#define TYPE_I32 Type::getInt32Ty(*CONTEXT)
#define CONST_I32(V) ConstantInt::get(TYPE_I32, V, false)
#define CONST(T, V) ConstantInt::get(T, V)

extern llvm::LLVMContext *CONTEXT;

namespace llvm
{
void fixStack(Function &F);
BasicBlock* createCloneBasicBlock(BasicBlock *BB);
}

#endif

下面是具体实现

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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Transforms/Utils.h"
#include "llvm/Transforms/Utils/Local.h"
#include "SplitBasicBlock.h"
#include "Utils.h"
#include <vector>
#include <cstdlib>
#include <ctime>
using namespace llvm;
using std::vector;

namespace // 我们自己的命名空间
{
class Flattening : public FunctionPass // 继承FunctionPass类
{
public:
static char ID; // 变量
Flattening() : FunctionPass(ID)
{
srand(time(0));
} // 构造函数

void flatten(Function &F);
bool runOnFunction(Function & F);
};
}
bool Flattening::runOnFunction(Function & F)
{
INIT_CONTEXT(F); //初始化获取上下文
flatten(F);
return true;
}

void Flattening::flatten(Function &F)
{
// 第一步:用vector保存除了入口块以外的基本块
vector<BasicBlock*>orgBB;
for(BasicBlock &BB : F)
{
orgBB.push_back(&BB);
}
orgBB.erase(orgBB.begin()); // 移除入口块
BasicBlock &entryBB = F.getEntryBlock();
if(BranchInst *br = dyn_cast<BranchInst>(entryBB.getTerminator())) // 判断入口块的终结指令是否为条件跳转
{
if(br->isConditional()) // 如果是条件跳转,就把该跳转指令作为一个新的基本块插入到vector的最前面,保证入口块到分发块是一个单向绝对跳转
{
orgBB.insert(orgBB.begin(), entryBB.splitBasicBlock(br));
}
}

// 第二步:创建分发块和返回块
BasicBlock *dispatchBB = BasicBlock::Create(*CONTEXT, "dispatchBB", &F, &entryBB); // Create函数的参数分别是:引用类型的上下文Context,基本块名称,函数名,插入到哪个基本块之前,这里的*CONTEXT已经被宏定义过了,就是F.getContext()
BasicBlock *returnBB = BasicBlock::Create(*CONTEXT, "returnBB", &F, &entryBB);
entryBB.moveBefore(dispatchBB); // 把入口块放到分发块前面,满足物理逻辑
entryBB.getTerminator()->eraseFromParent(); // 去除入口块原先的终结指令
BranchInst::Create(dispatchBB, &entryBB); // 建立entryBB到dispatchBB的跳转
BranchInst::Create(dispatchBB, returnBB); // 返回块原先没有跳转,直接建立到dispatchBB的跳转即可

//第三步:实现分发块的调度功能
int randNumCase = rand(); // 随机数用于case值
AllocaInst *swVarPtr = new AllocaInst(TYPE_I32, 0, "swVar.ptr", entryBB.getTerminator()); // Alloca指令,分配一段空间用于新建switch变量指针,参数为变量类型(TYPE_I32就是getInt32Ty(*CONTEXT)),地址空间(不用管,填成0就好),指令名称,插入到哪个指令前面
new StoreInst(CONST_I32(randNumCase), swVarPtr, entryBB.getTerminator()); // store指令,用于初始化变量,参数分别为Value值(由于是Value类型,所以需要把int转换为属于IR中的ConstantInt::get(TYPE_I32, V, false)),赋值的变量指针,这条指令插入到哪个指令前面
LoadInst *swVar = new LoadInst(TYPE_I32, swVarPtr, "swVar", dispatchBB); // load指令,读取swVarPtr指针空间中的数据,参数为函数类型(I32),指针,变量名称,这条指令插入到dispatchBB的后面
BasicBlock *defaultBB = BasicBlock::Create(*CONTEXT, "defaultBB", &F, returnBB); //创建一个default基本块,如果switch指令没有满足的那么就默认跳转到该基本块然后返回returnBB
BranchInst::Create(returnBB, defaultBB); // 保持default基本块完整性需要加一条终结指令
SwitchInst *swInst = SwitchInst::Create(swVar, defaultBB, 0, dispatchBB); // switch指令,参数为switch变量,默认跳转的基本块,插入到dispatchBB基本块的后面
for(BasicBlock *BB : orgBB) // 遍历之前保存的基本块
{
BB->moveBefore(returnBB); // 把它们移动到返回块前面,符合物理逻辑
swInst->addCase(CONST_I32(randNumCase), BB); // 给switch指令添加分支,参数为case值(也就是随机数),给当前基本块分配该case值
randNumCase = rand(); // 生成一个新的随机数分配后面的基本块
}

// 第四步:实现switch变量的修改,也就是调度变量的自动调整
for(BasicBlock *BB : orgBB)
{
if(BB->getTerminator()->getNumSuccessors() == 0) // 判断终结指令的后继块的数量,如果为0
{
continue; // 没有跳转,不做处理
}
else if (BB->getTerminator()->getNumSuccessors() == 1) // 后继块数量为1,说明是绝对跳转
{
ConstantInt *numCase = swInst->findCaseDest(BB->getTerminator()->getSuccessor(0)); // 创建一个CONST型变量numCase保存后继块的case值
new StoreInst(numCase, swVarPtr, BB->getTerminator()); // store指令,把下一个后继块的case值存入swVarPtr指针空间,那么一次分发块就会分发后继块的case值,该指令插入到当前块的终结指令前面
BB->getTerminator()->eraseFromParent(); // 把原先的终结指令去除
BranchInst::Create(returnBB, BB); //使其返回到returnBB
}
else if(BB->getTerminator()->getNumSuccessors() == 2) // 后继块数量为2,是条件跳转
{
ConstantInt *numCase1 = swInst->findCaseDest(BB->getTerminator()->getSuccessor(0));
ConstantInt *numCase2 = swInst->findCaseDest(BB->getTerminator()->getSuccessor(1));
BranchInst *br = cast<BranchInst>(BB->getTerminator()); // 获取原先的跳转指令,这里可以调用一个LowerSwitch的PASS,把所有的switch指令全部变成branch指令,因此只用判断branch的情况且分支数一定小于等于2
SelectInst *sel = SelectInst::Create(br->getCondition(), numCase1, numCase2, "", BB->getTerminator()); // select指令,类似于三目运算符,参数为条件语句,true的分支返回numCase1,false的分支返回numCase2,这里的sel接收的是返回值
new StoreInst(sel, swVarPtr, BB->getTerminator());
BB->getTerminator()->eraseFromParent();
BranchInst::Create(returnBB, BB);
}
}

// 第五步,修复PHI指令和逃逸变量
fixStack(F);
}

char Flattening::ID = 0; // 初始化ID
static RegisterPass<Flattening> X("fla", "LLVM Flattening");

虚假控制流——Bogus Control Flow

虚假控制流指,通过向正常控制流中插入若干不可达基本块(永远不会被执行的基本块)和由不透明谓词造成的虚假跳转,以产生大量垃圾代码干扰攻击者分析的混淆。

原理

1666846143819

代码实现

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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/IR/Module.h"
#include "SplitBasicBlock.h"
#include "Utils.h"
#include <vector>
#include <cstdlib>
#include <ctime>
using namespace llvm;
using std::vector;
// 混淆次数,次数越多越复杂
static cl::opt<int> obfuTimes("bcf_loop", cl::init(1), cl::desc("Obfuscate a function <bcf_loop> time(s)."));

namespace
{
class BogusControlFlow : public FunctionPass
{
public:
static char ID;
BogusControlFlow() : FunctionPass(ID)
{
srand(time(0));
}

bool runOnFunction(Function &F);

void bogus(BasicBlock *BB); // 对基本块BB进行混淆

Value* createBogusCmp(BasicBlock *insertAfter); //创建永真条件ICMP
};
}

bool BogusControlFlow::runOnFunction(Function &F)
{
INIT_CONTEXT(F);
FunctionPass *pass = createSplitBasicBlockPass();
pass->runOnFunction(F); // 调用基本块分割的Pass
for(int i = 0; i < obfuTimes; i++) // 混淆次数
{
vector<BasicBlock*>origBB;
for(BasicBlock &BB : F)
{
origBB.push_back(&BB);
}
for(BasicBlock *BB : origBB) // 单位是基本块
{
bogus(BB);
}
}
return true;
}

Value* BogusControlFlow::createBogusCmp(BasicBlock *insertAfter)
{
// y < 10 || x * (x + 1) % 2 == 0
Module *M = insertAfter->getModule();
GlobalVariable *xptr = new GlobalVariable(*M, TYPE_I32, false, GlobalValue::CommonLinkage, CONST_I32(0), "x");
GlobalVariable *yptr = new GlobalVariable(*M, TYPE_I32, false, GlobalValue::CommonLinkage, CONST_I32(0), "y"); // 创建x,y全局变量,参数为变量类型,是否为常量,链接方式,初始值,变量名称
LoadInst *x = new LoadInst(TYPE_I32, xptr, "", insertAfter);
LoadInst *y = new LoadInst(TYPE_I32, yptr, "", insertAfter);
ICmpInst *cmp1 = new ICmpInst(*insertAfter, CmpInst::ICMP_SLT, y, CONST_I32(10));
BinaryOperator *op1 = BinaryOperator::CreateAdd(x, CONST_I32(1), "", insertAfter);
BinaryOperator *op2 = BinaryOperator::CreateMul(x, op1, "", insertAfter);
BinaryOperator *op3 = BinaryOperator::CreateSRem(op2, CONST_I32(2), "", insertAfter);
ICmpInst *cmp2 = new ICmpInst(*insertAfter, CmpInst::ICMP_EQ, op3, CONST_I32(0));
return BinaryOperator::CreateOr(cmp1, cmp2, "", insertAfter);
}


void BogusControlFlow::bogus(BasicBlock *entryBB)
{
// 第一步:拆分基本块为entryBB, bodyBB, endBB
BasicBlock *bodyBB = entryBB->splitBasicBlock(entryBB->getFirstNonPHI(), "BodyBB"); // 找到第一个非PHI指令
BasicBlock *endBB = bodyBB->splitBasicBlock(bodyBB->getTerminator(), "endBB"); // endBB只由一条终结指令组成

// 第二步:克隆bodyBB
BasicBlock *cloneBB = createCloneBasicBlock(bodyBB);

// 第三步:构造虚假跳转
entryBB->getTerminator()->eraseFromParent();
bodyBB->getTerminator()->eraseFromParent();
cloneBB->getTerminator()->eraseFromParent(); // 移除原来的跳转

Value *cond1 = createBogusCmp(entryBB); // 在entryBB后面插入比较式
Value *cond2 = createBogusCmp(bodyBB); // 在bodyBB后面插入比较式

BranchInst::Create(bodyBB, cloneBB, cond1, entryBB); // 从entryBB,cond1为真跳转到bodyBB,为假跳转到cloneBB
BranchInst::Create(endBB, cloneBB, cond2, bodyBB); // bodBB,cond1为真跳转到endBB,为假跳转到cloneBB
BranchInst::Create(bodyBB, cloneBB); // cloneBB不会被执行,一个没用的跳转
}

char BogusControlFlow::ID = 0;
static RegisterPass<BogusControlFlow> X("bcf", "Add bogus control flow to each function.");
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include "Utils.h"
#include <vector>
#include "llvm/IR/Instructions.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
#include "llvm/Transforms/Utils/Cloning.h"
using namespace llvm;
using std::vector;

LLVMContext *CONTEXT = nullptr;

void llvm::fixStack(Function &F)
{
vector<PHINode*>orgPHI;
vector<Instruction*>orgReg;
BasicBlock &entryBB = F.getEntryBlock();
for(BasicBlock &BB : F)
{
for(Instruction &I : BB)
{
if(PHINode *PN = dyn_cast<PHINode>(&I)) // 判断是否为PHI指令
{
orgPHI.push_back(PN);
}
else if(!(isa<AllocaInst>(&I) && I.getParent() == &entryBB) && I.isUsedOutsideOfBlock(&BB)) // 如果不是在入口块的alloca指令且在其他基本块被引用了,那么就是逃逸变量
{
orgReg.push_back(&I);
}
}
}

for(PHINode *PN : orgPHI)
{
DemotePHIToStack(PN, entryBB.getTerminator());
}
for(Instruction *I : orgReg)
{
DemoteRegToStack(*I, entryBB.getTerminator());
}
}

BasicBlock* llvm::createCloneBasicBlock(BasicBlock *BB) // 创建克隆基本块
{
// 克隆之前先修复所有逃逸变量
vector<Instruction*> origReg;
BasicBlock &entryBB = BB->getParent()->getEntryBlock();
for(Instruction &I : *BB)
{
if(!(isa<AllocaInst>(&I) && I.getParent() == &entryBB) && I.isUsedOutsideOfBlock(BB))
{
origReg.push_back(&I);
}
}
for(Instruction *I : origReg)
{
DemoteRegToStack(*I, entryBB.getTerminator());
}

ValueToValueMapTy VMap; // 用于建议变量到克隆变量的映射,修复引用
BasicBlock *cloneBB = CloneBasicBlock(BB, VMap, "cloneBB", BB->getParent()); // 克隆BB,参数为基本块,映射,名称,函数(基本块的上一层结构就是函数),这是一个不完全克隆
for(Instruction &I : *cloneBB) // 遍历每一条指令
{
for(int i = 0; i < I.getNumOperands(); i++) // 遍历每一条指令的每一条操作
{
Value *V = MapValue(I.getOperand(i), VMap); //对变量进行替换
if(V) // 检测是否返回空指针
{
I.setOperand(i, V);
}
}
}
return cloneBB;
}

常量替代

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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Support/CommandLine.h"
#include <vector>
#include <cstdlib>
#include <ctime>
#include "Utils.h"
using namespace llvm;
using std::vector;

#define MAX_RAND 32767 // 防止溢出
#define NUMBER_CONST_SUBST 2

static cl::opt<int> obfuTimes("csub_loop", cl::init(1), cl::desc("Obfuscate a function <obfu_time> time(s)."));

namespace
{
class ConstantSubstitution : public FunctionPass
{
public:
static char ID;
ConstantSubstitution() : FunctionPass(ID)
{
srand(time(NULL));
}

bool runOnFunction(Function &F);

void substitute(BinaryOperator *BI);

void linearSubstitute(BinaryOperator *BI, int i);

void bitwiseSubstitute(BinaryOperator *BI, int i);
};
}

bool ConstantSubstitution::runOnFunction(Function &F)
{
INIT_CONTEXT(F);
for(int i = 0; i < obfuTimes; i++)
{
for(BasicBlock &BB : F)
{
vector<Instruction*>origInst;
for(Instruction &I : BB)
{
origInst.push_back(&I);
}
for(Instruction *I : origInst)
{
if(BinaryOperator *BI = dyn_cast<BinaryOperator>(I))
{
if(BI->getType()->isIntegerTy(32))
{
substitute(BI);
}
}
}
}
}
}

void ConstantSubstitution::linearSubstitute(BinaryOperator *BI, int i)
{
//val = ax + by + c
Module *M = BI->getModule();
ConstantInt *val = cast<ConstantInt>(BI->getOperand(i));
int randX = rand() % MAX_RAND, randY = rand() % MAX_RAND;
int randA = rand() % MAX_RAND, randB = rand() % MAX_RAND;
APInt c = val->getValue() - randA * randX - randB * randY;
ConstantInt *constX = CONST(val->getType(), randX);
ConstantInt *constY = CONST(val->getType(), randY);
ConstantInt *constA = CONST(val->getType(), randA);
ConstantInt *constB = CONST(val->getType(), randB);
ConstantInt *constC = (ConstantInt*)CONST(val->getType(), c);
GlobalVariable *xptr = new GlobalVariable(*M, TYPE_I32, false, GlobalValue::PrivateLinkage, constX, "x");
GlobalVariable *yptr = new GlobalVariable(*M, TYPE_I32, false, GlobalValue::PrivateLinkage, constY, "y");
LoadInst *x = new LoadInst(TYPE_I32, xptr, "", BI);
LoadInst *y = new LoadInst(TYPE_I32, yptr, "", BI);
BinaryOperator *op1 = BinaryOperator::CreateMul(constA, x, "", BI);
BinaryOperator *op2 = BinaryOperator::CreateMul(constB, y, "", BI);
BinaryOperator *op3 = BinaryOperator::CreateAdd(op1, op2, "", BI);
BinaryOperator *op4 = BinaryOperator::CreateAdd(op3, constC, "", BI);
BI->setOperand(i, op4);
}

void ConstantSubstitution::bitwiseSubstitute(BinaryOperator *BI, int i)
{
//val = c ^ (x << 5 | y >> 3)
Module *M = BI->getModule();
ConstantInt *val = cast<ConstantInt>(BI->getOperand(i));
int randX = rand() % MAX_RAND, randY = rand() % MAX_RAND;
APInt c = val->getValue() ^ (randX << 5 | randY >> 3);
ConstantInt *constX = CONST(val->getType(), randX);
ConstantInt *constY = CONST(val->getType(), randY);
ConstantInt *const5 = CONST(val->getType(), 5);
ConstantInt *const3 = CONST(val->getType(), 3);
ConstantInt *constC = (ConstantInt*)CONST(val->getType(), c);
GlobalVariable *xptr = new GlobalVariable(*M, TYPE_I32, false, GlobalValue::PrivateLinkage, constX, "x");
GlobalVariable *yptr = new GlobalVariable(*M, TYPE_I32, false, GlobalValue::PrivateLinkage, constY, "y");

LoadInst *x = new LoadInst(TYPE_I32, xptr, "", BI);
LoadInst *y = new LoadInst(TYPE_I32, yptr, "", BI);
BinaryOperator *op1 = BinaryOperator::CreateShl(x, const5, "", BI);
BinaryOperator *op2 = BinaryOperator::CreateLShr(y, const3, "", BI);
BinaryOperator *op3 = BinaryOperator::CreateOr(op1, op2, "", BI);
BinaryOperator *op4 = BinaryOperator::CreateXor(constC, op3, "", BI);
BI->setOperand(i, op4);
}

void ConstantSubstitution::substitute(BinaryOperator *BI)
{
int operateNum = BI->getNumOperands();
for(int i = 0; i < operateNum; i++)
{
if(isa<ConstantInt>(BI->getOperand(i)))
{
int opt = rand() % NUMBER_CONST_SUBST;
switch(opt)
{
case 0:
linearSubstitute(BI, i);
break;
case 1:
bitwiseSubstitute(BI, i);
break;
default:
break;
}
}
}
}

char ConstantSubstitution::ID = 0;
static RegisterPass<ConstantSubstitution> X("csub", "Replace a constant value with equivalent instructions.");

第二种写法:

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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/CFG.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Support/CommandLine.h"
#include "Utils.h"
#include<vector>
#include<algorithm>
#include<ctime>
#include<cstdlib>
using namespace llvm;
namespace
{
struct Pair
{
unsigned int pos;
Value *val;
};
struct ConstantReplace : public ModulePass
{
static char ID;
ConstantReplace() : ModulePass(ID) {}
void handleInstruction(Function *f,Instruction *ii,unsigned int &count)
{
int pos=0;
std::vector<Pair*> updates;
for(User::op_iterator opi=ii->op_begin();opi!=ii->op_end();opi++,pos++)
{
Value *v=*opi;
if(isa<ConstantInt>(*v))
{
ConstantInt *consts=(ConstantInt*)v;
Type *int8ty=Type::getInt8Ty(f->getContext());
Type *int16ty=Type::getInt16Ty(f->getContext());
Type *int32ty=Type::getInt32Ty(f->getContext());
Type *int64ty=Type::getInt64Ty(f->getContext());
std::string name="global_const"+std::to_string(count);
if(consts->getType()==int8ty)
{
unsigned char data=(consts->getValue().getZExtValue())&0xFF;
unsigned char rr=(rand()&0xFF);
unsigned char tt=data^rr;
Value *val1=ConstantInt::get(int8ty,tt);
Value *val2=ConstantInt::get(int8ty,rr);
GlobalVariable *g=(GlobalVariable*)f->getParent()->getOrInsertGlobal(name,int8ty);
g->setInitializer((Constant*)val1);
LoadInst *load=new LoadInst(int8ty,g,"",ii);
Value *vv=BinaryOperator::Create(Instruction::Xor,(Value *)load,(Value *)val2,"",ii);
Pair *node=(Pair*)malloc(sizeof(Pair));
node->pos=pos;
node->val=vv;
updates.push_back(node);
count++;
}
else if(consts->getType()==int16ty)
{
unsigned short data=(consts->getValue().getZExtValue())&0xFFFF;
unsigned short rr=(rand()&0xFFFF);
unsigned short tt=data^rr;
Value *val1=ConstantInt::get(int16ty,tt);
Value *val2=ConstantInt::get(int16ty,rr);
GlobalVariable *g=(GlobalVariable*)f->getParent()->getOrInsertGlobal(name,int16ty);
g->setInitializer((Constant*)val1);
LoadInst *load=new LoadInst(int16ty,g,"",ii);
Value *vv=BinaryOperator::Create(Instruction::Xor,(Value *)load,(Value *)val2,"",ii);
Pair *node=(Pair*)malloc(sizeof(Pair));
node->pos=pos;
node->val=vv;
updates.push_back(node);
count++;
}
else if(consts->getType()==int32ty)
{
unsigned int data=(consts->getValue().getZExtValue())&0xFFFFFFFF;
unsigned int rr=(rand()&0xFFFFFFFF);
unsigned int tt=data^rr;
Value *val1=ConstantInt::get(int32ty,tt);
Value *val2=ConstantInt::get(int32ty,rr);
GlobalVariable *g=(GlobalVariable*)f->getParent()->getOrInsertGlobal(name,int32ty);
g->setInitializer((Constant*)val1);
LoadInst *load=new LoadInst(int32ty,g,"",ii);
Value *vv=BinaryOperator::Create(Instruction::Xor,(Value *)load,(Value *)val2,"",ii);
Pair *node=(Pair*)malloc(sizeof(Pair));
node->pos=pos;
node->val=vv;
updates.push_back(node);
count++;
}
else if(consts->getType()==int64ty)
{
unsigned long long data=(consts->getValue().getZExtValue())&0xFFFFFFFFFFFFFFFF;
unsigned long long rr=(((((unsigned long long)rand())<<32)|rand())&0xFFFFFFFFFFFFFFFF);
unsigned long long tt=data^rr;
Value *val1=ConstantInt::get(int64ty,tt);
Value *val2=ConstantInt::get(int64ty,rr);
GlobalVariable *g=(GlobalVariable*)f->getParent()->getOrInsertGlobal(name,int64ty);
g->setInitializer((Constant*)val1);
LoadInst *load=new LoadInst(int64ty,g,"",ii);
Value *vv=BinaryOperator::Create(Instruction::Xor,(Value *)load,(Value *)val2,"",ii);
Pair *node=(Pair*)malloc(sizeof(Pair));
node->pos=pos;
node->val=vv;
updates.push_back(node);
count++;
}
else
continue;
}
}
for(std::vector<Pair*>::iterator iter=updates.begin();iter!=updates.end();iter++)
ii->setOperand((*iter)->pos,(*iter)->val);
}
void ReplaceConst(Module &M)
{
unsigned int count=0;

for(Function &func:M)
{
std::vector<Instruction*> instr_list;
for(BasicBlock &bb:func)
for(Instruction &ii:bb)
{
for(User::op_iterator opi=ii.op_begin();opi!=ii.op_end();opi++)
{
Value *v=*opi;
if(isa<ConstantInt>(*v))
{
instr_list.push_back(&ii);
break;
}
}
}
for(std::vector<Instruction*>::iterator iter=instr_list.begin();iter!=instr_list.end();iter++)
handleInstruction(&func,*iter,count);
}


}

bool runOnModule(Module &M) override
{
ReplaceConst(M);
return false;
}
};
}

char ConstantReplace::ID=0;
static RegisterPass<ConstantReplace> X("replaceconst", "Const");