bool IA_x86Details::handleAdd(IA_IAPI& block) { parsing_printf("\t found add insn %s without obvious thunk\n", block.getInstruction()->format().c_str()); // Check table insn and bail if it's not of the mov eax, [eax] form // We do this indirectly: if there was already a displacment that we // could find in the table insn, we have a "table address"; otherwise, check adds if(tableInsn.addrFromInsn != 0) { return false; } // Use the add operand as our table base; we're handling tables of the form: // <reg = index> // add reg, $base // mov reg, [reg] // jmp *reg Expression::Ptr addExpr = block.getInstruction()->getOperand(1).getValue(); zeroAllGPRegisters z(block.getAddr()); addExpr->apply(&z); thunkInsn.insn = block.getInstruction(); thunkInsn.addrFromInsn = z.getResult(); thunkInsn.addrOfInsn = block.getAddr(); parsing_printf("\t setting thunk offset to 0x%lx (EXPERIMENTAL!)\n", thunkInsn.addrFromInsn); return thunkInsn.addrFromInsn != 0; }
bool IA_x86Details::handleCall(IA_IAPI& block) { parsing_printf("\tchecking call at 0x%lx for thunk\n", block.getAddr()); if(!block.isRealCall()) { parsing_printf("\tthunk found at 0x%lx, checking for add\n", block.getAddr()); block.advance(); thunkInsn.addrFromInsn = block.getAddr(); Instruction::Ptr addInsn = block.getInstruction(); if(addInsn) parsing_printf("\tinsn after thunk: %s\n", addInsn->format().c_str()); else parsing_printf("\tNO INSN after thunk at 0x%lx\n", thunkInsn.addrFromInsn); if(addInsn) { std::set<RegisterAST::Ptr> boundRegs; if(addInsn->getOperation().getID() == e_pop) { addInsn->getWriteSet(boundRegs); block.advance(); addInsn = block.getInstruction(); } if(addInsn && ((addInsn->getOperation().getID() == e_add) || (addInsn->getOperation().getID() == e_lea))) { Expression::Ptr op0 = addInsn->getOperand(0).getValue(); Expression::Ptr op1 = addInsn->getOperand(1).getValue(); for(std::set<RegisterAST::Ptr>::const_iterator curReg = boundRegs.begin(); curReg != boundRegs.end(); ++curReg) { op0->bind(curReg->get(), Result(u64, 0)); op1->bind(curReg->get(), Result(u64, 0)); } Result imm = addInsn->getOperand(1).getValue()->eval(); Result imm2 = addInsn->getOperand(0).getValue()->eval(); if(imm.defined) { Address thunkDiff = imm.convert<Address>(); parsing_printf("\tsetting thunkInsn.addrFromInsn to 0x%lx (0x%lx + 0x%lx)\n", thunkInsn.addrFromInsn+thunkDiff, thunkInsn.addrFromInsn, thunkDiff); thunkInsn.addrOfInsn = block.getPrevAddr(); thunkInsn.addrFromInsn = thunkInsn.addrFromInsn + thunkDiff; return true; } else if(imm2.defined) { Address thunkDiff = imm2.convert<Address>(); parsing_printf("\tsetting thunkInsn.addrFromInsn to 0x%lx (0x%lx + 0x%lx)\n", thunkInsn.addrFromInsn+thunkDiff, thunkInsn.addrFromInsn, thunkDiff); thunkInsn.addrOfInsn = block.getPrevAddr(); thunkInsn.addrFromInsn = thunkInsn.addrFromInsn + thunkDiff; return true; } else { parsing_printf("\tadd insn %s found following thunk at 0x%lx, couldn't bind operands!\n", addInsn->format().c_str(), thunkInsn.addrFromInsn); } } } thunkInsn.addrFromInsn = 0; } thunkInsn.addrFromInsn = 0; thunkInsn.addrOfInsn = 0; thunkInsn.insn.reset(); return false; }