void trace (TRACE trace, void *v) { for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { INS tail = BBL_InsTail(bbl); if (INS_IsRet(tail)) { INS_InsertCall(tail, IPOINT_BEFORE, AFUNPTR(before_return), IARG_THREAD_ID, IARG_REG_VALUE, REG_ESP, IARG_END); } else if (INS_IsCall(tail)) { INS_InsertCall(tail, IPOINT_BEFORE, AFUNPTR(before_call), IARG_THREAD_ID, IARG_REG_VALUE, REG_ESP, IARG_ADDRINT, INS_NextAddress(tail), IARG_BRANCH_TARGET_ADDR, IARG_END); } } }
VOID Instruction(INS ins, VOID *v) { ADDRINT nextAddr = INS_NextAddress(ins); UINT32 maxRRegs = INS_MaxNumRRegs(ins); UINT32 maxWRegs = INS_MaxNumWRegs(ins); USIZE sz = INS_Size(ins); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)RecordFirstInstructionInfo, IARG_THREAD_ID, IARG_INST_PTR, IARG_ADDRINT, nextAddr, IARG_UINT32, maxRRegs, IARG_UINT32, maxWRegs, IARG_ADDRINT, sz, IARG_UINT32, 'r', IARG_END); }
VOID Instruction(INS ins, VOID *v) { ADDRINT nextIns; if (INS_IsRet(ins)) { INS prev = INS_Prev(ins); INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(Ret), IARG_THREAD_ID, IARG_REG_VALUE, REG_STACK_PTR, IARG_BRANCH_TARGET_ADDR, IARG_INST_PTR, IARG_UINT32, (INS_Valid(prev) && INS_Opcode(prev) == XED_CATEGORY_PUSH), IARG_END); } else if (INS_IsCall(ins)) { nextIns = INS_NextAddress(ins); INS_InsertCall(ins, IPOINT_TAKEN_BRANCH, AFUNPTR(Call), IARG_THREAD_ID, IARG_REG_VALUE, REG_STACK_PTR, IARG_BRANCH_TARGET_ADDR, IARG_INST_PTR, IARG_ADDRINT, nextIns, IARG_END); } else if (INS_IsMemoryWrite(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(MemWrite), IARG_THREAD_ID, IARG_MEMORYWRITE_EA, IARG_INST_PTR, IARG_END); } }
// Returns a pointer to an IRBuilder object. // It is up to the user to delete it when times come. IRBuilder *createIRBuilder(INS ins) { uint64 address = INS_Address(ins); std::string disas = INS_Disassemble(ins); INT32 opcode = INS_Opcode(ins); IRBuilder *ir = nullptr; switch (opcode) { case XED_ICLASS_ADC: ir = new AdcIRBuilder(address, disas); break; case XED_ICLASS_ADD: ir = new AddIRBuilder(address, disas); break; case XED_ICLASS_AND: ir = new AndIRBuilder(address, disas); break; case XED_ICLASS_ANDNPD: ir = new AndnpdIRBuilder(address, disas); break; case XED_ICLASS_ANDNPS: ir = new AndnpsIRBuilder(address, disas); break; case XED_ICLASS_ANDPD: ir = new AndpdIRBuilder(address, disas); break; case XED_ICLASS_ANDPS: ir = new AndpsIRBuilder(address, disas); break; case XED_ICLASS_BSWAP: ir = new BswapIRBuilder(address, disas); break; case XED_ICLASS_CALL_FAR: case XED_ICLASS_CALL_NEAR: ir = new CallIRBuilder(address, disas); break; case XED_ICLASS_CBW: ir = new CbwIRBuilder(address, disas); break; case XED_ICLASS_CDQE: ir = new CdqeIRBuilder(address, disas); break; case XED_ICLASS_CLC: ir = new ClcIRBuilder(address, disas); break; case XED_ICLASS_CLD: ir = new CldIRBuilder(address, disas); break; case XED_ICLASS_CMC: ir = new CmcIRBuilder(address, disas); break; case XED_ICLASS_CMOVB: ir = new CmovbIRBuilder(address, disas); break; case XED_ICLASS_CMOVBE: ir = new CmovbeIRBuilder(address, disas); break; case XED_ICLASS_CMOVL: ir = new CmovlIRBuilder(address, disas); break; case XED_ICLASS_CMOVLE: ir = new CmovleIRBuilder(address, disas); break; case XED_ICLASS_CMOVNB: ir = new CmovnbIRBuilder(address, disas); break; case XED_ICLASS_CMOVNBE: ir = new CmovnbeIRBuilder(address, disas); break; case XED_ICLASS_CMOVNL: ir = new CmovnlIRBuilder(address, disas); break; case XED_ICLASS_CMOVNLE: ir = new CmovnleIRBuilder(address, disas); break; case XED_ICLASS_CMOVNO: ir = new CmovnoIRBuilder(address, disas); break; case XED_ICLASS_CMOVNP: ir = new CmovnpIRBuilder(address, disas); break; case XED_ICLASS_CMOVNS: ir = new CmovnsIRBuilder(address, disas); break; case XED_ICLASS_CMOVNZ: ir = new CmovnzIRBuilder(address, disas); break; case XED_ICLASS_CMOVO: ir = new CmovoIRBuilder(address, disas); break; case XED_ICLASS_CMOVP: ir = new CmovpIRBuilder(address, disas); break; case XED_ICLASS_CMOVS: ir = new CmovsIRBuilder(address, disas); break; case XED_ICLASS_CMOVZ: ir = new CmovzIRBuilder(address, disas); break; case XED_ICLASS_CMP: ir = new CmpIRBuilder(address, disas); break; case XED_ICLASS_CQO: ir = new CqoIRBuilder(address, disas); break; case XED_ICLASS_CWDE: ir = new CwdeIRBuilder(address, disas); break; case XED_ICLASS_DEC: ir = new DecIRBuilder(address, disas); break; case XED_ICLASS_DIV: ir = new DivIRBuilder(address, disas); break; case XED_ICLASS_IDIV: ir = new IdivIRBuilder(address, disas); break; case XED_ICLASS_IMUL: ir = new ImulIRBuilder(address, disas); break; case XED_ICLASS_INC: ir = new IncIRBuilder(address, disas); break; case XED_ICLASS_JB: ir = new JbIRBuilder(address, disas); break; case XED_ICLASS_JBE: ir = new JbIRBuilder(address, disas); break; case XED_ICLASS_JL: ir = new JlIRBuilder(address, disas); break; case XED_ICLASS_JLE: ir = new JleIRBuilder(address, disas); break; case XED_ICLASS_JMP: ir = new JmpIRBuilder(address, disas); break; case XED_ICLASS_JNB: ir = new JnbIRBuilder(address, disas); break; case XED_ICLASS_JNBE: ir = new JnbeIRBuilder(address, disas); break; case XED_ICLASS_JNL: ir = new JnlIRBuilder(address, disas); break; case XED_ICLASS_JNLE: ir = new JnleIRBuilder(address, disas); break; case XED_ICLASS_JNO: ir = new JnoIRBuilder(address, disas); break; case XED_ICLASS_JNP: ir = new JnpIRBuilder(address, disas); break; case XED_ICLASS_JNS: ir = new JnsIRBuilder(address, disas); break; case XED_ICLASS_JNZ: ir = new JnzIRBuilder(address, disas); break; case XED_ICLASS_JO: ir = new JoIRBuilder(address, disas); break; case XED_ICLASS_JP: ir = new JpIRBuilder(address, disas); break; case XED_ICLASS_JS: ir = new JsIRBuilder(address, disas); break; case XED_ICLASS_JZ: ir = new JzIRBuilder(address, disas); break; case XED_ICLASS_LEA: ir = new LeaIRBuilder(address, disas); break; case XED_ICLASS_LEAVE: ir = new LeaveIRBuilder(address, disas); break; case XED_ICLASS_MOV: ir = new MovIRBuilder(address, disas); break; case XED_ICLASS_MOVAPD: ir = new MovapdIRBuilder(address, disas); break; case XED_ICLASS_MOVAPS: ir = new MovapsIRBuilder(address, disas); break; case XED_ICLASS_MOVDQA: ir = new MovdqaIRBuilder(address, disas); break; case XED_ICLASS_MOVDQU: ir = new MovdquIRBuilder(address, disas); break; case XED_ICLASS_MOVHLPS: ir = new MovhlpsIRBuilder(address, disas); break; case XED_ICLASS_MOVHPD: ir = new MovhpdIRBuilder(address, disas); break; case XED_ICLASS_MOVHPS: ir = new MovhpsIRBuilder(address, disas); break; case XED_ICLASS_MOVLHPS: ir = new MovlhpsIRBuilder(address, disas); break; case XED_ICLASS_MOVLPD: ir = new MovlpdIRBuilder(address, disas); break; case XED_ICLASS_MOVLPS: ir = new MovlpsIRBuilder(address, disas); break; case XED_ICLASS_MOVSX: case XED_ICLASS_MOVSXD: ir = new MovsxIRBuilder(address, disas); break; case XED_ICLASS_MOVZX: ir = new MovzxIRBuilder(address, disas); break; case XED_ICLASS_MUL: ir = new MulIRBuilder(address, disas); break; case XED_ICLASS_NEG: ir = new NegIRBuilder(address, disas); break; case XED_ICLASS_NOT: ir = new NotIRBuilder(address, disas); break; case XED_ICLASS_OR: ir = new OrIRBuilder(address, disas); break; case XED_ICLASS_ORPD: ir = new OrpdIRBuilder(address, disas); break; case XED_ICLASS_ORPS: ir = new OrpsIRBuilder(address, disas); break; case XED_ICLASS_POP: ir = new PopIRBuilder(address, disas); break; case XED_ICLASS_PUSH: ir = new PushIRBuilder(address, disas); break; case XED_ICLASS_RET_FAR: case XED_ICLASS_RET_NEAR: ir = new RetIRBuilder(address, disas); break; case XED_ICLASS_ROL: ir = new RolIRBuilder(address, disas); break; case XED_ICLASS_ROR: ir = new RorIRBuilder(address, disas); break; case XED_ICLASS_SAR: ir = new SarIRBuilder(address, disas); break; case XED_ICLASS_SBB: ir = new SbbIRBuilder(address, disas); break; case XED_ICLASS_SETB: ir = new SetbIRBuilder(address, disas); break; case XED_ICLASS_SETBE: ir = new SetbeIRBuilder(address, disas); break; case XED_ICLASS_SETL: ir = new SetlIRBuilder(address, disas); break; case XED_ICLASS_SETLE: ir = new SetleIRBuilder(address, disas); break; case XED_ICLASS_SETNB: ir = new SetnbIRBuilder(address, disas); break; case XED_ICLASS_SETNBE: ir = new SetnbeIRBuilder(address, disas); break; case XED_ICLASS_SETNL: ir = new SetnlIRBuilder(address, disas); break; case XED_ICLASS_SETNLE: ir = new SetnleIRBuilder(address, disas); break; case XED_ICLASS_SETNO: ir = new SetnoIRBuilder(address, disas); break; case XED_ICLASS_SETNP: ir = new SetnpIRBuilder(address, disas); break; case XED_ICLASS_SETNS: ir = new SetnsIRBuilder(address, disas); break; case XED_ICLASS_SETNZ: ir = new SetnzIRBuilder(address, disas); break; case XED_ICLASS_SETO: ir = new SetoIRBuilder(address, disas); break; case XED_ICLASS_SETP: ir = new SetpIRBuilder(address, disas); break; case XED_ICLASS_SETS: ir = new SetsIRBuilder(address, disas); break; case XED_ICLASS_SETZ: ir = new SetzIRBuilder(address, disas); break; case XED_ICLASS_SHL: // XED_ICLASS_SAL is also a SHL ir = new ShlIRBuilder(address, disas); break; case XED_ICLASS_SHR: ir = new ShrIRBuilder(address, disas); break; case XED_ICLASS_STC: ir = new StcIRBuilder(address, disas); break; case XED_ICLASS_STD: ir = new StdIRBuilder(address, disas); break; case XED_ICLASS_SUB: ir = new SubIRBuilder(address, disas); break; case XED_ICLASS_TEST: ir = new TestIRBuilder(address, disas); break; case XED_ICLASS_XADD: ir = new XaddIRBuilder(address, disas); break; case XED_ICLASS_XCHG: ir = new XchgIRBuilder(address, disas); break; case XED_ICLASS_XOR: ir = new XorIRBuilder(address, disas); break; case XED_ICLASS_XORPD: ir = new XorpdIRBuilder(address, disas); break; case XED_ICLASS_XORPS: ir = new XorpsIRBuilder(address, disas); break; default: ir = new NullIRBuilder(address, disas); break; } // Populate the operands const uint32 n = INS_OperandCount(ins); for (uint32 i = 0; i < n; ++i) { IRBuilderOperand::operand_t type; uint32 size = 0; uint64 val = 0; //Effective address = Displacement + BaseReg + IndexReg * Scale uint64 displacement = 0; uint64 baseReg = ID_INVALID; uint64 indexReg = ID_INVALID; uint64 memoryScale = 0; /* Special case */ if (INS_IsDirectBranchOrCall(ins)){ ir->addOperand(TritonOperand(IRBuilderOperand::IMM, INS_DirectBranchOrCallTargetAddress(ins), 0)); if (INS_MemoryOperandIsWritten(ins, 0)) ir->addOperand(TritonOperand(IRBuilderOperand::MEM_W, 0, INS_MemoryWriteSize(ins))); break; } /* Immediate */ if (INS_OperandIsImmediate(ins, i)) { type = IRBuilderOperand::IMM; val = INS_OperandImmediate(ins, i); } /* Register */ else if (INS_OperandIsReg(ins, i)) { type = IRBuilderOperand::REG; REG reg = INS_OperandReg(ins, i); val = PINConverter::convertDBIReg2TritonReg(reg); // store the register ID. if (REG_valid(reg)) { // check needed because instructions like "xgetbv 0" make // REG_Size crash. size = REG_Size(reg); } } /* Memory */ else if (INS_MemoryOperandCount(ins) > 0) { /* Memory read */ if (INS_MemoryOperandIsRead(ins, 0)) { type = IRBuilderOperand::MEM_R; size = INS_MemoryReadSize(ins); } /* Memory write */ else { type = IRBuilderOperand::MEM_W; size = INS_MemoryWriteSize(ins); } } /* load effective address instruction */ else if (INS_OperandIsAddressGenerator(ins, i)) { REG reg; type = IRBuilderOperand::LEA; displacement = INS_OperandMemoryDisplacement(ins, i); memoryScale = INS_OperandMemoryScale(ins, i); reg = INS_OperandMemoryBaseReg(ins, i); if (REG_valid(reg)) baseReg = PINConverter::convertDBIReg2TritonReg(reg); reg = INS_OperandMemoryIndexReg(ins, i); if (REG_valid(reg)) indexReg = PINConverter::convertDBIReg2TritonReg(reg); } /* Undefined */ else { // std::cout << "[DEBUG] Unknown kind of operand: " << INS_Disassemble(ins) << std::endl; continue; } ir->addOperand(TritonOperand(type, val, size, displacement, baseReg, indexReg, memoryScale)); } // Setup the opcode in the IRbuilder ir->setOpcode(opcode); ir->setOpcodeCategory(INS_Category(ins)); ir->setNextAddress(INS_NextAddress(ins)); return ir; }
// Pin calls this function before a code sequence is executed for the first time VOID TraceCalls(INS ins, VOID *v) { // If we don't have a proper config, we cannot instrument anything if (config == NULL) { return; } ADDRINT addr = INS_Address(ins); IMG img = IMG_FindByAddress(addr); // We are interested only calls from the JITted code. That code is not part of any valid image if (IMG_Valid(img) && img != config->img) { return; } // We don't know the origins of the calls (only the targets) so we need to instrument every call if (INS_IsCall(ins)) { bool ok = false; if (INS_RegRContain(ins, REG_EAX) || INS_RegRContain(ins, REG_EDX)) { ok = true; } else if (INS_IsDirectCall(ins)) { ADDRINT target_addr = INS_DirectBranchOrCallTargetAddress(ins); IMG target_img = IMG_FindByAddress(target_addr); if (!IMG_Valid(img) || img == config->img) { ok = true; } } if (ok) { // Select which call analysis function to use depending on whether we are in fast mode AFUNPTR analysisFunc = (AFUNPTR)MethodCallAnalysis; if (KnobFast.Value()) { analysisFunc = (AFUNPTR)MethodCallAnalysisFast; } ADDRINT ret_addr = INS_NextAddress(ins); INS_InsertIfCall(ins, IPOINT_BEFORE, (AFUNPTR)ShouldCallBeAnalyzed, IARG_FUNCARG_CALLSITE_REFERENCE, 0, IARG_ADDRINT, ret_addr, IARG_BRANCH_TARGET_ADDR, IARG_END); INS_InsertThenCall(ins, IPOINT_BEFORE, analysisFunc, IARG_FUNCARG_CALLSITE_REFERENCE, 0, IARG_ADDRINT, ret_addr, IARG_BRANCH_TARGET_ADDR, IARG_END); returnAddressToInstument[ret_addr] = true; return; } } if (returnAddressToInstument.find(addr) != returnAddressToInstument.end()) { // Select which call analysis function to use depending on whether we are in fast mode AFUNPTR analysisFuncIf = (AFUNPTR)ShouldReturnAddressBeAnalyzed; AFUNPTR analysisFuncThen = (AFUNPTR)ReturnValueAnalysis; if (KnobFast.Value()) { analysisFuncIf = (AFUNPTR)ShouldReturnAddressBeAnalyzedFast; analysisFuncThen = (AFUNPTR)ReturnValueAnalysisFast; } INS_InsertIfCall(ins, IPOINT_BEFORE, analysisFuncIf, IARG_ADDRINT, addr, IARG_END); INS_InsertThenCall(ins, IPOINT_BEFORE, analysisFuncThen, IARG_ADDRINT, addr, IARG_REG_VALUE, REG_EAX, IARG_FUNCARG_CALLSITE_REFERENCE, 0, IARG_END); return; } }
VOID Instruction(INS ins, void * v) { // track the write operations if ( INS_IsStackWrite(ins) ) { // map sparse INS addresses to dense IDs //const ADDRINT iaddr = INS_Address(ins); #ifdef STACK const UINT32 size = INS_MemoryWriteSize(ins); const BOOL single = (size <= 4); if( single ) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) StoreSingle, IARG_MEMORYWRITE_EA, IARG_ADDRINT, INS_Address(ins), IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) StoreMulti, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_END); } #endif ; } else if( INS_IsMemoryWrite(ins) ) { #ifdef HEAP const UINT32 size = INS_MemoryWriteSize(ins); const BOOL single = (size <= 4); if( single ) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) StoreSingleH, IARG_MEMORYWRITE_EA, IARG_ADDRINT, INS_Address(ins), IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) StoreMultiH, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_END); } #endif ; } #ifdef STACK // track the frame allocation/deallocation // record the count of function entry and exit via "CALL" and "Execution of the return address-instruction" // assume that the entry instruction will be executed once within each frame INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) CallEnd, IARG_ADDRINT, INS_Address(ins), IARG_END); if( INS_Opcode(ins) == XED_ICLASS_CALL_NEAR ) { ADDRINT nextAddr = INS_NextAddress(ins); //cerr << hex << nextAddr; //ADDRINT callee = INS_DirectBranchOrCallTargetAddress(ins); //cerr << "->" << callee << endl; INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR) CallBegin, IARG_ADDRINT, nextAddr, IARG_BRANCH_TARGET_ADDR, IARG_END); } #endif }
instruction::instruction(const INS& ins) { this->address = INS_Address(ins); this->next_address = INS_NextAddress(ins); // this->opcode = INS_Mnemonic(ins); this->opcode_size = static_cast<uint8_t>(INS_Size(ins)); this->opcode_buffer = std::shared_ptr<uint8_t>(new uint8_t[this->opcode_size], std::default_delete<uint8_t[]>()); PIN_SafeCopy(opcode_buffer.get(), reinterpret_cast<const VOID*>(this->address), this->opcode_size); this->disassemble = INS_Disassemble(ins); // including image, routine auto img = IMG_FindByAddress(this->address); this->including_image = IMG_Valid(img) ? IMG_Name(img) : ""; // this->including_routine = RTN_FindNameByAddress(this->address); PIN_LockClient(); auto routine = RTN_FindByAddress(this->address); PIN_UnlockClient(); if (RTN_Valid(routine)) { auto routine_mangled_name = RTN_Name(routine); this->including_routine_name = PIN_UndecorateSymbolName(routine_mangled_name, UNDECORATION_NAME_ONLY); } else this->including_routine_name = ""; // has fall through this->has_fall_through = INS_HasFallThrough(ins); // is call, ret or syscall this->is_call = INS_IsCall(ins); this->is_branch = INS_IsBranch(ins); this->is_ret = INS_IsRet(ins); this->is_syscall = INS_IsSyscall(ins); this->category = static_cast<xed_category_enum_t>(INS_Category(ins)); this->iclass = static_cast<xed_iclass_enum_t>(INS_Opcode(ins)); // read registers auto read_reg_number = INS_MaxNumRRegs(ins); for (decltype(read_reg_number) reg_id = 0; reg_id < read_reg_number; ++reg_id) { this->src_registers.push_back(INS_RegR(ins, reg_id)); } // written registers auto written_reg_number = INS_MaxNumWRegs(ins); for (decltype(written_reg_number) reg_id = 0; reg_id < written_reg_number; ++reg_id) { this->dst_registers.push_back(INS_RegW(ins, reg_id)); } auto is_special_reg = [](const REG& reg) -> bool { return (reg >= REG_MM_BASE); }; this->is_special = std::any_of(std::begin(this->src_registers), std::end(this->src_registers), is_special_reg) || std::any_of(std::begin(this->dst_registers), std::end(this->dst_registers), is_special_reg) || (this->category == XED_CATEGORY_X87_ALU) || (this->iclass == XED_ICLASS_XEND) || (this->category == XED_CATEGORY_LOGICAL_FP) || (this->iclass == XED_ICLASS_PUSHA) || (this->iclass == XED_ICLASS_PUSHAD) || (this->iclass == XED_ICLASS_PUSHF) || (this->iclass == XED_ICLASS_PUSHFD) || (this->iclass == XED_ICLASS_PUSHFQ); // is memory read, write this->is_memory_read = INS_IsMemoryRead(ins); this->is_memory_write = INS_IsMemoryWrite(ins); this->is_memory_read2 = INS_HasMemoryRead2(ins); }
VOID Ins( INS ins, VOID *v ) { if (KnobDetach > 0 && scount > KnobDetach) return; if (KnobLog) { void *addr = Addrint2VoidStar(INS_Address(ins)); string disasm = INS_Disassemble(ins); PrintIns(addr, disasm.c_str()); } scount++; if (INS_Opcode(ins) == XED_ICLASS_PUSH) { if (INS_OperandIsImmediate(ins, 0)) { ADDRINT value = INS_OperandImmediate(ins, 0); INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmuPushValue), IARG_REG_VALUE, REG_STACK_PTR, IARG_ADDRINT, value, IARG_RETURN_REGS, REG_STACK_PTR, IARG_END); INS_Delete(ins); } else if(INS_OperandIsReg(ins, 0)) { REG reg = INS_OperandReg(ins, 0); INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmuPushValue), IARG_REG_VALUE, REG_STACK_PTR, IARG_REG_VALUE, reg, IARG_RETURN_REGS, REG_STACK_PTR, IARG_END); INS_Delete(ins); } else if(INS_OperandIsMemory(ins, 0)) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmuPushMem), IARG_REG_VALUE, REG_STACK_PTR, IARG_MEMORYREAD_EA, IARG_RETURN_REGS, REG_STACK_PTR, IARG_END); INS_Delete(ins); } else { fprintf(stderr, "EmuPush: unsupported operand type (%p:'%s')\n", Addrint2VoidStar(INS_Address(ins)), INS_Disassemble(ins).c_str()); } } else if (INS_Opcode(ins) == XED_ICLASS_POP) { if(INS_OperandIsReg(ins, 0)) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmuPopReg), IARG_REG_VALUE, REG_STACK_PTR, IARG_REG_REFERENCE, INS_OperandReg(ins, 0), IARG_RETURN_REGS, REG_STACK_PTR, IARG_END); INS_Delete(ins); } else if(INS_OperandIsMemory(ins, 0)) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmuPopMem), IARG_REG_VALUE, REG_STACK_PTR, IARG_MEMORYWRITE_EA, IARG_RETURN_REGS, REG_STACK_PTR, IARG_END); INS_Delete(ins); } else { fprintf(stderr, "EmuPop: unsupported operand type (%p:'%s')\n", Addrint2VoidStar(INS_Address(ins)), INS_Disassemble(ins).c_str()); } } else if (INS_Opcode(ins) == XED_ICLASS_LEAVE) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmuLeave), IARG_REG_VALUE, REG_STACK_PTR, IARG_REG_REFERENCE, REG_GBP, IARG_RETURN_REGS, REG_STACK_PTR, IARG_END); INS_Delete(ins); } else if (INS_IsCall(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmuCall), IARG_ADDRINT, INS_NextAddress(ins), IARG_BRANCH_TARGET_ADDR, IARG_REG_REFERENCE, REG_STACK_PTR, IARG_RETURN_REGS, scratchReg, IARG_END); INS_InsertIndirectJump(ins, IPOINT_AFTER, scratchReg); INS_Delete(ins); } else if (INS_IsRet(ins)) { UINT64 imm = 0; if (INS_OperandCount(ins) > 0 && INS_OperandIsImmediate(ins, 0)) { imm = INS_OperandImmediate(ins, 0); } INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmuRet), IARG_CALL_ORDER, CALL_ORDER_FIRST, IARG_REG_REFERENCE, REG_STACK_PTR, IARG_ADDRINT, (ADDRINT)imm, IARG_RETURN_REGS, scratchReg, IARG_END); INS_InsertIndirectJump(ins, IPOINT_AFTER, scratchReg); INS_Delete(ins); } else if (INS_IsIndirectBranchOrCall(ins)) { // This is not a call (it was checked before) so this is indirect jump INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmuIndJmp), IARG_BRANCH_TARGET_ADDR, IARG_RETURN_REGS, scratchReg, IARG_END); INS_InsertIndirectJump(ins, IPOINT_AFTER, scratchReg); INS_Delete(ins); } }
VOID Instruction(INS ins, VOID *v) { ADDRINT nextAddr = INS_NextAddress(ins); UINT32 maxRRegs = INS_MaxNumRRegs(ins); UINT32 maxWRegs = INS_MaxNumWRegs(ins); ADDRINT sz = INS_Size(ins); if (numContextsInstrumented < 100) { numContextsInstrumented++; INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)RecordContext, // 4 dummy params to get the real params to be pushed on the stack in Intel64 IARG_UINT32, 1, IARG_UINT32, 2, IARG_UINT32, 3, IARG_UINT32, 4, IARG_CONTEXT, IARG_END); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)RecordContextFastCall, IARG_FAST_ANALYSIS_CALL, IARG_CONTEXT, IARG_END); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)VerifyContext, IARG_INST_PTR, IARG_CONTEXT, IARG_END); } else if (numRegularInstrumented < 100) { numRegularInstrumented++; INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)RecordInstructionInfoFastCall, IARG_FAST_ANALYSIS_CALL, IARG_THREAD_ID, IARG_INST_PTR, IARG_REG_VALUE, REG_GFLAGS, IARG_ADDRINT, nextAddr, IARG_UINT32, maxRRegs, IARG_UINT32, maxWRegs, IARG_ADDRINT, sz, #ifdef TARGET_IA32E IARG_ADDRINT, 0xdeadbeefdeadbeefLL, #else IARG_ADDRINT, 0xdeadbeef, #endif IARG_REG_VALUE, REG_GDX, IARG_REG_VALUE, REG_GDX, IARG_REG_VALUE, REG_GDX, IARG_REG_VALUE, REG_GDX, IARG_REG_VALUE, REG_GDX, IARG_REG_VALUE, REG_GDX, IARG_END); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)RecordInstructionInfo, // 4 dummy params to get the real params to be pushed on the stack in Intel64 IARG_UINT32, 1, IARG_UINT32, 2, IARG_UINT32, 3, IARG_UINT32, 4, IARG_THREAD_ID, IARG_INST_PTR, IARG_REG_VALUE, REG_GFLAGS, IARG_ADDRINT, nextAddr, IARG_UINT32, maxRRegs, IARG_UINT32, maxWRegs, IARG_ADDRINT, sz, #ifdef TARGET_IA32E IARG_ADDRINT, 0xdeadbeefdeadbeefLL, #else IARG_ADDRINT, 0xdeadbeef, #endif IARG_REG_VALUE, REG_GDX, IARG_REG_VALUE, REG_GDX, IARG_REG_VALUE, REG_GDX, IARG_REG_VALUE, REG_GDX, IARG_REG_VALUE, REG_GDX, IARG_REG_VALUE, REG_GDX, IARG_END); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)VerifyInstructionInfo, IARG_THREAD_ID, IARG_INST_PTR, IARG_REG_VALUE, REG_GFLAGS, IARG_ADDRINT, nextAddr, IARG_UINT32, maxRRegs, IARG_UINT32, maxWRegs, IARG_ADDRINT, sz, #ifdef TARGET_IA32E IARG_ADDRINT, 0xdeadbeefdeadbeefLL, #else IARG_ADDRINT, 0xdeadbeef, #endif IARG_REG_VALUE, REG_GDX, IARG_REG_VALUE, REG_GDX, IARG_REG_VALUE, REG_GDX, IARG_REG_VALUE, REG_GDX, IARG_REG_VALUE, REG_GDX, IARG_REG_VALUE, REG_GDX, IARG_END); } }
VOID Instruction(INS ins, VOID *v) { PIN_LockClient(); IMG img = IMG_FindByAddress(INS_Address(ins)); PIN_UnlockClient(); if (IMG_Valid(img) && IMG_IsMainExecutable(img)){ if (INS_IsCall(ins)){ INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)PrologueAnalysis, IARG_ADDRINT, INS_Address(ins), IARG_ADDRINT, INS_NextAddress(ins), IARG_PTR, new string(INS_Disassemble(ins)), IARG_END); } else if (INS_IsRet(ins)){ INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)EpilogueAnalysis, IARG_ADDRINT, INS_Address(ins), IARG_ADDRINT, INS_NextAddress(ins), IARG_PTR, new string(INS_Disassemble(ins)), IARG_END); } else if (INS_OperandCount(ins) > 1 && INS_MemoryOperandIsWritten(ins, 0)){ INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)WriteMem, IARG_ADDRINT, INS_Address(ins), IARG_PTR, new string(INS_Disassemble(ins)), IARG_UINT32, INS_OperandCount(ins), IARG_UINT32, INS_OperandReg(ins, 1), IARG_MEMORYOP_EA, 0, IARG_END); } /* Value Set Analysis */ if (INS_Opcode(ins) == XED_ICLASS_MOV && INS_RegR(ins, 0) == REG_RBP && INS_RegR(ins, 1) == REG_INVALID() && INS_IsMemoryWrite(ins)){ INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)ValueSetAnalysis, IARG_ADDRINT, INS_Address(ins), IARG_PTR, new string(INS_Disassemble(ins)), IARG_REG_VALUE, REG_RSP, IARG_REG_VALUE, REG_RBP, IARG_MEMORYOP_EA, 0, IARG_END); } /* Analyzes stack overflow */ if (INS_MemoryOperandIsWritten(ins, 0)){ INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)WriteMemAnalysis, IARG_ADDRINT, INS_Address(ins), IARG_PTR, new string(INS_Disassemble(ins)), IARG_MEMORYOP_EA, 0, IARG_END); } /* Timer Handler - And instruction counter */ INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)timerHandler, IARG_ADDRINT, INS_Address(INS_Prev(ins)), IARG_ADDRINT, INS_Address(ins), IARG_ADDRINT, INS_Address(INS_Next(ins)), IARG_PTR, new string(INS_Disassemble(ins)), IARG_END); } }