/****************************************************************** Title:movRMHandler Function:Handler to handle instruction "mov REG [mem addr]" Input: INS ins:Instruction to be handled. int srcA:The 1st src operand. int srcB:The 2nd src operand. int srcC:The 3rd src operand. int dstA:The 1st dst operand. int dstB:The 2nd dst operand. int dstC:The 3rd dst operand. Output: int Return value:-1 means unable to handle the instruction ******************************************************************/ int movRMHandler(INS ins,int srcA,int srcB,int srcC,int dstA,int dstB,int dstC) { REG baseReg = INS_OperandMemoryBaseReg(ins,1); INT64 displacement = INS_OperandMemoryDisplacement(ins,1); REG indexReg = INS_OperandMemoryIndexReg(ins,1); UINT32 scale = INS_OperandMemoryScale(ins,1); if(REG_valid(baseReg)){ INS_InsertCall(ins, IPOINT_AFTER, (AFUNPTR)getRegisterValue, IARG_REG_VALUE,baseReg, IARG_END); } int valueBaseReg = regValue; if(REG_valid(indexReg)){ INS_InsertCall(ins, IPOINT_AFTER, (AFUNPTR)getRegisterValue, IARG_REG_VALUE,indexReg, IARG_END); } int valueIndexReg = regValue; unsigned int realAddress = displacement+valueBaseReg+valueIndexReg*scale; if(INS_IsMemoryRead(ins)){ INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(movRMHook), IARG_UINT32, REG(INS_OperandReg(ins, 0)), IARG_MEMORYREAD_EA, IARG_END); }else{ fprintf(log,"Error at reading memory\n"); return -1; } countAllIns++; countHandledIns++; return 0; }
/* Instrumentation of each instruction * that uses a memory operand */ VOID Instruction(INS ins, VOID *v) { trace_enter(); if (!INS_IsStackRead(ins)) { for (UINT32 memopIdx = 0; memopIdx < INS_MemoryOperandCount(ins); memopIdx++) { if (INS_MemoryOperandIsWritten(ins, memopIdx)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) update_stack_heap_region, IARG_CONST_CONTEXT, IARG_MEMORYOP_EA, memopIdx, IARG_END); UINT32 opIdx = INS_MemoryOperandIndexToOperandIndex(ins, memopIdx); REG base_reg = INS_OperandMemoryBaseReg(ins, opIdx); if (base_reg != REG_INVALID()) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) check_parameter_out, IARG_REG_VALUE, base_reg, IARG_END); } } } } if (INS_IsCall(ins)) { if (INS_IsDirectCall(ins)) { ADDRINT addr = INS_DirectBranchOrCallTargetAddress(ins); FID fid = fn_lookup_by_address(addr); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) fn_call, IARG_CONST_CONTEXT, IARG_UINT32, fid, IARG_END); } else { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) fn_indirect_call, IARG_CONST_CONTEXT, IARG_BRANCH_TARGET_ADDR, IARG_END); } } if (INS_IsRet(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) fn_ret, IARG_CONST_CONTEXT, IARG_END); } trace_leave(); }
REG INS_get_memwr_basereg(INS ins) { for (unsigned int i = 0; i < INS_OperandCount(ins); i++) { if (INS_OperandIsMemory(ins, i) && INS_OperandWritten(ins, i)) { return REG_FullRegName(INS_OperandMemoryBaseReg(ins, i)); } } return REG_INVALID(); }
/****************************************************************** Title:movRRHandler Function:Handler to handle instruction "mov REG REG" Input: INS ins:Instruction to be handled. int srcA:The 1st src operand. int srcB:The 2nd src operand. int srcC:The 3rd src operand. int dstA:The 1st dst operand. int dstB:The 2nd dst operand. int dstC:The 3rd dst operand. Output: int Return value:-1 means unable to handle the instruction ******************************************************************/ int movRRHandler(INS ins,int srcA,int srcB,int srcC,int dstA,int dstB,int dstC) { REG dstReg = INS_OperandMemoryBaseReg(ins,0); REG srcReg = INS_OperandReg(ins,1); int state = regState[srcReg]; if(state==1){ regState[dstReg]=1; }else{ regState[dstReg]=0; } countAllIns++; countHandledIns++; return 0; }
VOID RewriteBases(INS ins, BOOL * live) { for (UINT32 i = 0; i < INS_OperandCount(ins); i++) { if (!INS_OperandIsMemory(ins, i)) continue; if (INS_OperandMemoryIndexReg(ins, i) != REG_INVALID()) { CheckEffectiveAddress(ins); return; } REG baseReg = INS_OperandMemoryBaseReg(ins, i); // If no basereg is used, then it must be an absolute address if (baseReg == REG_INVALID()) continue; // No need to rewrite stack references if (baseReg == REG_ESP) continue; // If we reach this point, we have an instruction that // must be rewritten, but if the memory operand is // implicit, we can't rewrite the base register if (INS_OperandIsImplicit(ins, i)) { CheckEffectiveAddress(ins); return; } REG shadowReg = ShadowReg(baseReg); INS_OperandMemorySetBaseReg(ins, i, shadowReg); // Remember to write the shadow register live[RegIndex(baseReg)] = true; } }
VOID Instruction(INS ins, VOID *v) { INT32 count = INS_OperandCount(ins); for (INT32 i = 0; i < 5; i++) { if (i >= count) { dis << " "; continue; } else if (INS_OperandIsAddressGenerator(ins, i)) dis << "AGN"; else if (INS_OperandIsMemory(ins, i)) { dis << "MEM"; dis << " " << REG_StringShort(INS_OperandMemoryBaseReg(ins, i)); } else if (INS_OperandIsReg(ins, i)) dis << "REG"; else if (INS_OperandIsImmediate(ins, i)) dis << "IMM"; else if (INS_OperandIsDisplacement(ins, i)) dis << "DSP"; else dis << "XXX"; if (INS_OperandIsImplicit(ins, i)) dis << ":IMP "; else dis << " "; } dis << INS_Disassemble(ins) << endl; }
void log_ins(INS ins) { // dump the instruction INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) &execute_instruction, IARG_INST_PTR, IARG_PTR, strdup(INS_Disassemble(ins).c_str()), IARG_END); // reads memory (1) if(INS_IsMemoryRead(ins) != 0) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) &dump_read_memory, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_END); } // reads memory (2) if(INS_HasMemoryRead2(ins) != 0) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) &dump_read_memory, IARG_MEMORYREAD2_EA, IARG_MEMORYREAD_SIZE, IARG_END); } IPOINT after = IPOINT_AFTER; if(INS_IsCall(ins) != 0) { // TODO is this correct? after = IPOINT_TAKEN_BRANCH; } else if(INS_IsSyscall(ins) != 0) { // TODO support syscalls return; } else if(INS_HasFallThrough(ins) == 0 && (INS_IsBranch(ins) != 0 || INS_IsRet(ins) != 0)) { // TODO is this correct? after = IPOINT_TAKEN_BRANCH; } // dump written memory if(INS_IsMemoryWrite(ins) != 0) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) &dump_written_memory_before, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_END); INS_InsertCall(ins, after, (AFUNPTR) &dump_written_memory_after, IARG_END); } // dump all affected registers for (UINT32 i = 0; i < INS_OperandCount(ins); i++) { if(INS_OperandIsMemory(ins, i) != 0) { if(INS_OperandMemoryBaseReg(ins, i) != REG_INVALID()) { REG base_reg = INS_OperandMemoryBaseReg(ins, i); if(g_reg_index[base_reg] != 0) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) &dump_reg_before, IARG_UINT32, g_reg_index[base_reg]-1, IARG_REG_VALUE, INS_OperandMemoryBaseReg(ins, i), IARG_END); INS_InsertCall(ins, after, (AFUNPTR) &dump_reg_r_after, IARG_UINT32, g_reg_index[base_reg]-1, IARG_END); } } if(INS_OperandMemoryIndexReg(ins, i) != REG_INVALID()) { REG index_reg = INS_OperandMemoryIndexReg(ins, i); if(g_reg_index[index_reg] != 0) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) &dump_reg_before, IARG_UINT32, g_reg_index[index_reg]-1, IARG_REG_VALUE, INS_OperandMemoryIndexReg(ins, i), IARG_END); INS_InsertCall(ins, after, (AFUNPTR) &dump_reg_r_after, IARG_UINT32, g_reg_index[index_reg]-1, IARG_END); } } } if(INS_OperandIsReg(ins, i) != 0) { REG reg_index = REG_FullRegName(INS_OperandReg(ins, i)); if(INS_OperandReadAndWritten(ins, i) != 0) { if(g_reg_index[reg_index] != 0) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) &dump_reg_before, IARG_UINT32, g_reg_index[reg_index]-1, IARG_REG_VALUE, reg_index, IARG_END); INS_InsertCall(ins, after, (AFUNPTR) &dump_reg_rw_after, IARG_UINT32, g_reg_index[reg_index]-1, IARG_REG_VALUE, reg_index, IARG_END); } } else if(INS_OperandRead(ins, i) != 0) { if(g_reg_index[reg_index] != 0) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) &dump_reg_before, IARG_UINT32, g_reg_index[reg_index]-1, IARG_REG_VALUE, reg_index, IARG_END); INS_InsertCall(ins, after, (AFUNPTR) &dump_reg_r_after, IARG_UINT32, g_reg_index[reg_index]-1, IARG_END); } } else if(INS_OperandWritten(ins, i) != 0) { if(g_reg_index[reg_index] != 0) { INS_InsertCall(ins, after, (AFUNPTR) &dump_reg_w_after, IARG_UINT32, g_reg_index[reg_index]-1, IARG_REG_VALUE, reg_index, IARG_END); } } } } INS_InsertCall(ins, after, (AFUNPTR) &print_newline, IARG_END); }
VOID HandleAccess (INS ins, BOOL isRead, BOOL *hasSegmentedMemAccess) { UINT32 operandCount = INS_OperandCount (ins); UINT32 i, displacement, scale; REG baseReg = REG_INVALID(), indexReg = REG_INVALID(); *hasSegmentedMemAccess = FALSE; for (i=0; i<operandCount; i++) { if (INS_OperandIsMemory (ins, i) && (INS_OperandMemorySegmentReg (ins, i) == TESTED_SEG_REG ) && ((isRead && INS_OperandRead (ins, i)) || (!isRead && INS_OperandWritten (ins, i))) ) { displacement = INS_OperandMemoryDisplacement (ins, i); baseReg = INS_OperandMemoryBaseReg (ins, i); indexReg = INS_OperandMemoryIndexReg (ins, i); scale = INS_OperandMemoryScale (ins, i); *hasSegmentedMemAccess = TRUE; break; } } /*fprintf(trace, " SegMemAccess-%s (hasSegmentedMemAccess %d) (operand %d) %p %s\n", isRead?"READ":"WRITE", *hasSegmentedMemAccess, i, INS_Address(ins), INS_Disassemble(ins).c_str());*/ if (baseReg != REG_INVALID()) { if (indexReg != REG_INVALID()) { if (isRead) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeSegmentedMemAccessBaseIndexDispl, IARG_INST_PTR, IARG_MEMORYREAD_EA, IARG_UINT32, BASE_INDEX_DISPLACEMENT_ADDRESSING_READ_TYPE, IARG_REG_VALUE, baseReg, IARG_REG_VALUE, indexReg, IARG_UINT32, scale, IARG_UINT32, displacement, IARG_THREAD_ID, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeSegmentedMemAccessBaseIndexDispl, IARG_INST_PTR, IARG_MEMORYWRITE_EA, IARG_UINT32, BASE_INDEX_DISPLACEMENT_ADDRESSING_WRITE_TYPE, IARG_REG_VALUE, baseReg, IARG_REG_VALUE, indexReg, IARG_UINT32, scale, IARG_UINT32, displacement, IARG_THREAD_ID, IARG_END); } } else { if (isRead) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeSegmentedMemAccessBaseDispl, IARG_INST_PTR, IARG_MEMORYREAD_EA, IARG_UINT32, BASE_DISPLACEMENT_ADDRESSING_READ_TYPE, IARG_REG_VALUE, baseReg, IARG_UINT32, displacement, IARG_THREAD_ID, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeSegmentedMemAccessBaseDispl, IARG_INST_PTR, IARG_MEMORYWRITE_EA, IARG_UINT32, BASE_DISPLACEMENT_ADDRESSING_WRITE_TYPE, IARG_REG_VALUE, baseReg, IARG_UINT32, displacement, IARG_THREAD_ID, IARG_END); } } } else if (indexReg != REG_INVALID()) { if (isRead) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeSegmentedMemAccessIndexDispl, IARG_INST_PTR, IARG_MEMORYREAD_EA, IARG_UINT32, INDEX_DISPLACEMENT_ADDRESSING_READ_TYPE, IARG_REG_VALUE, indexReg, IARG_UINT32, scale, IARG_UINT32, displacement, IARG_THREAD_ID, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeSegmentedMemAccessIndexDispl, IARG_INST_PTR, IARG_MEMORYWRITE_EA, IARG_UINT32, INDEX_DISPLACEMENT_ADDRESSING_WRITE_TYPE, IARG_REG_VALUE, indexReg, IARG_UINT32, scale, IARG_UINT32, displacement, IARG_THREAD_ID, IARG_END); } } else if (*hasSegmentedMemAccess) { if (isRead) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeSegmentedMemAccessDispl, IARG_INST_PTR, IARG_MEMORYREAD_EA, IARG_UINT32, DISPLACEMENT_ONLY_ADDRESSING_READ_TYPE, IARG_UINT32, displacement, IARG_THREAD_ID, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeSegmentedMemAccessDispl, IARG_INST_PTR, IARG_MEMORYWRITE_EA, IARG_UINT32, DISPLACEMENT_ONLY_ADDRESSING_WRITE_TYPE, IARG_UINT32, displacement, IARG_THREAD_ID, 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; }
VOID HandleAccess (INS ins, BOOL isRead) { UINT32 operandCount = INS_OperandCount (ins); UINT32 i, displacement=0, scale=0; REG baseReg = REG_INVALID(), indexReg = REG_INVALID(); BOOL instrumented = FALSE; for (i=0; i<operandCount; i++) { if ( ((INS_OperandIsMemory (ins, i) && isRead && INS_OperandRead (ins, i)) || (INS_OperandIsMemory (ins, i) && !isRead && INS_OperandWritten (ins, i))) ) { displacement = INS_OperandMemoryDisplacement (ins, i); baseReg = INS_OperandMemoryBaseReg (ins, i); indexReg = INS_OperandMemoryIndexReg (ins, i); scale = INS_OperandMemoryScale (ins, i); break; } } if (baseReg != REG_INVALID()) { if (indexReg != REG_INVALID()) { if (isRead) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeMemAccessBaseIndexDispl, IARG_INST_PTR, IARG_MEMORYREAD_EA, IARG_UINT32, BASE_INDEX_DISPLACEMENT_ADDRESSING_READ_TYPE, IARG_REG_VALUE, baseReg, IARG_REG_VALUE, indexReg, IARG_UINT32, scale, IARG_UINT32, displacement, IARG_THREAD_ID, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeMemAccessBaseIndexDispl, IARG_INST_PTR, IARG_MEMORYWRITE_EA, IARG_UINT32, BASE_INDEX_DISPLACEMENT_ADDRESSING_WRITE_TYPE, IARG_REG_VALUE, baseReg, IARG_REG_VALUE, indexReg, IARG_UINT32, scale, IARG_UINT32, displacement, IARG_THREAD_ID, IARG_END); } instrumented = TRUE; } else { if (isRead) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeMemAccessBaseDispl, IARG_INST_PTR, IARG_MEMORYREAD_EA, IARG_UINT32, BASE_DISPLACEMENT_ADDRESSING_READ_TYPE, IARG_REG_VALUE, baseReg, IARG_UINT32, displacement, IARG_THREAD_ID, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeMemAccessBaseDispl, IARG_INST_PTR, IARG_MEMORYWRITE_EA, IARG_UINT32, BASE_DISPLACEMENT_ADDRESSING_WRITE_TYPE, IARG_REG_VALUE, baseReg, IARG_UINT32, displacement, IARG_THREAD_ID, IARG_END); } instrumented = TRUE; } } else { if (isRead) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeMemAccessDispl, IARG_INST_PTR, IARG_MEMORYREAD_EA, IARG_UINT32, DISPLACEMENT_ONLY_ADDRESSING_READ_TYPE, IARG_UINT32, displacement, IARG_THREAD_ID, IARG_END); } else { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)AnalyzeMemAccessDispl, IARG_INST_PTR, IARG_MEMORYWRITE_EA, IARG_UINT32, DISPLACEMENT_ONLY_ADDRESSING_WRITE_TYPE, IARG_UINT32, displacement, IARG_THREAD_ID, IARG_END); } instrumented = TRUE; } ASSERTX (instrumented); // must delete this INS - since it's memory address is 16bit, cannot be sure // it accesses valid memory - so we are only testing the IARG_MEMORY(READ/WRITE)_EA // on these instructions INS_Delete(ins); }
VOID Instruction(INS ins, VOID *v) { if (INS_IsMemoryRead(ins) && !instrumentedReadFromIpWithNoOffset) { BOOL readsFromIpWithNoOffset = FALSE; for (UINT32 i = 0; i < INS_OperandCount(ins); i++) { if (!INS_OperandIsMemory(ins, i)) continue; if (INS_OperandMemoryBaseReg(ins, i) == REG_INST_PTR && INS_OperandMemoryDisplacement(ins, i)==0) { readsFromIpWithNoOffset = TRUE; break; } } if (!readsFromIpWithNoOffset) { return; } instrumentedReadFromIpWithNoOffset = TRUE; // only instrument one of these printf ("Instrumenting [ip] read %p %s\n", INS_Address(ins), INS_Disassemble(ins).c_str()); globalIpOfReadRecordedAtInstrumentationTime = INS_Address(ins); globalReadInsSize = INS_Size(ins); fflush (stdout); INS_InsertCall(ins,IPOINT_BEFORE, (AFUNPTR)IpReadBefore, IARG_INST_PTR, IARG_MEMORYREAD_EA, IARG_REG_VALUE, REG_INST_PTR, IARG_END); INS_InsertCall(ins,IPOINT_AFTER, (AFUNPTR)IpReadAfter, IARG_REG_VALUE, REG_INST_PTR, IARG_END); } else if (INS_IsMemoryWrite(ins) && !instrumentedWriteFromIpWithNoOffset) { /* const xed_decoded_inst_t* xedd = INS_XedDec(ins); xed_reg_enum_t breg1 = xed_decoded_inst_get_base_reg(xedd,0); if (breg1== XED_REG_RIP) { readsFromIpWithNoOffset = TRUE; } */ BOOL writesFromIpWithNoOffset = FALSE; for (UINT32 i = 0; i < INS_OperandCount(ins); i++) { if (!INS_OperandIsMemory(ins, i)) continue; if (INS_OperandMemoryBaseReg(ins, i) == REG_INST_PTR && INS_OperandMemoryDisplacement(ins, i)==0) { writesFromIpWithNoOffset = TRUE; break; } } if (!writesFromIpWithNoOffset) { return; } instrumentedReadFromIpWithNoOffset = TRUE; // only instrument one of these printf ("Instrumenting [ip] write %p %s\n", INS_Address(ins), INS_Disassemble(ins).c_str()); globalIpOfWriteRecordedAtInstrumentationTime = INS_Address(ins); globalWriteInsSize = INS_Size(ins); fflush (stdout); INS_InsertCall(ins,IPOINT_BEFORE, (AFUNPTR)IpWriteBefore, IARG_INST_PTR, IARG_MEMORYWRITE_EA, IARG_REG_VALUE, REG_INST_PTR, IARG_END); INS_InsertCall(ins,IPOINT_AFTER, (AFUNPTR)IpWriteAfter, IARG_REG_VALUE, REG_INST_PTR, IARG_END); } }