VOID Ins(INS ins, VOID *v) { static bool before = false, after = false, taken = false; if (!before) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(beforeCall), IARG_END); INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(beforeCheck), IARG_END); Priority(IPOINT_BEFORE, ins); before = true; } if (!after && INS_HasFallThrough(ins)) { INS_InsertCall(ins, IPOINT_AFTER, AFUNPTR(afterCall), IARG_END); INS_InsertCall(ins, IPOINT_AFTER, AFUNPTR(afterCheck), IARG_END); Priority(IPOINT_AFTER, ins); after = true; } if (!taken && INS_IsBranchOrCall(ins)) { INS_InsertCall(ins, IPOINT_TAKEN_BRANCH, AFUNPTR(takenCall), IARG_END); INS_InsertCall(ins, IPOINT_TAKEN_BRANCH, AFUNPTR(takenCheck), IARG_END); Priority(IPOINT_TAKEN_BRANCH, ins); taken = true; } }
VOID Image(IMG img, void *v) { for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)) { for (RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn)) { RTN_Open(rtn); numRtnsFoundInImageCallback++; INS ins = RTN_InsHeadOnly(rtn); if (INS_Invalid() == ins) { // no instruction found - assert that RTN_InsHead(rtn) also doesn't find any INS ASSERTX (INS_Invalid() == RTN_InsHead(rtn)); RTN_Close(rtn); continue; } if (INS_HasFallThrough(ins)) { ADDRINT insAddress = INS_Address(ins); numRtnsInstrumentedFromImageCallback++; RTN_InsertCall( rtn, IPOINT_BEFORE, AFUNPTR(AtRtn), IARG_ADDRINT, RTN_Address(rtn), IARG_END); INS_InsertCall (ins, IPOINT_BEFORE, AFUNPTR(BeforeInsHeadOnly), IARG_ADDRINT, INS_Address(ins), IARG_END); INS_InsertCall (ins, IPOINT_AFTER, AFUNPTR(AfterInsHeadOnly), IARG_ADDRINT, INS_Address(ins), IARG_END); ins = RTN_InsHead(rtn); ASSERTX(INS_Invalid() != ins); ASSERTX(INS_Address(ins)==insAddress); INS_InsertCall (ins, IPOINT_BEFORE, AFUNPTR(BeforeInsHead), IARG_ADDRINT, insAddress, IARG_END); INS_InsertCall (ins, IPOINT_AFTER, AFUNPTR(AfterInsHead), IARG_ADDRINT, insAddress, IARG_END); } RTN_Close(rtn); } } }
VOID Instruction(INS ins, VOID * v) { if(INS_IsMemoryWrite(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(CaptureWriteEa), IARG_THREAD_ID, IARG_MEMORYWRITE_EA, IARG_END); if(INS_HasFallThrough(ins)) { INS_InsertPredicatedCall(ins, IPOINT_AFTER, AFUNPTR(EmitWrite), IARG_THREAD_ID, IARG_MEMORYWRITE_SIZE, IARG_END); } if(INS_IsBranchOrCall(ins)) { INS_InsertPredicatedCall(ins, IPOINT_TAKEN_BRANCH, AFUNPTR(EmitWrite), IARG_THREAD_ID, IARG_MEMORYWRITE_SIZE, IARG_END); } } UINT32 memOperands = INS_MemoryOperandCount(ins); int write_operands = 0; for(UINT32 memOp = 0; memOp < memOperands; memOp++) { if(INS_MemoryOperandIsWritten(ins, memOp)) { write_operands++; } } assert(write_operands <= 1); }
void Ins(INS ins, void * v) { string * st = new string(INS_Disassemble(ins)); // For O/S's (Mac) that don't support PIN_AddSyscallEntryFunction(), // instrument the system call instruction. if (INS_IsSyscall(ins) && INS_HasFallThrough(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(sysargs), IARG_SYSCALL_NUMBER, IARG_SYSARG_VALUE, 0, IARG_SYSARG_VALUE, 1, IARG_SYSARG_VALUE, 2, IARG_SYSARG_VALUE, 3, IARG_SYSARG_VALUE, 4, IARG_SYSARG_VALUE, 5, IARG_END); INS_InsertCall(ins, IPOINT_AFTER, AFUNPTR(sysret), IARG_SYSRET_VALUE, IARG_END); } INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(printIp), IARG_INST_PTR, IARG_PTR, st->c_str(), IARG_END); }
VOID Instruction(INS ins, VOID *v) { // instruments stores using a predicated call, i.e. // the call happens iff the store will be actually executed if (INS_IsMemoryWrite(ins)) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)RecordWriteAddrSize, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_INST_PTR, IARG_END); #if 0 if (INS_HasFallThrough(ins)) { INS_InsertCall( ins, IPOINT_AFTER, (AFUNPTR)RecordMemWrite, IARG_INST_PTR, IARG_END); } if (INS_IsBranchOrCall(ins)) { INS_InsertCall( ins, IPOINT_TAKEN_BRANCH, (AFUNPTR)RecordMemWrite, IARG_INST_PTR, IARG_END); } #endif } }
VOID Trace(TRACE trace, VOID *v) { for (BBL bbl = TRACE_BblTail(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { if (BBL_HasFallThrough(bbl)) { INS ins = BBL_InsTail(bbl); TEST(INS_HasFallThrough(ins), "BBL_HasFallThrough or INS_HasFallThrough failed"); } } }
VOID Instruction(INS ins, VOID *v) { // instruments loads using a predicated call, i.e. // the call happens iff the load will be actually executed if (INS_IsMemoryRead(ins)) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)RecordMem, IARG_INST_PTR, IARG_UINT32, 'R', IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_UINT32, INS_IsPrefetch(ins), IARG_END); } if (INS_HasMemoryRead2(ins)) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)RecordMem, IARG_INST_PTR, IARG_UINT32, 'R', IARG_MEMORYREAD2_EA, IARG_MEMORYREAD_SIZE, IARG_UINT32, INS_IsPrefetch(ins), IARG_END); } // instruments stores using a predicated call, i.e. // the call happens iff the store will be actually executed if (INS_IsMemoryWrite(ins)) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)RecordWriteAddrSize, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_END); if (INS_HasFallThrough(ins)) { INS_InsertCall( ins, IPOINT_AFTER, (AFUNPTR)RecordMemWrite, IARG_INST_PTR, IARG_END); } if (INS_IsBranchOrCall(ins)) { INS_InsertCall( ins, IPOINT_TAKEN_BRANCH, (AFUNPTR)RecordMemWrite, IARG_INST_PTR, IARG_END); } } }
void instrumentBranch(INS ins, void * v) { if (INS_IsBranch(ins) && INS_HasFallThrough(ins)) { INS_InsertCall(ins, IPOINT_TAKEN_BRANCH, (AFUNPTR) handleBranch, IARG_INST_PTR, IARG_BOOL, TRUE, IARG_END); INS_InsertCall(ins, IPOINT_AFTER, (AFUNPTR) handleBranch, IARG_INST_PTR, IARG_BOOL, FALSE, IARG_END); } }
VOID Instruction(INS ins, VOID *v) { // For O/S's (Mac) that don't support PIN_AddSyscallEntryFunction(), // instrument the system call instruction. if (INS_IsSyscall(ins) && INS_HasFallThrough(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)BeforeSyscall, IARG_INST_PTR, IARG_END); INS_InsertCall(ins, IPOINT_AFTER, (AFUNPTR)AfterSyscall, IARG_INST_PTR, IARG_END); } }
VOID Trace(TRACE trace, VOID *v) { static BOOL programStart = TRUE; if (programStart) { programStart = FALSE; next_pc = (void*)INS_Address(BBL_InsHead(TRACE_BblHead(trace))); } for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { // check BBL entry PC INS_InsertCall( BBL_InsHead(bbl), IPOINT_BEFORE, (AFUNPTR)CheckPc, IARG_INST_PTR, IARG_END); INS tail = BBL_InsTail(bbl); if (INS_IsBranchOrCall(tail)) { // record taken branch targets INS_InsertCall( tail, IPOINT_BEFORE, AFUNPTR(RecordPc), IARG_INST_PTR, IARG_BRANCH_TARGET_ADDR, IARG_BRANCH_TAKEN, IARG_END); } if (INS_HasFallThrough(tail)) { // record fall-through INS_InsertCall( tail, IPOINT_AFTER, (AFUNPTR)RecordPc, IARG_INST_PTR, IARG_FALLTHROUGH_ADDR, IARG_BOOL, TRUE, IARG_END); } #if defined(TARGET_IA32) || defined(TARGET_IA32E) if (INS_IsSysenter(tail) || INS_HasRealRep(tail)) { // sysenter on x86 has some funny control flow that we can't correctly verify for now // Genuinely REP prefixed instructions are also odd, they appear to stutter. INS_InsertCall(tail, IPOINT_BEFORE, (AFUNPTR)Skip, IARG_END); } #endif } }
// Pin calls this function every time a new instruction is encountered VOID Instruction(INS ins, VOID *v) { if (INS_IsSyscall(ins) && INS_HasFallThrough(ins)) { // CountDown() is called for every instruction executed INS_InsertIfCall(ins, IPOINT_AFTER, (AFUNPTR)CountDown, IARG_END); // PrintIp() is called only when the last CountDown() returns a non-zero value. INS_InsertThenCall(ins, IPOINT_AFTER, (AFUNPTR)PrintIp, IARG_INST_PTR, IARG_END); // return value only available after INS_InsertCall(ins, IPOINT_AFTER, AFUNPTR(SysAfter), IARG_INST_PTR, IARG_END); } }
VOID Trace(TRACE trace, VOID *v) { INS ins; for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { for (ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) { UINT32 hasFallThrough = INS_HasFallThrough(ins); INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(docount_before), IARG_UINT32, hasFallThrough, IARG_END); if (hasFallThrough) { INS_InsertCall(ins, IPOINT_AFTER, AFUNPTR(docount_after), IARG_END); } } } }
// Is called for every instruction and instruments syscalls VOID Instruction(INS ins, VOID *v) { // For O/S's (Mac) that don't support PIN_AddSyscallEntryFunction(), // instrument the system call instruction. if (INS_IsSyscall(ins) && INS_HasFallThrough(ins)) { // Arguments and syscall number is only available before INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(SysBefore), IARG_INST_PTR, IARG_SYSCALL_NUMBER, IARG_SYSARG_VALUE, 0, IARG_SYSARG_VALUE, 1, IARG_SYSARG_VALUE, 2, IARG_SYSARG_VALUE, 3, IARG_SYSARG_VALUE, 4, IARG_SYSARG_VALUE, 5, IARG_END); // return value only available after INS_InsertCall(ins, IPOINT_AFTER, AFUNPTR(SysAfter), IARG_SYSRET_VALUE, IARG_END); } }
/* * Instruction * Catches Syscall, Return, Store functions and calls appropriate handler */ VOID Instruction(INS ins, VOID *v) { if (INS_IsSyscall(ins) && INS_HasFallThrough(ins)) { // Arguments and syscall number is only available before INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(SysBefore), IARG_INST_PTR, IARG_SYSCALL_NUMBER, IARG_SYSARG_VALUE, 0, IARG_SYSARG_VALUE, 1, IARG_SYSARG_VALUE, 2, IARG_SYSARG_VALUE, 3, IARG_SYSARG_VALUE, 4, IARG_SYSARG_VALUE, 5, IARG_REG_VALUE, REG_STACK_PTR, IARG_END); } else if (INS_Valid(ins)) { if(INS_IsRet(ins)) { INS_InsertCall(ins, IPOINT_TAKEN_BRANCH, AFUNPTR(Return), IARG_REG_VALUE, REG_STACK_PTR, IARG_END); } else if(INS_IsStackWrite(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(StackWrite), IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_END); } else if(INS_IsMemoryWrite(ins) && !(INS_IsBranchOrCall(ins))) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(MemoryWrite), IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_END); } } }
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 PINshield::avoidEvasion(INS ins){ ADDRINT curEip = INS_Address(ins); ProcInfo *pInfo = ProcInfo::getInstance(); Config *config = Config::getInstance(); FilterHandler *filterHandler = FilterHandler::getInstance(); //Filter instructions inside a known library (only graphic dll) if(filterHandler->isFilteredLibraryInstruction(curEip)){ return; } // Pattern matching in order to avoid the dead path of obsidium if(strcmp( (INS_Disassemble(ins).c_str() ),"xor eax, dword ptr [edx+ecx*8+0x4]") == 0){ MYTEST("Obsidium_evasion"); REGSET regsIn; REGSET_AddAll(regsIn); REGSET regsOut; REGSET_AddAll(regsOut); if(INS_HasFallThrough(ins)){ INS_InsertCall(ins,IPOINT_AFTER,(AFUNPTR)KillObsidiumDeadPath, IARG_PARTIAL_CONTEXT, ®sIn, ®sOut,IARG_END); } } // 1 - single instruction detection if(config->ANTIEVASION_MODE_INS_PATCHING && this->evasionPatcher.patchDispatcher(ins, curEip)){ return; } // 2 - memory read // Checking if there is a read at addresses that the application shouldn't be aware of if(config->ANTIEVASION_MODE_SREAD){ for (UINT32 op = 0; op<INS_MemoryOperandCount(ins); op++) { if (INS_MemoryOperandIsRead(ins,op)) { //if first read initialize the FakeReadHandler if(firstRead == 0){ fakeMemH.initFakeMemory(); firstRead=1; } REG scratchReg = GetScratchReg(op); INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(handleRead), IARG_INST_PTR, IARG_MEMORYOP_EA, op, IARG_PTR, &fakeMemH, IARG_RETURN_REGS, scratchReg, IARG_END); INS_RewriteMemoryOperand(ins, op, scratchReg); } } } //3. memory write filter if(config->ANTIEVASION_MODE_SWRITE){ for (UINT32 op = 0; op<INS_MemoryOperandCount(ins); op++) { if(INS_MemoryOperandIsWritten(ins,op) && INS_IsMov(ins)){ REG writeReg = GetScratchReg(op); INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(handleWrite), IARG_INST_PTR, IARG_MEMORYOP_EA, op, IARG_PTR, &fakeWriteH, IARG_RETURN_REGS, writeReg, // this is an output param IARG_END); INS_RewriteMemoryOperand(ins, op, writeReg); } } } }
// This function is called before every instruction is executed VOID instrument_routine(RTN rtn, void *ip) { string name = RTN_Name(rtn); if(name == "ivan") { RTN_Open(rtn); for (INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins)) { int opCount = INS_OperandCount(ins); int opcode = INS_Opcode(ins); if(INS_IsMemoryRead(ins)) { for(int i = 0; i< opCount; i++) { if(INS_MemoryOperandIsRead(ins,i)) { /* INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)RecordMemRead,IARG_PTR,ins, IARG_INST_PTR, IARG_MEMORYOP_EA, i, IARG_END); */ cout<<"opcode:"<<INS_Opcode(ins)<<", mnemonic: "<<INS_Mnemonic(ins)<<endl; if(INS_Opcode(ins)!= XED_ICLASS_RET_NEAR) { REG scratchReg = GetScratchReg(i); INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(GetMemAddress), IARG_MEMORYOP_EA, i, IARG_RETURN_REGS, scratchReg, IARG_END); INS_RewriteMemoryOperand(ins, i, scratchReg); } } } } if(INS_IsMemoryWrite(ins)) { for(int i = 0; i< opCount; i++) { /* if(INS_OperandIsImmediate(ins,i)) { cout<<"immediate "<<INS_OperandImmediate(ins,i)<<endl; } */ if(INS_MemoryOperandIsWritten(ins,i) && INS_HasFallThrough(ins)) { /* INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)RecordMemWrite, IARG_INST_PTR, IARG_MEMORYOP_EA, i, IARG_END); INS_InsertCall( ins, IPOINT_AFTER, (AFUNPTR)RecordMemWrite, IARG_INST_PTR, IARG_MEMORYOP_EA, i, IARG_END); */ if(opcode != XED_ICLASS_PUSH) { REG scratchReg = GetScratchReg(i); INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(GetMemAddress), IARG_MEMORYOP_EA, i, IARG_RETURN_REGS, scratchReg, IARG_END); INS_RewriteMemoryOperand(ins, i, scratchReg); } } } } } RTN_Close(rtn); } }
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 Image(IMG img, VOID *v){ for (UINT16 i = 0; i < n_excluded_lib_names; i++) { if (IMG_Name(img).find(excluded_lib_names[i]) != string::npos){ cout << "Excluded module: " << IMG_Name(img) << endl; return; } } for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)){ for (RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn)) { RTN_Open(rtn); for (INS ins = RTN_InsHead(rtn); INS_Valid(ins); ins = INS_Next(ins)) { // Avoid instrumenting the instrumentation if (!INS_IsOriginal(ins)) continue; if(!SeqProgram) { if ((INS_IsMemoryWrite(ins) || INS_IsMemoryRead(ins)) && INS_HasFallThrough(ins)) { if (INS_IsMemoryWrite(ins) && INS_IsMemoryRead(ins) && INS_HasMemoryRead2(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)ProcessInst, IARG_THREAD_ID, IARG_MEMORYWRITE_EA, IARG_MEMORYREAD_EA, IARG_MEMORYREAD2_EA, IARG_INST_PTR, IARG_END); } else if (INS_IsMemoryWrite(ins) && INS_IsMemoryRead(ins) && !INS_HasMemoryRead2(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)ProcessInst, IARG_THREAD_ID, IARG_MEMORYWRITE_EA, IARG_MEMORYREAD_EA, IARG_ADDRINT, 0, IARG_INST_PTR, IARG_END); } else if (INS_IsMemoryWrite(ins) && !INS_IsMemoryRead(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)ProcessInst, IARG_THREAD_ID, IARG_MEMORYWRITE_EA, IARG_ADDRINT, 0, IARG_ADDRINT, 0, IARG_INST_PTR, IARG_END); } else if (!INS_IsMemoryWrite(ins) && INS_IsMemoryRead(ins) && INS_HasMemoryRead2(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)ProcessInst, IARG_THREAD_ID, IARG_ADDRINT, 0, IARG_MEMORYREAD_EA, IARG_MEMORYREAD2_EA, IARG_INST_PTR, IARG_END); } else if (!INS_IsMemoryWrite(ins) && INS_IsMemoryRead(ins) && !INS_HasMemoryRead2(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)ProcessInst, IARG_THREAD_ID, IARG_ADDRINT, 0, IARG_MEMORYREAD_EA, IARG_ADDRINT,0, IARG_INST_PTR, IARG_END); } else { //not a memory opeartion ASSERTX(0); } } } else { if(INS_IsBranch(ins)){ INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)ProcessBranch, IARG_BRANCH_TAKEN, IARG_INST_PTR, IARG_END); } } } RTN_Close(rtn); } } }
/* Trace instrumentation */ static void TRACE_Instrumentation(TRACE trace, VOID *v) { for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { for (INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) { /* Check if the analysis me be unlocked */ tracer::pintool::checkUnlockAnalysis(INS_Address(ins)); if (!tracer::pintool::analysisTrigger.getState()) /* Analysis locked */ continue; if (tracer::pintool::instructionBlacklisted(INS_Address(ins)) == true || tracer::pintool::instructionWhitelisted(INS_Address(ins)) == false) /* Insruction blacklisted */ continue; /* Prepare the Triton's instruction */ triton::arch::Instruction* tritonInst = new triton::arch::Instruction(); /* Save memory read1 informations */ if (INS_IsMemoryRead(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)saveMemoryAccess, IARG_PTR, tritonInst, IARG_MEMORYREAD_EA, IARG_MEMORYREAD_SIZE, IARG_END); } /* Save memory read2 informations */ if (INS_HasMemoryRead2(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)saveMemoryAccess, IARG_PTR, tritonInst, IARG_MEMORYREAD2_EA, IARG_MEMORYREAD_SIZE, IARG_END); } /* Callback before */ INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)callbackBefore, IARG_PTR, tritonInst, IARG_INST_PTR, IARG_UINT32, INS_Size(ins), IARG_CONTEXT, IARG_THREAD_ID, IARG_END); /* Callback after */ /* Syscall after context must be catcher with INSERT_POINT.SYSCALL_EXIT */ if (INS_IsSyscall(ins) == false) { IPOINT where = IPOINT_AFTER; if (INS_HasFallThrough(ins) == false) where = IPOINT_TAKEN_BRANCH; INS_InsertCall(ins, where, (AFUNPTR)callbackAfter, IARG_PTR, tritonInst, IARG_CONTEXT, IARG_THREAD_ID, IARG_END); } /* I/O memory monitoring for snapshot */ if (INS_OperandCount(ins) > 1 && INS_MemoryOperandIsWritten(ins, 0)) { INS_InsertCall( ins, IPOINT_BEFORE, (AFUNPTR)callbackSnapshot, IARG_MEMORYOP_EA, 0, IARG_UINT32, INS_MemoryWriteSize(ins), IARG_END); } } } }
// Is called for every instruction and instruments reads and writes VOID Instruction(TRACE trace, VOID *v) { // Instruments memory accesses using a predicated call, i.e. // the instrumentation is called iff the instruction will actually be executed. // // The IA-64 architecture has explicitly predicated instructions. // On the IA-32 and Intel(R) 64 architectures conditional moves and REP // prefixed instructions appear as predicated instructions in Pin. //UINT32 memOperands = INS_MemoryOperandCount(ins); // Iterate over each memory operand of the instruction. for(BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl=BBL_Next(bbl)){ for(INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins=INS_Next(ins)) { // Note that in some architectures a single memory operand can be // both read and written (for instance incl (%eax) on IA-32) // In that case we instrument it once for read and once for write. if (INS_IsMemoryWrite(ins)) { INS_InsertPredicatedCall( ins, IPOINT_BEFORE, (AFUNPTR)RecordWriteAddrSize, IARG_MEMORYWRITE_EA, IARG_MEMORYWRITE_SIZE, IARG_END); if (INS_HasFallThrough(ins)) { INS_InsertCall( ins, IPOINT_AFTER, (AFUNPTR)RecordMemWrite, IARG_INST_PTR, IARG_END); //INS_InsertCall(ins, IPOINT_AFTER, (AFUNPTR)PrintValue, IARG_ADDRINT,&mem_value,IARG_END); /* INS_InsertFillBuffer( ins, IPOINT_AFTER, bufId, IARG_ADDRINT,mem_value,offsetof(struct MEMREF, value), //IARG_REG_VALUE,INS_OperandReg(ins,1),offsetof(struct MEMREF, value), IARG_END); */ } if (INS_IsBranchOrCall(ins)) { INS_InsertCall( ins, IPOINT_TAKEN_BRANCH, (AFUNPTR)RecordMemWrite, IARG_INST_PTR, IARG_END); } } } } }