void IndirectControlFlowAnalyzer::FindAllThunks() { // Enumuerate every block to find thunk for (auto bit = reachable.begin(); bit != reachable.end(); ++bit) { // We intentional treat a getting PC call as a special case that does not // end a basic block. So, we need to check every instruction to find all thunks ParseAPI::Block *b = *bit; const unsigned char* buf = (const unsigned char*)(b->region()->getPtrToInstruction(b->start())); if( buf == NULL ) { parsing_printf("%s[%d]: failed to get pointer to instruction by offset\n",FILE__, __LINE__); return; } InstructionDecoder dec(buf, b->end() - b->start(), b->obj()->cs()->getArch()); InsnAdapter::IA_IAPI* block = InsnAdapter::IA_IAPI::makePlatformIA_IAPI(b->obj()->cs()->getArch(), dec, b->start(), b->obj() , b->region(), b->obj()->cs(), b); Address cur = b->start(); while (cur < b->end()) { if (block->getInstruction().getCategory() == c_CallInsn && block->isThunk()) { bool valid; Address addr; boost::tie(valid, addr) = block->getCFT(); const unsigned char *target = (const unsigned char *) b->region()->getPtrToInstruction(addr); InstructionDecoder targetChecker(target, InstructionDecoder::maxInstructionLength, b->obj()->cs()->getArch()); Instruction thunkFirst = targetChecker.decode(); set<RegisterAST::Ptr> thunkTargetRegs; thunkFirst.getWriteSet(thunkTargetRegs); for (auto curReg = thunkTargetRegs.begin(); curReg != thunkTargetRegs.end(); ++curReg) { ThunkInfo t; t.reg = (*curReg)->getID(); t.value = block->getAddr() + block->getInstruction().size(); t.value += ThunkAdjustment(t.value, t.reg, b); t.block = b; thunks.insert(make_pair(block->getAddr(), t)); parsing_printf("\tfind thunk at %lx, storing value %lx to %s\n", block->getAddr(), t.value , t.reg.name().c_str()); } } cur += block->getInstruction().size(); if (cur < b->end()) block->advance(); } delete block; } }
// Find all blocks that reach the block containing the indirect jump void IndirectControlFlowAnalyzer::GetAllReachableBlock() { reachable.clear(); queue<Block*> q; q.push(block); while (!q.empty()) { ParseAPI::Block *cur = q.front(); q.pop(); if (reachable.find(cur) != reachable.end()) continue; reachable.insert(cur); boost::lock_guard<Block> g(*cur); for (auto eit = cur->sources().begin(); eit != cur->sources().end(); ++eit) if ((*eit)->intraproc()) { if ((*eit)->src() == NULL) { fprintf(stderr, "edge type = %d, target block [%lx, %lx)\n", (*eit)->type(), cur->start(), cur->end()); } q.push((*eit)->src()); } } }
void DICFG::insert_functions_and_bbs(const CodeObject::funclist& funcs) { CodeObject::funclist::iterator funcs_iter; PARSE_API_RET_BLOCKLIST::iterator blocks_iter; ParseAPI::Function *fun; ParseAPI::Block *block; ArmsFunction *arms_fun, *cf; ArmsBasicBlock *arms_block; /* Create objects representing individual functions */ for(funcs_iter = funcs.begin(); funcs_iter != funcs.end(); funcs_iter++) { fun = *funcs_iter; if (find_function((address_t)fun->addr())) continue; arms_fun = new ArmsFunction((address_t)fun->addr(), fun->name(), this); store_function(arms_fun); } /* Insert their basic blocks; mark their start and end address, plus set * all containing functions. */ for(funcs_iter = funcs.begin(); funcs_iter != funcs.end(); funcs_iter++) { fun = *funcs_iter; arms_fun = find_function((address_t)fun->addr()); ParseAPI::Function::blocklist blocks = fun->blocks(); for(blocks_iter = blocks.begin(); blocks_iter != blocks.end(); blocks_iter++) { block = *blocks_iter; // fprintf(stderr, "handling bb 0x%lx\n", block->start()); /* don't handle shared blocks multiple times */ if (find_bb((address_t) block->start())) continue; fprintf(stderr, "adding new bb 0x%lx\n", block->start()); arms_block = new ArmsBasicBlock((address_t) block->start(), (address_t) block->end(), (address_t) block->last(), this); store_bb(arms_block); /* add the containing functions */ std::vector<ParseAPI::Function *> containing_funcs; block->getFuncs(containing_funcs); std::vector<ParseAPI::Function *>::iterator cf_iter = containing_funcs.begin(); for ( ; cf_iter != containing_funcs.end(); cf_iter++) { cf = find_function((address_t)((*cf_iter)->addr())); arms_block->add_containing_function(cf); cf->add_bb(arms_block); } } } /* Mark entry bbs and exit bbs */ for(funcs_iter = funcs.begin(); funcs_iter != funcs.end(); funcs_iter++) { fun = *funcs_iter; arms_fun = find_function((address_t)fun->addr()); Block *entry_block = fun->entry(); assert(entry_block); ArmsBasicBlock *arms_entry_block = find_bb((address_t)entry_block->start()); arms_entry_block->set_is_entry_block(); arms_fun->add_entry_block(arms_entry_block); PARSE_API_RET_BLOCKLIST return_blocks = fun->returnBlocks(); for(blocks_iter = return_blocks.begin(); blocks_iter != return_blocks.end(); blocks_iter++) { ArmsBasicBlock *arms_exit_block = find_bb((address_t)(*blocks_iter)->start()); arms_exit_block->set_is_exit_block(); arms_fun->add_exit_block(arms_exit_block); } } }