虚假控制流的原理和去除方法我在另一篇文章已经讲过了:利用angr符号执行去除虚假控制流 ,这篇文章简单记录下我阅读OLLVM虚假控制流源码的过程。
OLLVM虚假控制流源码地址:https://github.com/obfuscator-llvm/obfuscator/blob/llvm-4.0/lib/Transforms/Obfuscation/BogusControlFlow.cpp
首先从runOnFunction 函数开始:
ObfTimes 是对函数进行混淆的次数,ObfProbRate 是对基本块进行混淆的概率,这两个分别是执行opt 时传入的参数:
runOnFunction 函数剩下的内容:
toObfuscate 函数的作用是检查这个函数之前有没有进行过虚假控制流混淆,如果有则返回false避免重复混淆,还检查了一些其他东西,感觉不是很重要。要重点分析的是bogus 和doF 函数。
OLLVM的作者喜欢在函数开头就声明所有全局变量,先不管它。
进入bogus 函数后首先检查了一遍obfProbRate 和obfTimes (话说之前在runOnFunction 里不就检查过了吗= =)。
这里的NumTimesOnFunctions是调试用的。虚假控制流的代码比控制流平坦化的代码多了几百行,重要的原因就是添加了很多调试语句。为了突出重点,之后的调试语句直接忽略:
接着是一个超大的循环,直到函数结尾,我们去掉所有调试语句分析,循环总共有两层,第一层的循环开头把所有基本块存入一个list中:
接着进入第二层的循环,每个基本块有ObfProbRate 的概率被混淆,即对基本块调用了addBogusFlow 函数:
后面就都是调试内容了,所以bogus 函数的作用就是对指定函数的每个基本块以ObfProbRate 的概率进行混淆,接下来分析addBogusFlow 函数。
首先通过getFirstNonPHIOrDbgOrLifetime 函数和splitBasicBlock 函数把BasicBlock分成了两部分,第一部分只包含PHI Node 和一些调试信息,其中Twine 可以看做字符串,即新产生的BasicBlock的名称:
随后调用createAlteredBasicBlock 函数产生了一个新的基本块:
createAlteredBasicBlock 函数首先调用了CloneBasicBlock 函数对传入的基本块进行克隆:
但是CloneBasicBlock 函数进行的克隆并不是完全的克隆,第一他不会对指令的操作数进行替换,比如:
在clone出来的基本块中,fadd 指令的操作数不是%a.clone ,而是%a 。
所以之后要通过VMap 对所有操作数进行映射,使其恢复正常:
第二,它不会对PHI Node进行任何处理,PHI Node的前驱块仍然是原始基本块的前驱块,但是新克隆出来的基本块并没有任何前驱块,所以我们要对PHI Node的前驱块进行remap:
解释一下什么是PHI Node,所有 LLVM 指令都使用 SSA (Static Single Assignment,静态一次性赋值) 方式表示,即所有变量都只能被赋值一次,这样做主要是便于后期的代码优化。如下图,%temp 的值被赋值成1后就永远是1了: PHI Node是一条可以一定程度上绕过SSA机制的指令,它可以根据不同的前驱基本块来赋值(有点像三元运算符)。如下图,如果PHI Node的前驱基本块是entry,则将current_i赋值为2,如果是for_body,则赋值为%i_plus_one: 在这里我产生了一个疑问:既然Clone出来的基本块不存在任何前驱,那PHI Node的前继基本块到底被remap到了哪呢? 我翻了一下LLVM的源码,发现VMap只会保存新旧指令的映射关系: 然后根据MapValue的注释来看应该是映射成了nullptr: 暂且不知道PHI Node中的前驱块设为nullptr会有什么影响,先继续往下看吧。 之后是恢复Metadata和Debug信息,个人感觉是可有可无的,不管它:
至此我们就完成了对一个基本块的克隆,之后是往基本块里添加垃圾指令,这里大概的思路就是往基本块里插入一些没用的赋值指令,或者修改cmp指令的条件,BinaryOp 大概指的是add、mul、cmp这类运算指令:
总的来说createAlteredBasicBlock函数克隆了一个基本块,并且往这个基本块里添加了一些垃圾指令。
现在我们有了一个原始基本块originalBB ,和一个克隆出的基本块alteredBB ,以及一个只包含PHI Node和Debug信息的基本块basicBlock (就是一开始分离出来的那个),现在的状况是这样: 删除了basciBlock和alteredBB末尾的跳转,添加了新的分支指令。 FCmpInst * condition = new FCmpInst(*basicBlock, FCmpInst::FCMP_TRUE , LHS, RHS, *var4) 是一个永真的条件 :
现在的状况是这样: 然后又是一波类似的操作,这里截取的originalBB结尾的跳转指令作为一个新的基本块originalBBPart2 :
现在的状况是这样,可以看到alteredBB实际上是一个不可达的基本块,俗称垃圾块: 至此虚假控制流混淆已见雏形。
首先回顾一下runOnFunction 函数最后的代码,bogus 函数的代码我已经了解得差不多了,接下来是doF 函数:
从开头的注释我们大概能了解到这个函数的作用,修改所有永真式(比如:if(true) 改为if((y < 10 || x * (x + 1) % 2 == 0)) ),使其变得更加复杂,并且移除所有基本块和指令的名称:
初始化两个全局变量x 和y :
遍历模块中所有函数的所有指令,遇到条件为永真式的条件跳转时将比较指令FCmpInst 存储到toDelete 向量中,将跳转指令BranchInst 存储到toEdit 向量中。删除所有基本块和指令名称的代码被注释掉了,不知道为啥:
添加新的条件跳转,删除旧的条件跳转,注释里的条件给错了,从代码来看应该是if y < 10 || x*(x-1) % 2 == 0 ,不过也差不多:
另外在IDA里这个条件有时候会变成if y >= 10 && x*(x-1) % 2 != 0 : 最后是删除之前存储的FCmpInst :
到这里OLLVM虚假控制流的源码基本分析完毕了。
在研究虚假控制流的源码之前属实没想到它的代码会比控制流平坦化多出几百行。原因之一是在复制基本块时要处理PHI Node和一些Debug信息,以及添加垃圾指令(不知道这样做是不是为了防止IDA识别重复的基本块);原因之二是代码中有很多debug语句,也占据了半壁江山;最后一点就是作者的代码风格问题了,感觉有点肿胀。
总的来说还是很有收获啦!不过在研究过程中还是有一些没弄懂的地方,比如PHI Node的remap到底是个什么remap法,简单的映射成nullptr不会有问题吗?然后就是Lifetime Intrinsics和Debug Intrinsics到底是个啥也没弄明白。希望有大佬能指点迷津。
virtual
bool
runOnFunction(Function &F){
/
/
Check
if
the percentage
is
correct
if
(ObfTimes <
=
0
) {
errs()<<
"BogusControlFlow application number -bcf_loop=x must be x > 0"
;
return
false;
}
/
/
Check
if
the number of applications
is
correct
if
( !((ObfProbRate >
0
) && (ObfProbRate <
=
100
)) ) {
errs()<<
"BogusControlFlow application basic blocks percentage -bcf_prob=x must be 0 < x <= 100"
;
return
false;
}
virtual
bool
runOnFunction(Function &F){
/
/
Check
if
the percentage
is
correct
if
(ObfTimes <
=
0
) {
errs()<<
"BogusControlFlow application number -bcf_loop=x must be x > 0"
;
return
false;
}
/
/
Check
if
the number of applications
is
correct
if
( !((ObfProbRate >
0
) && (ObfProbRate <
=
100
)) ) {
errs()<<
"BogusControlFlow application basic blocks percentage -bcf_prob=x must be 0 < x <= 100"
;
return
false;
}
static cl::opt<
int
>
ObfProbRate(
"bcf_prob"
, cl::desc(
"Choose the probability [%] each basic blocks will be obfuscated by the -bcf pass"
), cl::value_desc(
"probability rate"
), cl::init(defaultObfRate), cl::Optional);
static cl::opt<
int
>
ObfTimes(
"bcf_loop"
, cl::desc(
"Choose how many time the -bcf pass loop on a function"
), cl::value_desc(
"number of times"
), cl::init(defaultObfTime), cl::Optional);
static cl::opt<
int
>
ObfProbRate(
"bcf_prob"
, cl::desc(
"Choose the probability [%] each basic blocks will be obfuscated by the -bcf pass"
), cl::value_desc(
"probability rate"
), cl::init(defaultObfRate), cl::Optional);
static cl::opt<
int
>
ObfTimes(
"bcf_loop"
, cl::desc(
"Choose how many time the -bcf pass loop on a function"
), cl::value_desc(
"number of times"
), cl::init(defaultObfTime), cl::Optional);
/
/
If fla annotations
if
(toObfuscate(flag,&F,
"bcf"
)) {
bogus(F);
doF(
*
F.getParent());
return
true;
}
return
false;
}
/
/
end of runOnFunction()
/
/
If fla annotations
if
(toObfuscate(flag,&F,
"bcf"
)) {
bogus(F);
doF(
*
F.getParent());
return
true;
}
return
false;
}
/
/
end of runOnFunction()
void bogus(Function &F) {
/
/
For statistics
and
debug
+
+
NumFunction;
int
NumBasicBlocks
=
0
;
bool
firstTime
=
true;
/
/
First time we do the loop
in
this function
bool
hasBeenModified
=
false;
DEBUG_WITH_TYPE(
"opt"
, errs() <<
"bcf: Started on function "
<< F.getName() <<
"\n"
);
DEBUG_WITH_TYPE(
"opt"
, errs() <<
"bcf: Probability rate: "
<< ObfProbRate<<
"\n"
);
if
(ObfProbRate <
0
|| ObfProbRate >
100
){
DEBUG_WITH_TYPE(
"opt"
, errs() <<
"bcf: Incorrect value,"
<<
" probability rate set to default value: "
<< defaultObfRate <<
" \n"
);
ObfProbRate
=
defaultObfRate;
}
DEBUG_WITH_TYPE(
"opt"
, errs() <<
"bcf: How many times: "
<< ObfTimes<<
"\n"
);
if
(ObfTimes <
=
0
){
DEBUG_WITH_TYPE(
"opt"
, errs() <<
"bcf: Incorrect value,"
<<
" must be greater than 1. Set to default: "
<< defaultObfTime <<
" \n"
);
ObfTimes
=
defaultObfTime;
}
NumTimesOnFunctions
=
ObfTimes;
void bogus(Function &F) {
/
/
For statistics
and
debug
+
+
NumFunction;
int
NumBasicBlocks
=
0
;
bool
firstTime
=
true;
/
/
First time we do the loop
in
this function
bool
hasBeenModified
=
false;
DEBUG_WITH_TYPE(
"opt"
, errs() <<
"bcf: Started on function "
<< F.getName() <<
"\n"
);
DEBUG_WITH_TYPE(
"opt"
, errs() <<
"bcf: Probability rate: "
<< ObfProbRate<<
"\n"
);
if
(ObfProbRate <
0
|| ObfProbRate >
100
){
DEBUG_WITH_TYPE(
"opt"
, errs() <<
"bcf: Incorrect value,"
<<
" probability rate set to default value: "
<< defaultObfRate <<
" \n"
);
ObfProbRate
=
defaultObfRate;
}
DEBUG_WITH_TYPE(
"opt"
, errs() <<
"bcf: How many times: "
<< ObfTimes<<
"\n"
);
if
(ObfTimes <
=
0
){
DEBUG_WITH_TYPE(
"opt"
, errs() <<
"bcf: Incorrect value,"
<<
" must be greater than 1. Set to default: "
<< defaultObfTime <<
" \n"
);
ObfTimes
=
defaultObfTime;
}
NumTimesOnFunctions
=
ObfTimes;
NumTimesOnFunctions
=
ObfTimes;
NumTimesOnFunctions
=
ObfTimes;
STATISTIC(NumTimesOnFunctions,
"b. Number of times we run on each function"
);
STATISTIC(NumTimesOnFunctions,
"b. Number of times we run on each function"
);
do{
/
/
Put
all
the function's block
in
a
list
std::
list
<BasicBlock
*
> basicBlocks;
for
(Function::iterator i
=
F.begin();i!
=
F.end();
+
+
i) {
basicBlocks.push_back(&
*
i);
}
do{
/
/
Put
all
the function's block
in
a
list
std::
list
<BasicBlock
*
> basicBlocks;
for
(Function::iterator i
=
F.begin();i!
=
F.end();
+
+
i) {
basicBlocks.push_back(&
*
i);
}
while
(!basicBlocks.empty()){
NumBasicBlocks
+
+
;
/
/
Basic Blocks' selection
if
((
int
)llvm::cryptoutils
-
>get_range(
100
) <
=
ObfProbRate){
hasBeenModified
=
true;
BasicBlock
*
basicBlock
=
basicBlocks.front();
addBogusFlow(basicBlock, F);
}
/
/
remove the block
from
the
list
basicBlocks.pop_front();
}
/
/
end of
while
(!basicBlocks.empty())
while
(!basicBlocks.empty()){
NumBasicBlocks
+
+
;
/
/
Basic Blocks' selection
if
((
int
)llvm::cryptoutils
-
>get_range(
100
) <
=
ObfProbRate){
hasBeenModified
=
true;
BasicBlock
*
basicBlock
=
basicBlocks.front();
addBogusFlow(basicBlock, F);
}
/
/
remove the block
from
the
list
basicBlocks.pop_front();
}
/
/
end of
while
(!basicBlocks.empty())
/
*
addBogusFlow
*
*
Add bogus flow to a given basic block, according to the header's description
*
/
virtual void addBogusFlow(BasicBlock
*
basicBlock, Function &F){
/
/
Split the block: first part with only the phi nodes
and
debug info
and
terminator
/
/
created by splitBasicBlock. (
-
> No instruction)
/
/
Second part with every instructions
from
the original block
/
/
We do this way, so we don't have to adjust
all
the phi nodes, metadatas
and
so on
/
/
for
the first block. We have to let the phi nodes
in
the first part, because they
/
/
actually are updated
in
the second part according to them.
BasicBlock::iterator i1
=
basicBlock
-
>begin();
if
(basicBlock
-
>getFirstNonPHIOrDbgOrLifetime())
i1
=
(BasicBlock::iterator)basicBlock
-
>getFirstNonPHIOrDbgOrLifetime();
Twine
*
var;
var
=
new Twine(
"originalBB"
);
BasicBlock
*
originalBB
=
basicBlock
-
>splitBasicBlock(i1,
*
var);
/
*
addBogusFlow
*
*
Add bogus flow to a given basic block, according to the header's description
*
/
virtual void addBogusFlow(BasicBlock
*
basicBlock, Function &F){
/
/
Split the block: first part with only the phi nodes
and
debug info
and
terminator
/
/
created by splitBasicBlock. (
-
> No instruction)
/
/
Second part with every instructions
from
the original block
/
/
We do this way, so we don't have to adjust
all
the phi nodes, metadatas
and
so on
/
/
for
the first block. We have to let the phi nodes
in
the first part, because they
/
/
actually are updated
in
the second part according to them.
BasicBlock::iterator i1
=
basicBlock
-
>begin();
if
(basicBlock
-
>getFirstNonPHIOrDbgOrLifetime())
i1
=
(BasicBlock::iterator)basicBlock
-
>getFirstNonPHIOrDbgOrLifetime();
Twine
*
var;
var
=
new Twine(
"originalBB"
);
BasicBlock
*
originalBB
=
basicBlock
-
>splitBasicBlock(i1,
*
var);
/
/
Creating the altered basic block on which the first basicBlock will jump
Twine
*
var3
=
new Twine(
"alteredBB"
);
BasicBlock
*
alteredBB
=
createAlteredBasicBlock(originalBB,
*
var3, &F);
/
/
Creating the altered basic block on which the first basicBlock will jump
Twine
*
var3
=
new Twine(
"alteredBB"
);
BasicBlock
*
alteredBB
=
createAlteredBasicBlock(originalBB,
*
var3, &F);
virtual BasicBlock
*
createAlteredBasicBlock(BasicBlock
*
basicBlock,
const Twine & Name
=
"gen"
, Function
*
F
=
0
){
/
/
Useful to remap the informations concerning instructions.
ValueToValueMapTy VMap;
BasicBlock
*
alteredBB
=
llvm::CloneBasicBlock (basicBlock, VMap, Name, F);
virtual BasicBlock
*
createAlteredBasicBlock(BasicBlock
*
basicBlock,
const Twine & Name
=
"gen"
, Function
*
F
=
0
){
/
/
Useful to remap the informations concerning instructions.
ValueToValueMapTy VMap;
BasicBlock
*
alteredBB
=
llvm::CloneBasicBlock (basicBlock, VMap, Name, F);
orig:
%
a
=
...
%
b
=
fadd
%
a, ...
clone:
%
a.clone
=
...
%
b.clone
=
fadd
%
a, ... ; Note that this references the old
%
a
and
not
%
a.clone!
orig:
%
a
=
...
%
b
=
fadd
%
a, ...
clone:
%
a.clone
=
...
%
b.clone
=
fadd
%
a, ... ; Note that this references the old
%
a
and
not
%
a.clone!
/
/
Remap operands.
BasicBlock::iterator ji
=
basicBlock
-
>begin();
for
(BasicBlock::iterator i
=
alteredBB
-
>begin(), e
=
alteredBB
-
>end() ; i !
=
e;
+
+
i){
/
/
Loop over the operands of the instruction
for
(User::op_iterator opi
=
i
-
>op_begin (), ope
=
i
-
>op_end(); opi !
=
ope;
+
+
opi){
/
/
get the value
for
the operand
Value
*
v
=
MapValue(
*
opi, VMap, RF_None,
0
);
if
(v !
=
0
){
*
opi
=
v;
DEBUG_WITH_TYPE(
"gen"
, errs() <<
"bcf: Value's operand has been setted\n"
);
}
}
/
/
Remap operands.
BasicBlock::iterator ji
=
basicBlock
-
>begin();
for
(BasicBlock::iterator i
=
alteredBB
-
>begin(), e
=
alteredBB
-
>end() ; i !
=
e;
+
+
i){
/
/
Loop over the operands of the instruction
for
(User::op_iterator opi
=
i
-
>op_begin (), ope
=
i
-
>op_end(); opi !
=
ope;
+
+
opi){
/
/
get the value
for
the operand
Value
*
v
=
MapValue(
*
opi, VMap, RF_None,
0
);
if
(v !
=
0
){
*
opi
=
v;
DEBUG_WITH_TYPE(
"gen"
, errs() <<
"bcf: Value's operand has been setted\n"
);
}
}
/
/
Remap phi nodes' incoming blocks.
if
(PHINode
*
pn
=
dyn_cast<PHINode>(i)) {
for
(unsigned j
=
0
, e
=
pn
-
>getNumIncomingValues(); j !
=
e;
+
+
j) {
Value
*
v
=
MapValue(pn
-
>getIncomingBlock(j), VMap, RF_None,
0
);
if
(v !
=
0
){
pn
-
>setIncomingBlock(j, cast<BasicBlock>(v));
}
}
}
/
/
Remap phi nodes' incoming blocks.
if
(PHINode
*
pn
=
dyn_cast<PHINode>(i)) {
for
(unsigned j
=
0
, e
=
pn
-
>getNumIncomingValues(); j !
=
e;
+
+
j) {
Value
*
v
=
MapValue(pn
-
>getIncomingBlock(j), VMap, RF_None,
0
);
if
(v !
=
0
){
pn
-
>setIncomingBlock(j, cast<BasicBlock>(v));
}
}
}
/
/
Remap attached metadata.
SmallVector<std::pair<unsigned, MDNode
*
>,
4
> MDs;
i
-
>getAllMetadata(MDs);
/
/
important
for
compiling with DWARF, using option
-
g.
i
-
>setDebugLoc(ji
-
>getDebugLoc());
ji
+
+
;
}
/
/
The instructions' informations are now
all
correct
/
/
Remap attached metadata.
SmallVector<std::pair<unsigned, MDNode
*
>,
4
> MDs;
i
-
>getAllMetadata(MDs);
/
/
important
for
compiling with DWARF, using option
-
g.
i
-
>setDebugLoc(ji
-
>getDebugLoc());
ji
+
+
;
}
/
/
The instructions' informations are now
all
correct
/
/
add random instruction
in
the middle of the bloc. This part can be improve
for
(BasicBlock::iterator i
=
alteredBB
-
>begin(), e
=
alteredBB
-
>end() ; i !
=
e;
+
+
i){
/
/
in
the case we find binary operator, we modify slightly this part by randomly
/
/
insert some instructions
if
(i
-
>isBinaryOp()){
/
/
binary instructions
unsigned opcode
=
i
-
>getOpcode();
BinaryOperator
*
op,
*
op1
=
NULL;
Twine
*
var
=
new Twine(
"_"
);
/
/
treat differently
float
or
int
/
/
Binary
int
if
(opcode
=
=
Instruction::Add || opcode
=
=
Instruction::Sub ||
opcode
=
=
Instruction::Mul || opcode
=
=
Instruction::UDiv ||
opcode
=
=
Instruction::SDiv || opcode
=
=
Instruction::URem ||
opcode
=
=
Instruction::SRem || opcode
=
=
Instruction::Shl ||
opcode
=
=
Instruction::LShr || opcode
=
=
Instruction::AShr ||
opcode
=
=
Instruction::And || opcode
=
=
Instruction::Or ||
opcode
=
=
Instruction::Xor){
for
(
int
random
=
(
int
)llvm::cryptoutils
-
>get_range(
10
); random <
10
;
+
+
random){
switch(llvm::cryptoutils
-
>get_range(
4
)){
/
/
to improve
case
0
:
/
/
do nothing
break
;
case
1
: op
=
BinaryOperator::CreateNeg(i
-
>getOperand(
0
),
*
var,&
*
i);
op1
=
BinaryOperator::Create(Instruction::Add,op,
i
-
>getOperand(
1
),
"gen"
,&
*
i);
break
;
case
2
: op1
=
BinaryOperator::Create(Instruction::Sub,
i
-
>getOperand(
0
),
i
-
>getOperand(
1
),
*
var,&
*
i);
op
=
BinaryOperator::Create(Instruction::Mul,op1,
i
-
>getOperand(
1
),
"gen"
,&
*
i);
break
;
case
3
: op
=
BinaryOperator::Create(Instruction::Shl,
i
-
>getOperand(
0
),
i
-
>getOperand(
1
),
*
var,&
*
i);
break
;
}
}
}
/
/
Binary
float
if
(opcode
=
=
Instruction::FAdd || opcode
=
=
Instruction::FSub ||
opcode
=
=
Instruction::FMul || opcode
=
=
Instruction::FDiv ||
opcode
=
=
Instruction::FRem){
for
(
int
random
=
(
int
)llvm::cryptoutils
-
>get_range(
10
); random <
10
;
+
+
random){
switch(llvm::cryptoutils
-
>get_range(
3
)){
/
/
can be improved
case
0
:
/
/
do nothing
break
;
case
1
: op
=
BinaryOperator::CreateFNeg(i
-
>getOperand(
0
),
*
var,&
*
i);
op1
=
BinaryOperator::Create(Instruction::FAdd,op,
i
-
>getOperand(
1
),
"gen"
,&
*
i);
break
;
case
2
: op
=
BinaryOperator::Create(Instruction::FSub,
i
-
>getOperand(
0
),
i
-
>getOperand(
1
),
*
var,&
*
i);
op1
=
BinaryOperator::Create(Instruction::FMul,op,
i
-
>getOperand(
1
),
"gen"
,&
*
i);
break
;
}
}
}
if
(opcode
=
=
Instruction::ICmp){
/
/
Condition (with
int
)
ICmpInst
*
currentI
=
(ICmpInst
*
)(&i);
switch(llvm::cryptoutils
-
>get_range(
3
)){
/
/
must be improved
case
0
:
/
/
do nothing
break
;
case
1
: currentI
-
>swapOperands();
break
;
case
2
:
/
/
randomly change the predicate
switch(llvm::cryptoutils
-
>get_range(
10
)){
case
0
: currentI
-
>setPredicate(ICmpInst::ICMP_EQ);
break
;
/
/
equal
case
1
: currentI
-
>setPredicate(ICmpInst::ICMP_NE);
break
;
/
/
not
equal
case
2
: currentI
-
>setPredicate(ICmpInst::ICMP_UGT);
break
;
/
/
unsigned greater than
case
3
: currentI
-
>setPredicate(ICmpInst::ICMP_UGE);
break
;
/
/
unsigned greater
or
equal
case
4
: currentI
-
>setPredicate(ICmpInst::ICMP_ULT);
break
;
/
/
unsigned less than
case
5
: currentI
-
>setPredicate(ICmpInst::ICMP_ULE);
break
;
/
/
unsigned less
or
equal
case
6
: currentI
-
>setPredicate(ICmpInst::ICMP_SGT);
break
;
/
/
signed greater than
case
7
: currentI
-
>setPredicate(ICmpInst::ICMP_SGE);
break
;
/
/
signed greater
or
equal
case
8
: currentI
-
>setPredicate(ICmpInst::ICMP_SLT);
break
;
/
/
signed less than
case
9
: currentI
-
>setPredicate(ICmpInst::ICMP_SLE);
break
;
/
/
signed less
or
equal
}
break
;
}
}
if
(opcode
=
=
Instruction::FCmp){
/
/
Conditions (with
float
)
FCmpInst
*
currentI
=
(FCmpInst
*
)(&i);
switch(llvm::cryptoutils
-
>get_range(
3
)){
/
/
must be improved
case
0
:
/
/
do nothing
break
;
case
1
: currentI
-
>swapOperands();
break
;
case
2
:
/
/
randomly change the predicate
switch(llvm::cryptoutils
-
>get_range(
10
)){
case
0
: currentI
-
>setPredicate(FCmpInst::FCMP_OEQ);
break
;
/
/
ordered
and
equal
case
1
: currentI
-
>setPredicate(FCmpInst::FCMP_ONE);
break
;
/
/
ordered
and
operands are unequal
case
2
: currentI
-
>setPredicate(FCmpInst::FCMP_UGT);
break
;
/
/
unordered
or
greater than
case
3
: currentI
-
>setPredicate(FCmpInst::FCMP_UGE);
break
;
/
/
unordered,
or
greater than,
or
equal
case
4
: currentI
-
>setPredicate(FCmpInst::FCMP_ULT);
break
;
/
/
unordered
or
less than
case
5
: currentI
-
>setPredicate(FCmpInst::FCMP_ULE);
break
;
/
/
unordered,
or
less than,
or
equal
case
6
: currentI
-
>setPredicate(FCmpInst::FCMP_OGT);
break
;
/
/
ordered
and
greater than
case
7
: currentI
-
>setPredicate(FCmpInst::FCMP_OGE);
break
;
/
/
ordered
and
greater than
or
equal
case
8
: currentI
-
>setPredicate(FCmpInst::FCMP_OLT);
break
;
/
/
ordered
and
less than
case
9
: currentI
-
>setPredicate(FCmpInst::FCMP_OLE);
break
;
/
/
ordered
or
less than,
or
equal
}
break
;
}
}
}
}
return
alteredBB;
}
/
/
end of createAlteredBasicBlock()
/
/
add random instruction
in
the middle of the bloc. This part can be improve
for
(BasicBlock::iterator i
=
alteredBB
-
>begin(), e
=
alteredBB
-
>end() ; i !
=
e;
+
+
i){
/
/
in
the case we find binary operator, we modify slightly this part by randomly
/
/
insert some instructions
if
(i
-
>isBinaryOp()){
/
/
binary instructions
unsigned opcode
=
i
-
>getOpcode();
BinaryOperator
*
op,
*
op1
=
NULL;
Twine
*
var
=
new Twine(
"_"
);
/
/
treat differently
float
or
int
/
/
Binary
int
if
(opcode
=
=
Instruction::Add || opcode
=
=
Instruction::Sub ||
opcode
=
=
Instruction::Mul || opcode
=
=
Instruction::UDiv ||
opcode
=
=
Instruction::SDiv || opcode
=
=
Instruction::URem ||
opcode
=
=
Instruction::SRem || opcode
=
=
Instruction::Shl ||
opcode
=
=
Instruction::LShr || opcode
=
=
Instruction::AShr ||
opcode
=
=
Instruction::And || opcode
=
=
Instruction::Or ||
opcode
=
=
Instruction::Xor){
for
(
int
random
=
(
int
)llvm::cryptoutils
-
>get_range(
10
); random <
10
;
+
+
random){
switch(llvm::cryptoutils
-
>get_range(
4
)){
/
/
to improve
case
0
:
/
/
do nothing
break
;
case
1
: op
=
BinaryOperator::CreateNeg(i
-
>getOperand(
0
),
*
var,&
*
i);
op1
=
BinaryOperator::Create(Instruction::Add,op,
i
-
>getOperand(
1
),
"gen"
,&
*
i);
break
;
case
2
: op1
=
BinaryOperator::Create(Instruction::Sub,
i
-
>getOperand(
0
),
i
-
>getOperand(
1
),
*
var,&
*
i);
op
=
BinaryOperator::Create(Instruction::Mul,op1,
i
-
>getOperand(
1
),
"gen"
,&
*
i);
break
;
case
3
: op
=
BinaryOperator::Create(Instruction::Shl,
i
-
>getOperand(
0
),
i
-
>getOperand(
1
),
*
var,&
*
i);
break
;
}
}
}
/
/
Binary
float
if
(opcode
=
=
Instruction::FAdd || opcode
=
=
Instruction::FSub ||
opcode
=
=
Instruction::FMul || opcode
=
=
Instruction::FDiv ||
opcode
=
=
Instruction::FRem){
for
(
int
random
=
(
int
)llvm::cryptoutils
-
>get_range(
10
); random <
10
;
+
+
random){
switch(llvm::cryptoutils
-
>get_range(
3
)){
/
/
can be improved
case
0
:
/
/
do nothing
break
;
case
1
: op
=
BinaryOperator::CreateFNeg(i
-
>getOperand(
0
),
*
var,&
*
i);
op1
=
BinaryOperator::Create(Instruction::FAdd,op,
i
-
>getOperand(
1
),
"gen"
,&
*
i);
break
;
case
2
: op
=
BinaryOperator::Create(Instruction::FSub,
i
-
>getOperand(
0
),
i
-
>getOperand(
1
),
*
var,&
*
i);
op1
=
BinaryOperator::Create(Instruction::FMul,op,
i
-
>getOperand(
1
),
"gen"
,&
*
i);
break
;
}
}
}
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课