예제 #1
0
파일: CAinst.cpp 프로젝트: sirmc/XnRmor
void instrumentFunction(BPatch_function *function)
{
    std::set<BPatch_basicBlock*> blocks;
    std::set<BPatch_basicBlock*>::reverse_iterator b;
    BPatch_flowGraph *cfg = function->getCFG();
    cfg->getAllBasicBlocks(blocks);
    for (b = blocks.rbegin(); b != blocks.rend(); b++) {
        instrumentBasicBlock(function, *b);
    }
}
예제 #2
0
// inserts a callback for each basic block assigning it an instrumentation
// time 16bit random ID just as afl
bool insertBBCallback(BPatch_binaryEdit * appBin, BPatch_function * curFunc,
                      char *funcName, BPatch_function * instBBIncFunc,int *bbIndex)
{

    BPatch_flowGraph *appCFG = curFunc->getCFG ();
    unsigned short randID;

    if (!appCFG) {
        cerr << "Failed to find CFG for function " << funcName << endl;
        return false;
    }

    BPatch_Set < BPatch_basicBlock * >allBlocks;
    if (!appCFG->getAllBasicBlocks (allBlocks)) {
        cerr << "Failed to find basic blocks for function " << funcName << endl;
        return false;
    } else if (allBlocks.size () == 0) {
        cerr << "No basic blocks for function " << funcName << endl;
        return false;
    }

    BPatch_Set < BPatch_basicBlock * >::iterator iter;
    for (iter = allBlocks.begin (); iter != allBlocks.end (); iter++) {
        if(*bbIndex < bbSkip) { // skip over first bbSkip bbs
            (*bbIndex)++;
            continue;

        }
        unsigned long address = (*iter)->getStartAddress ();
        randID = rand() % USHRT_MAX;
        if(verbose) {
            cout << "Instrumenting Basic Block 0x" << hex << address << " of " <<
                 funcName << " with random id " << randID << endl;
        }

        BPatch_Vector < BPatch_snippet * >instArgs;
        BPatch_constExpr bbId (randID);
        instArgs.push_back (&bbId);
        BPatch_point *bbEntry = (*iter)->findEntryPoint ();
        if (NULL == bbEntry) {
            // warn the user, but continue
            cerr << "Failed to find entry for basic block at 0x" << hex << address
                 << endl;
            (*bbIndex)++;
            continue;
        }
        BPatch_funcCallExpr instIncExpr (*instBBIncFunc, instArgs);
        BPatchSnippetHandle *handle =
            appBin->insertSnippet (instIncExpr, *bbEntry, BPatch_callBefore,
                                   BPatch_lastSnippet);
        if (!handle) {
            // warn the user, but continue to next bb
            cerr << "Failed to insert instrumention in basic block at 0x" << hex <<
                 address << endl;
            (*bbIndex)++;
            continue;
        }

        (*bbIndex)++;
    }

    return true;

}
예제 #3
0
test_results_t test1_33_Mutator::executeTest() 
{
	int pvalue;
	unsigned int i;

	if (isMutateeFortran(appImage)) 
	{
		return SKIPPED;
	}

	BPatch_Vector<BPatch_function *> bpfv;
	const char *fn = "test1_33_func2";
	if (NULL == appImage->findFunction(fn, bpfv) || !bpfv.size()
			|| NULL == bpfv[0])
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		logerror("    Unable to find function %s\n", fn);
		return FAILED;
	}

	BPatch_function *func2 = bpfv[0];

	BPatch_flowGraph *cfg = func2->getCFG();
	if (cfg == NULL) 
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		logerror("  Unable to get control flow graph of %s\n", fn);
		return FAILED;
	}

	/*
	 * Test for consistency of entry basic blocks.
	 */

	BPatch_Vector<BPatch_basicBlock*> entry_blocks;
	cfg->getEntryBasicBlock(entry_blocks);

	if (entry_blocks.size() != 1) 
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		logerror("  Detected %d entry basic blocks in %s, should have been one.\n", entry_blocks.size(), fn);
		return FAILED;
	}

	for (i = 0; i < entry_blocks.size(); i++) 
	{
		BPatch_Vector<BPatch_basicBlock*> sources;
		entry_blocks[i]->getSources(sources);

		if (sources.size() > 0) 
		{
			logerror("**Failed** test #33 (control flow graphs)\n");
			logerror("  An entry basic block has incoming edges in the control flow graph\n");
			return FAILED;
		}

		BPatch_Vector<BPatch_basicBlock*> targets;
		entry_blocks[i]->getTargets(targets);

		if (targets.size() < 1) 
		{
			logerror("**Failed** test #33 (control flow graphs\n");
			logerror("  An entry basic block has no outgoing edges in the control flow graph\n");
			return FAILED;
		}
	}

	/*
	 * Test for consistency of exit basic blocks.
	 */

	BPatch_Vector<BPatch_basicBlock*> exit_blocks;
	cfg->getExitBasicBlock(exit_blocks);

	if (exit_blocks.size() != 1) 
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		logerror("  Detected %d exit basic blocks in %s, should have been one.\n", exit_blocks.size(), fn);
		return FAILED;
	}

	for (i = 0; i < exit_blocks.size(); i++) 
	{
		BPatch_Vector<BPatch_basicBlock*> sources;
		exit_blocks[i]->getSources(sources);

		if (sources.size() < 1) 
		{
			logerror("**Failed** test #33 (control flow graphs)\n");
			logerror("  An exit basic block has no incoming edges in the control flow graph\n");
			return FAILED;
		}

		BPatch_Vector<BPatch_basicBlock*> targets;
		exit_blocks[i]->getTargets(targets);

		if (targets.size() > 0) 
		{
			logerror("**Failed** test #33 (control flow graphs)\n");
			logerror("  An exit basic block has outgoing edges in the control flow graph\n");
			return FAILED;
		}
	}

	/*
	 * Check structure of control flow graph.
	 */

        std::set<BPatch_basicBlock*> blocks;
	cfg->getAllBasicBlocks(blocks);

	if (blocks.size() < 4) 
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		logerror("  Detected %d basic blocks in %s, should be at least four.\n", blocks.size(), fn);
		return FAILED;
	}

	bool foundOutDegreeTwo = false;
	bool foundInDegreeTwo = false;
	int blocksNoIn = 0, blocksNoOut = 0;

        for (std::set<BPatch_basicBlock *>::iterator iter = blocks.begin();
             iter != blocks.end(); ++iter) {
           BPatch_Vector<BPatch_basicBlock*> in;
           BPatch_Vector<BPatch_basicBlock*> out;
           
           (*iter)->getSources(in);
           (*iter)->getTargets(out);
           
           if (in.size() == 0)
              blocksNoIn++;
           
           if (out.size() == 0)
              blocksNoOut++;
           
           if (in.size() > 2 || out.size() > 2) 
           {
              logerror("**Failed** test #33 (control flow graphs)\n");
              logerror("  Detected a basic block in %s with %d incoming edges and %d\n", fn, in.size(), out.size());
              logerror("  outgoing edges - neither should be greater than two.\n");
              return FAILED;
           } 
           else if (in.size() > 1 && out.size() > 1) 
           {
              logerror("**Failed** test #33 (control flow graphs)\n");
              logerror("  Detected a basic block in %s with %d incoming edges and %d\n", fn, in.size(), out.size());
              logerror("  outgoing edges - only one should be greater than one.\n");
              return FAILED;
           } 
           else if (in.size() == 0 && out.size() == 0) 
           {
              logerror("**Failed** test #33 (control flow graphs)\n");
              logerror("  Detected a basic block in %s with no incoming or outgoing edges.\n", fn);
              return FAILED;
           } 
           else if (in.size() == 2) 
           {
              assert(out.size() <= 1);
              
              if (foundInDegreeTwo) 
              {
                 logerror("**Failed** test #33 (control flow graphs)\n");
                 logerror("  Detected two basic blocks in %s with in degree two, there should only\n", fn);
                 logerror("  be one.\n");
                 return FAILED;
              }
              foundInDegreeTwo = true;
              
              if (in[0]->getBlockNumber() == in[1]->getBlockNumber()) 
              {
                 logerror("**Failed** test #33 (control flow graphs)\n");
                 logerror("  Two edges go to the same block (number %d).\n", in[0]->getBlockNumber());
                 return FAILED;
              }
           } 
           else if (out.size() == 2) 
           {
              assert(in.size() <= 1);
              
              if (foundOutDegreeTwo) 
              {
                 logerror("**Failed** test #33 (control flow graphs)\n");
                 logerror("  Detected two basic blocks in %s with out degree two, there should only\n", fn);
                 logerror("  be one.\n");
                 return FAILED;
              }
              foundOutDegreeTwo = true;
              
              if (out[0]->getBlockNumber() == out[1]->getBlockNumber()) 
              {
                 logerror("**Failed** test #33 (control flow graphs)\n");
                 logerror("  Two edges go to the same block (number %d).\n", out[0]->getBlockNumber());
                 return FAILED;
              }
           } 
           else if (in.size() > 1 || out.size() > 1) 
           {
              /* Shouldn't be able to get here. */
              logerror("**Failed** test #33 (control flow graphs)\n");
              logerror("  Detected a basic block in %s with %d incoming edges and %d\n", fn, in.size(), out.size());
              logerror("  outgoing edges.\n");
              return FAILED;
           }
	}
        
	if (blocksNoIn > 1) 
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		logerror("  Detected more than one block in %s with no incoming edges.\n", fn);
		return FAILED;
	}

	if (blocksNoOut > 1) 
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		logerror("  Detected more than block in %s with no outgoing edges.\n", fn);
		return FAILED;
	}

	if (!foundOutDegreeTwo) 
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		logerror("  Did not detect the \"if\" statement in %s.\n", fn);
		return FAILED;
	}

	/*
	 * Check for loops (there aren't any in the function we're looking at).
	 */

	std::set<int> empty;

	if (hasBackEdge(entry_blocks[0], empty)) 
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		logerror("  Detected a loop in %s, there should not be one.\n", fn);
		return FAILED;
	}

	/*
	 * Now check a function with a switch statement.
	 */
	bpfv.clear();
	const char *fn2 = "test1_33_func3";

	// Bernat, 8JUN05 -- include uninstrumentable here...

	if (NULL == appImage->findFunction(fn2, bpfv, false, false, true) || !bpfv.size()
			|| NULL == bpfv[0])
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		logerror("    Unable to find function %s\n", fn2);
		return FAILED;
	}

	BPatch_function *func3 = bpfv[0];
	BPatch_flowGraph *cfg3 = func3->getCFG();

	if (cfg3 == NULL) 
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		logerror("  Unable to get control flow graph of %s\n", fn2);
		return FAILED;
	}

        std::set<BPatch_basicBlock*> blocks3;
	cfg3->getAllBasicBlocks(blocks3);

	if (blocks3.size() < 10) 
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		logerror("  Detected %d basic blocks in %s, should be at least ten.\n", blocks3.size(), fn2);
		return FAILED;
	}

	bool foundSwitchIn = false;
	bool foundSwitchOut = false;
	bool foundRangeCheck = false;

        for (std::set<BPatch_basicBlock *>::iterator iter = blocks3.begin();
             iter != blocks3.end(); ++iter) {
           BPatch_basicBlock *block = *iter;

           BPatch_Vector<BPatch_basicBlock*> in;
           BPatch_Vector<BPatch_basicBlock*> out;
           
           block->getSources(in);
           block->getTargets(out);

           if (!foundSwitchOut && out.size() >= 10 && in.size() <= 1) 
           {
              foundSwitchOut = true;
           } 
           else if (!foundSwitchIn && in.size() >= 10 && out.size() <= 1) 
           {
              foundSwitchIn = true;
           } 
           else if (!foundRangeCheck && out.size() == 2 && in.size() <= 1) 
           {
              foundRangeCheck = true;
           } 
           else if (in.size() > 1 && out.size() > 1) 
           {
              logerror("**Failed** test #33 (control flow graphs)\n");
              logerror("  Found basic block in %s with unexpected number of edges.\n", fn2);
              logerror("  %d incoming edges, %d outgoing edges.\n",
                       in.size(), out.size());
              return FAILED;
           }
	}

	if (!foundSwitchIn || !foundSwitchOut) 
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		if (!foundSwitchIn)
			logerror("  Did not find \"switch\" statement in %s.\n", fn2);
		if (!foundSwitchOut)
			logerror("  Did not find block after \"switch\" statement.\n");
		return FAILED;
	}

	/* Check dominator info. */
	BPatch_Vector<BPatch_basicBlock*> entry3;
	cfg3->getEntryBasicBlock(entry3);

	if (entry3.size() != 1) 
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		logerror("  Detected %d entry basic blocks in %s, should have been one.\n", entry_blocks.size(), fn2);
		return FAILED;
	}

        for (std::set<BPatch_basicBlock *>::iterator iter2 = blocks3.begin();
             iter2 != blocks3.end(); ++iter2) {
           if (!entry3[0]->dominates(*iter2))  {
              logerror("**Failed** test #33 (control flow graphs)\n");
              logerror("  Entry block does not dominate all blocks in %s\n", fn2);
              return FAILED;
           }
	}

	BPatch_Vector<BPatch_basicBlock*> exit3;
	cfg3->getExitBasicBlock(exit3);

	if (exit3.size() != 1) 
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		logerror("  Detected %d exit basic blocks in  %s, should have been one.\n", exit3.size(), fn2);
		for (unsigned i = 0; i < exit3.size(); ++i) {
		  logerror("\t%d: 0x%lx\n", i, exit3[i]->getStartAddress());
		}
		return FAILED;
	}

	for (i = 0; i < (unsigned int) exit3.size(); i++) 
	{
		if (!exit3[i]->postdominates(entry3[0])) 
		{
			logerror("**Failed** test #33 (control flow graphs)\n");
			logerror("  Exit block %d does not postdominate all entry blocks in %s\n", i, fn2);
			return FAILED;
		}
	}
#if !defined(os_windows_test) && defined(ENABLE_PARSE_API_GRAPHS)
	logerror("Testing parseAPI dominators\n");
	
	ParseAPI::Function* parse_func = ParseAPI::convert(func3);
	assert(parse_func);
	Block* parse_entry = parse_func->entry();
	bool parse_idoms_ok = true;
	for(Function::blocklist::const_iterator bl = parse_func->blocks().begin();
	    bl != parse_func->blocks().end();
	    ++bl)
	{
	  if(*bl == parse_entry) continue;
	  if(!dominates(*parse_func, parse_entry, *bl))
	  {
	    parse_idoms_ok = false;
	  }
	}
	if(!parse_idoms_ok)
	{
	  logerror("**Failed** test #33 (CFG)\n");
	  logerror("  ParseAPI dominator algorithm does not have entry block dominating all blocks in function\n");
	  return FAILED;
	}
#endif	
		      

	BPatch_variableExpr *expr33_1 = 
		appImage->findVariable("test1_33_globalVariable1");
	if (expr33_1 == NULL) 
	{
		logerror("**Failed** test #33 (control flow graphs)\n");
		logerror("    Unable to locate test1_33_globalVariable1\n");
		return FAILED;
	} 

	pvalue = 1;
	expr33_1->writeValue(&pvalue);

	return PASSED;
}
예제 #4
0
bool instrumentMemoryWrites(dynHandle *dh, BPatch_function *func)
{
   BPatch_Set<BPatch_basicBlock*> allBlocks;
   BPatch_snippet incSnippet; 
   BPatch_Set<BPatch_opCode> ops;
   BPatch_Set<BPatch_basicBlock*>::iterator iter;
   int bb_warn_cnt = 0, bb_pass_cnt = 0;

   sendMsg(config.outfd, ID_INST_MEM_WRITE, VERB2);

   sendMsg(config.outfd, ID_GET_CFG, VERB3);
   BPatch_flowGraph *appCFG = func->getCFG();
   if (!appCFG) {
      sendMsg(config.outfd, ID_GET_CFG, VERB3, ID_FAIL,
              "Failure in BPatch_function::getCFG()");
      goto fail;

   } else {
      sendMsg(config.outfd, ID_GET_CFG, VERB3, ID_PASS);
   }

   sendMsg(config.outfd, ID_INST_GET_BB, VERB3);
   if (!appCFG->getAllBasicBlocks(allBlocks)) {
      sendMsg(config.outfd, ID_INST_GET_BB, VERB3, ID_FAIL,
              "Failure in BPatch_flowGraph::getAllBasicBlocks()");
      goto fail;

   } else if (allBlocks.size() == 0) {
      sendMsg(config.outfd, ID_INST_GET_BB, VERB3, ID_WARN,
              "No basic blocks found in function");
      goto fail;

   } else {
      sendMsg(config.outfd, ID_INST_GET_BB, VERB3, ID_PASS);
   }

   if (! generateInstrumentation (dh, func, &incSnippet))
    	goto fail;

   ops.insert(BPatch_opStore);

   sendMsg(config.outfd, ID_INST_BB_LIST, VERB3);
   for (iter = allBlocks.begin(); iter != allBlocks.end(); iter++) {
      if (!shouldInsert())
         continue;
      sendMsg(config.outfd, ID_INST_GET_BB_POINTS, VERB4);
      BPatch_Vector<BPatch_point*> *points = (*iter)->findPoint(ops);
      if (!points) {
         sendMsg(config.outfd, ID_INST_GET_BB_POINTS, VERB4, ID_WARN,
                 "Failure in BPatch_basicBlock::findPoint()");
         ++bb_warn_cnt;
         continue;

      } else if (points->size() == 0) {
         sendMsg(config.outfd,  ID_INST_GET_BB_POINTS, VERB4, ID_WARN,
                 "No instrumentation points found in basic block");
         ++bb_warn_cnt;
         continue;

      } else {
         sendMsg(config.outfd, ID_INST_GET_BB_POINTS, VERB4, ID_PASS);
      }

      sendMsg(config.outfd, ID_INST_INSERT_CODE, VERB4);
      BPatchSnippetHandle *handle = dh->addSpace->insertSnippet(incSnippet, *points);
      if (!handle) {
         sendMsg(config.outfd, ID_INST_INSERT_CODE, VERB4, ID_FAIL,
                 "Failure in BPatch_process::insertSnippet()");
         ++bb_warn_cnt;
         continue;

      } else {
         sendMsg(config.outfd, ID_INST_INSERT_CODE, VERB4, ID_PASS);
         ++bb_pass_cnt;
      }
   }
   if (bb_warn_cnt)
      sendMsg(config.outfd, ID_INST_BB_LIST, VERB3, ID_WARN,
              sprintf_static("%d warning(s), %d passed.", bb_warn_cnt, bb_pass_cnt));
   else
      sendMsg(config.outfd, ID_INST_BB_LIST, VERB3, ID_PASS);

   sendMsg(config.outfd, ID_INST_MEM_WRITE, VERB2, ID_PASS);
   return true;

 fail:
   sendMsg(config.outfd, ID_INST_MEM_WRITE, VERB2, ID_WARN,
           "Failure while instrumenting memory writes.");
   return false;

}
예제 #5
0
void
dyninst_analyze_address_taken(BPatch_addressSpace *handle, DICFG *cfg)
{
	/* XXX: this is the most naive address-taken analysis that can be used by the
         * lbr_analysis_pass. More sophisticated ones can be (and are) plugged in in the pass.
         * This naive solution is provided only for comparison with more sophisticated ones.
	 * 
         * This analysis looks for instruction operands that correspond to known function addresses,
         * and then marks these functions as having their address taken. In particular, we
         * do /not/ look for function pointers stored in (static) memory, or for function
         * pointers that are computed at runtime. 
         */

	SymtabCodeSource *sts;
	CodeObject *co;

	std::vector<BPatch_object*> objs;
	handle->getImage()->getObjects(objs);
	assert(objs.size() > 0);
	const char *bin = objs[0]->pathName().c_str();

	// Create a new binary object 
	sts 	= new SymtabCodeSource((char*)bin);
	co 	= new CodeObject(sts);

	// Parse the binary 
	co->parse(); 

	BPatch_image *image = handle->getImage();
	std::vector<BPatch_module *> *mods = image->getModules();
	std::vector<BPatch_module *>::iterator mods_iter; 
	for (mods_iter = mods->begin(); mods_iter != mods->end(); mods_iter++) {
		std::vector<BPatch_function *> *funcs = (*mods_iter)->getProcedures(false); 
		std::vector<BPatch_function *>::iterator funcs_iter = funcs->begin();
		for(; funcs_iter != funcs->end(); funcs_iter++) {
			co->parse((Address)(*funcs_iter)->getBaseAddr(), true);
			BPatch_flowGraph *fg = (*funcs_iter)->getCFG();
			std::set<BPatch_basicBlock*> blocks;
			fg->getAllBasicBlocks(blocks);
			std::set<BPatch_basicBlock*>::iterator block_iter;
			for (block_iter = blocks.begin(); block_iter != blocks.end(); ++block_iter) {
				BPatch_basicBlock *block = (*block_iter);
				std::vector<Instruction::Ptr> insns;
				block->getInstructions(insns);
				std::vector<Instruction::Ptr>::iterator insn_iter;
				for (insn_iter = insns.begin(); insn_iter != insns.end(); ++insn_iter) {
					Instruction::Ptr ins = *insn_iter;
					std::vector<Operand> ops;
					ins->getOperands(ops);
					std::vector<Operand>::iterator op_iter;
					for (op_iter = ops.begin(); op_iter != ops.end(); ++op_iter) {
						Expression::Ptr expr = (*op_iter).getValue();

						struct OperandAnalyzer : public Dyninst::InstructionAPI::Visitor {
							virtual void visit(BinaryFunction* op) {};
							virtual void visit(Dereference* op) {}
							virtual void visit(Immediate* op) {
								address_t addr;
								ArmsFunction *func;
								switch(op->eval().type) {
								case s32:
									addr = op->eval().val.s32val;
									break;
								case u32:
									addr = op->eval().val.u32val;
									break;
								case s64:
									addr = op->eval().val.s64val;
									break;
								case u64:
									addr = op->eval().val.u64val;
									break;
								default:
									return;
								}
								func = cfg_->find_function(addr);
								if(func) {
									printf("Instruction [%s] references function 0x%jx\n", ins_->format().c_str(), addr);
									func->set_addr_taken();
								}
							}
							virtual void visit(RegisterAST* op) {}
							OperandAnalyzer(DICFG *cfg, Instruction::Ptr ins) {
								cfg_ = cfg;
								ins_ = ins;
							};
							DICFG *cfg_;
							Instruction::Ptr ins_;
						};

						OperandAnalyzer oa(cfg, ins);
						expr->apply(&oa);
					}
				}
			}
		} 
	}
}