ollvm源码分析之虚假控制流(2)

参考网站:Obfuscator-llvm源码分析
参考网站:ollvm源码分析

Pass之BogusControlFlow

实现功能是:添加虚假控制流

1 命令

命令解析
-mllvm -bcf激活虚假控制流
-mllvm -bcf_loop若被激活,指定虚假控制流应用次数,默认为1
-mllvm -bcf_prob=40若被激活,指定某比率的基本块被混淆,默认为30%

2 代码分析

2.1 入口函数runOnFunction

继承了FunctionPass,因此它的入口函数即为runOnFunction。

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;
      }
      // If fla annotations
      if(toObfuscate(flag,&F,"bcf")) {
        bogus(F);
        doF(*F.getParent());
        return true;
      }

      return false;
    } // end of runOnFunction()

首先判断ObfTimes与ObfProbRate。ObfTimes指循环执行的次数,必须大于0,默认为它;ObfProbRate指每个基本块被混淆的几率,必须在0到100之间,默认为30。然后toObfuscate(flag,&F,“bcf”)函数判断是否包含了启动bcf的命令,满足条件则调用bogus函数与doF函数。

2.2 bogus函数

bogus函数首先将本function的所有basicblock存放到一个list容器中,然后使用一个while循环调用addBogusFlow函数对选中的basicblock进行增加虚假控制流。

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;
      int NumObfTimes = ObfTimes;

        // Real begining of the pass
        // Loop for the number of time we run the pass on the function
        do{
          DEBUG_WITH_TYPE("cfg", errs() << "bcf: Function " << F.getName()
              <<", before the pass:\n");
          DEBUG_WITH_TYPE("cfg", F.viewCFG());
          // 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);
          }
          DEBUG_WITH_TYPE("gen", errs() << "bcf: Iterating on the Function's Basic Blocks\n");

          while(!basicBlocks.empty()){
            NumBasicBlocks ++;
            // Basic Blocks' selection
            if((int)llvm::cryptoutils->get_range(100) <= ObfProbRate){
              DEBUG_WITH_TYPE("opt", errs() << "bcf: Block "
                  << NumBasicBlocks <<" selected. \n");
              hasBeenModified = true;
              ++NumModifiedBasicBlocks;
              NumAddedBasicBlocks += 3;
              FinalNumBasicBlocks += 3;
              // Add bogus flow to the given Basic Block (see description)
              BasicBlock *basicBlock = basicBlocks.front();
              addBogusFlow(basicBlock, F);
            }
            else{
              DEBUG_WITH_TYPE("opt", errs() << "bcf: Block "
                  << NumBasicBlocks <<" not selected.\n");
            }
            // remove the block from the list
            basicBlocks.pop_front();

            if(firstTime){ // first time we iterate on this function
              ++InitNumBasicBlocks;
              ++FinalNumBasicBlocks;
            }
          } // end of while(!basicBlocks.empty())
          DEBUG_WITH_TYPE("gen", errs() << "bcf: End of function " << F.getName() << "\n");
          if(hasBeenModified){ // if the function has been modified
            DEBUG_WITH_TYPE("cfg", errs() << "bcf: Function " << F.getName()
                <<", after the pass: \n");
            DEBUG_WITH_TYPE("cfg", F.viewCFG());
          }
          else{
            DEBUG_WITH_TYPE("cfg", errs() << "bcf: Function's not been modified \n");
          }
          firstTime = false;
        }while(--NumObfTimes > 0);
    }

外层do…while循环是根据ObfTimes的值来进行多次混淆。遍历基本块,随机决定当前基本块是否需要修改,若ObfProbRate满足条件则调用addBogusFlow函数。

2.3 addBogusFlow函数
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);       

首先调用getFirstNonPHIOrDbgOrLifetime()函数获取本basicblock中第一个不是Phi、Dbg、Lifetime的指令的地址,然后调用splitBasicBlock函数。splitBasicBlock函数可根据上述指令的地址将一个basicblock一分为二(basicBlock和originalBB)。

Twine * var3 = new Twine("alteredBB");
BasicBlock *alteredBB = createAlteredBasicBlock(originalBB, *var3, &F);

使用createAlteredBasicBlock函数对originalBB进行复制,得到alteredBB。

alteredBB->getTerminator()->eraseFromParent();
basicBlock->getTerminator()->eraseFromParent();

现在有3个基本块basicBlock、originalBB 、alteredBB,需要清除basicBlock、alteredBB与父节点的关系。

Value * LHS = ConstantFP::get(Type::getFloatTy(F.getContext()), 1.0);
Value * RHS = ConstantFP::get(Type::getFloatTy(F.getContext()), 1.0);
Twine * var4 = new Twine("condition");
FCmpInst * condition = new FCmpInst(*basicBlock, FCmpInst::FCMP_TRUE , LHS, RHS, *var4);
BranchInst::Create(originalBB, alteredBB, (Value *)condition, basicBlock);
BranchInst::Create(originalBB, alteredBB);

对于基本块basicBlock创建一个条件,若为真则其跳转到originalBB,否则跳转到alteredBB。同时为alteredBB创建一条跳转到originalBB的指令(该跳转指令不会执行)。

BasicBlock::iterator i = originalBB->end();
Twine * var5 = new Twine("originalBBpart2");
BasicBlock * originalBBpart2 = originalBB->splitBasicBlock(--i , *var5);
originalBB->getTerminator()->eraseFromParent();

Twine * var6 = new Twine("condition2");
FCmpInst * condition2 = new FCmpInst(*originalBB, CmpInst::FCMP_TRUE , LHS, RHS, *var6);
BranchInst::Create(originalBBpart2, alteredBB, (Value *)condition2, originalBB);

获取originalBB最后一条指令的位置,调用splitBasicBlock将originalBB分为originalBB与originalBBpart2,并消除两者间关系。对于基本块originalBB创建一个条件,若为真则跳转到originalBBpart2,为假则跳转到alteredBB。
至此,执行完addBogusFlow函数后的基本块的关系图如下所示。
关系图

2.4 createAlteredBasicBlock函数

用于对复制得到的alteredBB进行变换。遍历alteredBB中的所有OpCode,若包含有Add、Sub、UDiv、SDiv、URem、SRem、Shl、LShr、AShr、And、Or、Xor以及FAdd、FSub、FMul、FDiv、FRem指令,则用随机生成一些指令来进行替换。

2.5 doF函数

将Module中所有恒真的判断用不透明谓词(y < 10 || x * (x + 1) % 2 == 0)进行替换。

Twine * varX = new Twine("x");
Twine * varY = new Twine("y");
Value * x1 =ConstantInt::get(Type::getInt32Ty(M.getContext()), 0, false);
Value * y1 =ConstantInt::get(Type::getInt32Ty(M.getContext()), 0, false);

GlobalVariable 	* x = new GlobalVariable(M,Type::getInt32Ty(M.getContext()), false,GlobalValue::CommonLinkage, (Constant * )x1,*varX);
GlobalVariable 	* y = new GlobalVariable(M,Type::getInt32Ty(M.getContext()), false,GlobalValue::CommonLinkage, (Constant * )y1,varY);

创建两个全局变量。

for(Module::iterator mi = M.begin(), me = M.end(); mi != me; ++mi){
	for(Function::iterator fi = mi->begin(), fe = mi->end(); fi != fe; ++fi){ 
		TerminatorInst * tbb= fi->getTerminator();
        if(tbb->getOpcode() == Instruction::Br){
        	BranchInst * br = (BranchInst *)(tbb);
            if(br->isConditional()){
              FCmpInst * cond = (FCmpInst *)br->getCondition();
              unsigned opcode = cond->getOpcode();
              if(opcode == Instruction::FCmp){
                if (cond->getPredicate() == FCmpInst::FCMP_TRUE){
                  DEBUG_WITH_TYPE("gen",
                      errs()<<"bcf: an always true predicate !\n");
                  toDelete.push_back(cond); // The condition
                  toEdit.push_back(tbb);    // The branch using the condition
                }
              }
            }
         }
     }
}

然后遍历模块中所有基本块,搜索出条件为真的语句。
最后用y < 10 || x * (x + 1) % 2 == 0替换。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值