首页
社区
课程
招聘
[原创]OLLVM虚假控制流源码学习笔记
发表于: 2021-2-28 00:01 15131

[原创]OLLVM虚假控制流源码学习笔记

2021-2-28 00:01
15131

虚假控制流的原理和去除方法我在另一篇文章已经讲过了:利用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避免重复混淆,还检查了一些其他东西,感觉不是很重要。要重点分析的是bogusdoF函数。

OLLVM的作者喜欢在函数开头就声明所有全局变量,先不管它。

进入bogus函数后首先检查了一遍obfProbRateobfTimes(话说之前在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))),使其变得更加复杂,并且移除所有基本块和指令的名称:

初始化两个全局变量xy

遍历模块中所有函数的所有指令,遇到条件为永真式的条件跳转时将比较指令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;
          }
        }
      }

[峰会]看雪.第八届安全开发者峰会10月23日上海龙之梦大酒店举办!

收藏
免费 10
支持
分享
打赏 + 2.00雪花
打赏次数 1 雪花 + 2.00
 
赞赏  kanxue   +2.00 2021/02/28 精品文章~
最新回复 (7)
雪    币: 4168
活跃值: (15932)
能力值: ( LV9,RANK:710 )
在线值:
发帖
回帖
粉丝
2
太强了!
2021-2-28 00:22
0
雪    币: 14303
活跃值: (10769)
能力值: ( LV12,RANK:360 )
在线值:
发帖
回帖
粉丝
3
    ScUpax0s 太强了!

郭老师555

最后于 2021-2-28 00:24 被34r7hm4n编辑 ,原因:
2021-2-28 00:23
0
雪    币: 968
活跃值: (6818)
能力值: (RANK:462 )
在线值:
发帖
回帖
粉丝
4
太强了,感谢分享
2021-2-28 09:21
0
雪    币: 44153
活跃值: (20185)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
5
太强了,感谢分享
2021-2-28 10:46
0
雪    币: 24477
活跃值: (62774)
能力值: (RANK:135 )
在线值:
发帖
回帖
粉丝
6
感谢分享~
2021-3-8 10:52
0
雪    币: 379
活跃值: (1135)
能力值: ( LV6,RANK:98 )
在线值:
发帖
回帖
粉丝
7
2021-8-9 17:02
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
8
太强了!
2021-11-8 20:34
0
游客
登录 | 注册 方可回帖
返回
//