bool overwriteInstruction(PatchBlock *block, uint64_t addr, uint8_t* val, size_t nbytes) { ParseAPI::Block *b = block->block(); ParseAPI::SymtabCodeRegion *r = dynamic_cast<ParseAPI::SymtabCodeRegion*>(b->region()); if (r == NULL) return false; Offset region_off = (Offset)r->getPtrToInstruction(addr) - (Offset)r->symRegion()->getPtrToRawData(); bool success; success = r->symRegion()->patchData(region_off++, (void*)val, nbytes); return success; }
// 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); for (auto eit = cur->sources().begin(); eit != cur->sources().end(); ++eit) if ((*eit)->intraproc()) q.push((*eit)->src()); } }
// 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 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->obj()->cs()->getPtrToInstruction(b->start())); if( buf == NULL ) { parsing_printf("%s[%d]: failed to get pointer to instruction by offset\n",FILE__, __LINE__); return; } parsing_printf("Looking for thunk in block [%lx,%lx).", b->start(), b->end()); InstructionDecoder dec(buf, b->end() - b->start(), b->obj()->cs()->getArch()); InsnAdapter::IA_IAPI block(dec, b->start(), b->obj() , b->region(), b->obj()->cs(), b); while (block.getAddr() < 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->obj()->cs()->getPtrToInstruction(addr); InstructionDecoder targetChecker(target, InstructionDecoder::maxInstructionLength, b->obj()->cs()->getArch()); Instruction::Ptr 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()); } } block.advance(); } } }
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); } } }