INT32 RecordRegisters(BBL bbl, UINT16 * stats, UINT32 max_stats) { UINT32 count = 0; for (INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) { if (count >= max_stats) { cerr << "Too many stats in this block" << endl; exit(1); } bool rmem = INS_IsMemoryRead(ins) || INS_HasMemoryRead2(ins); bool wmem = INS_IsMemoryWrite(ins); bool rw_mem = rmem & wmem; if (rw_mem) stats[count++] = PATTERN_MEM_RW; else if (rmem) stats[count++] = PATTERN_MEM_R; else if (wmem) stats[count++] = PATTERN_MEM_W; else if (INS_SegmentRegPrefix(ins) != REG_INVALID()) stats[count++] = PATTERN_NO_MEM_LIES; else stats[count++] = PATTERN_NO_MEM; } stats[count++] = 0; return count; }
/* 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(); }
REG INS_get_mem_indexreg(INS ins) { for (unsigned int i = 0; i < INS_OperandCount(ins); i++) { if (INS_OperandIsMemory(ins, i) && INS_OperandRead(ins, i)) { return REG_FullRegName(INS_OperandMemoryIndexReg(ins, i)); } } return REG_INVALID(); }
// returns the full name of the first register operand read REG INS_get_read_reg(INS ins) { for (unsigned int i = 0; i < INS_OperandCount(ins); i++) { if (INS_OperandIsReg(ins, i) && INS_OperandRead(ins, i)) { return REG_FullRegName(INS_OperandReg(ins, i)); } } return REG_INVALID(); }
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; } }
/** * This function is called **/ void traceInst(INS ins, VOID*) { ADDRINT address = INS_Address(ins); std::string mod_name = getModule( address ); RegList regs; for ( UINT32 i = 0; i < INS_OperandCount(ins); i++ ) { if ( INS_OperandIsReg(ins, i) ) { REG x = INS_OperandReg(ins, i); if ( x != REG_INVALID() ) regs.push_back( x ); } } if (isUnknownAddress(address)) { // The address is an address that does not belong to any loaded module. // This is potential shellcode. For these instructions a callback // function is inserted that dumps information to the trace file when // the instruction is actually executed. INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(dump_shellcode), IARG_PTR, new std::string(dumpInstruction(ins)), IARG_PTR, ®s, IARG_CONTEXT, IARG_END ); } else { if ( !modlist.empty() && (modlist.find(mod_name) == modlist.end()) ) // not concerned return; // The address is a legit address, meaning it is probably not part of // any shellcode. In this case we just log the instruction to dump it // later to show when control flow was transfered from legit code to // shellcode. legitInstructions.push_back(dumpInstruction(ins)); if (legitInstructions.size() > KnobMaxLegitInsLogSize.Value()) { // Log only up to KnobMaxLegitInsLogSize.Value() instructions or the whole // program before the shellcode will be dumped. legitInstructions.pop_front(); } } }
VOID Instruction(INS ins, VOID *v) { REG basereg = INS_dec(ins)->basereg; if (basereg == REG_INVALID()) return; // Not allowed to change esp if (basereg == REG_ESP) return; INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)SwizzleAddress, IARG_REG_VALUE, basereg, IARG_RETURN_REGS, basereg, IARG_END); }
int main(int argc, char **argv) { const int nScratch = REG_INST_TOOL_LAST-REG_INST_TOOL_FIRST+1; int seen[nScratch]; bool failed = false; PIN_Init(argc, argv); for (int i=0; i<nScratch; i++) seen[i] = 0; // Claim all the registers we expect to be able to claim for (int i=0; i<nScratch; i++) { REG scratch = PIN_ClaimToolRegister(); if (scratch < REG_INST_TOOL_FIRST || scratch > REG_INST_TOOL_LAST) { printf ("Failed: got a non-scratch register (%d)\n", int(scratch)); failed = true; } seen[scratch-REG_INST_TOOL_FIRST]++; } // Check that we fail when we try to allocate an extra one. if (PIN_ClaimToolRegister() != REG_INVALID()) { printf ("Failed: got register when we shouldn't have\n"); failed = true; } // Check that we got each register once for (int i=0; i<nScratch; i++) { if (seen[i] != 1) { printf ("Failed: saw REG_INST_G%d %d times\n", i, seen[i]); failed = true; } } if (!failed) printf ("Passed\n"); // No need to run the code... exit(failed ? 1 : 0); }
VOID CountsUpdate(INS ins) { if (INS_FullRegRContain(ins, REG_EAX)) fullRegRContainCount++; if (INS_IsInterrupt(ins)) interruptCount++; if (INS_IsRDTSC(ins)) rdtscCount++; if (INS_IsSysret(ins)) sysretCount++; if (INS_IsXchg(ins)) xchgCount++; if (INS_IsDirectFarJump(ins)) { directFarJumpCount++; UINT32 displacement; UINT16 segment; INS_GetFarPointer(ins, segment, displacement); TEST(segment == 0xabcd && displacement == 0x14, "INS_GetFarPointer failed"); } if (INS_MemoryIndexReg(ins) != REG_INVALID()) memoryIndexRegCount++; }
REG GetScratchReg(UINT32 index) { static std::vector<REG> regs; while (index >= regs.size()) { REG reg = PIN_ClaimToolRegister(); if (reg == REG_INVALID()) { std::cerr << "*** Ran out of tool registers" << std::endl; PIN_ExitProcess(1); /* does not return */ } regs.push_back(reg); } return regs[index]; }
REG param_reg(unsigned int pid) { switch (pid) { case 0: return REG_RAX; case 1: return REG_RDI; case 2: return REG_RSI; case 3: return REG_RDX; case 4: return REG_RCX; case 5: return REG_R8; case 6: return REG_R9; default: return REG_INVALID(); } }
/* * initialize thread contexts * * spill a tool register for the thread * contexts and register a thread start callback * * returns: 0 on success, 1 on error */ static inline int thread_ctx_init(void) { /* claim a tool register; optimized branch */ if (unlikely( (thread_ctx_ptr = PIN_ClaimToolRegister()) == REG_INVALID())) { /* error message */ LOG(string(__FUNCTION__) + ": register claim failed\n"); /* failed */ return 1; } /* * thread start/stop hooks; * keep track of the threads and allocate/free space for the * per-thread logistics (i.e., syscall context, VCPU, etc) */ PIN_AddThreadStartFunction(thread_alloc, NULL); PIN_AddThreadFiniFunction(thread_free, NULL); /* success */ return 0; }
int main(int argc, char * argv[]) { PIN_Init(argc, argv); PIN_InitSymbols(); RegThreadInfo = PIN_ClaimToolRegister(); if (RegThreadInfo == REG_INVALID()) { std::cout << "Out of tool registers" << std::endl; PIN_ExitProcess(1); } // Get the test type and initialize the corresponding lock variable. // TestType = GetTestType(KnobTest.Value()); switch (TestType) { case TEST_NONE: std::cout << "Must specify a test to run with the '-test' knob" << std::endl; PIN_ExitProcess(1); break; case TEST_INVALID: std::cout << "Invalid test name: " << KnobTest.Value() << std::endl; PIN_ExitProcess(1); break; case TEST_LOCK_INTEGRITY: case TEST_LOCK_STRESS: PIN_InitLock(&Lock); break; case TEST_MUTEX_INTEGRITY: case TEST_MUTEX_STRESS: case TEST_MUTEX_TRYSTRESS: PIN_MutexInit(&Mutex); break; case TEST_WRITER_INTEGRITY: case TEST_WRITER_STRESS: case TEST_WRITER_TRYSTRESS: case TEST_READER_STRESS: case TEST_READER_TRYSTRESS: case TEST_RW_INTEGRITY: case TEST_RW_STRESS: case TEST_RW_TRYSTRESS: PIN_RWMutexInit(&RWMutex); break; case TEST_SEMAPHORE: PIN_SemaphoreInit(&Sem1); PIN_SemaphoreInit(&Sem2); PIN_SemaphoreSet(&Sem1); PIN_MutexInit(&Mutex); break; case TEST_TRYLOCKS: PIN_MutexInit(&Mutex); PIN_RWMutexInit(&RWMutex); PIN_SemaphoreInit(&Sem1); break; default: ASSERTX(0); } PIN_AddThreadStartFunction(OnThreadStart, 0); PIN_AddThreadFiniFunction(OnThreadFini, 0); RTN_AddInstrumentFunction(InstrumentRtn, 0); PIN_AddFiniFunction(OnExit, 0); PIN_StartProgram(); return 0; }
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); }
// This function represents the case of a register copied to memory void RegTaintMem(ADDRINT reg_r, UINT32 mem_scale, ADDRINT reg_base, ADDRINT reg_index, ADDRINT mem_w, UINT32 op,ADDRINT inst_addr) { if (TaintedRegs[reg_r]) { bbl_taintedmem = 1; TDS *tds_temp = new TDS; tds_temp->offset = TaintedRegs[reg_r]->offset; tds_temp->var_length = TaintedRegs[reg_r]->var_length; switch(mem_scale) { case 1: tds_temp->var_type = type_BYTE; break; case 2: tds_temp->var_type = type_WORD; break; case 4: tds_temp->var_type = type_DWORD; break; default: tds_temp->var_type = type_unknown; break; } tds_temp->memaddr = mem_w; tds_temp->opcode = op; tds_temp->source = TaintedRegs[reg_r]; tds_temp->pointer = TaintedRegs[reg_r]->pointer; TaintedAddrs[mem_w] = tds_temp; if(reg_base!=REG_INVALID()) { pointer[reg_base][reg_index].pointer=1; pointer[reg_base][reg_index].pointaddr=mem_w; pointer[reg_base][reg_index].var_type = tds_temp->var_type; } out << " reg point this tainted mem: "<<reg_base<<" && "<<reg_index<<" type: "<<tds_temp->var_type<<endl; out << endl; out << "register to memory " << inst_addr <<endl; if ( op >= XED_ICLASS_MOV && op <= XED_ICLASS_MOVZX) { out << "MOV " <<" scale: "<<mem_scale<<endl; if( mem_w == memRetStack ) { out <<"detect overwriting of function's retaddr at stack!"<<endl; out <<"retaddress in stack at: "<<mem_w<<endl; } } out << "T " << mem_w << " source " << TaintedRegs[reg_r]->memaddr<<endl; // for (TDS * t=TaintedAddrs[mem_w];t;t=t->source) //out << "trace " << t->memaddr << endl; } else //reg not tainted --> mem not tainted { if (TaintedAddrs.count(mem_w)) // if mem is already not tainted nothing to do { TaintedAddrs.erase(mem_w); out << "U by clean memory addr " << mem_w << endl; } } }
// this function represents the case of a memory copied to register void MemTaintReg(ADDRINT mem_r, UINT32 mem_scale, ADDRINT reg_base, ADDRINT reg_index, ADDRINT reg_w, UINT32 op, ADDRINT inst_addr)//ADDRINT insad) { // out<<"reg_w:"<<reg_w<<endl; if (TaintedAddrs.count(mem_r)) //count is either 0 or 1 for set { TDS *tds_temp = new TDS; tds_temp->offset = TaintedAddrs[mem_r]->offset; tds_temp->var_length = TaintedAddrs[mem_r]->var_length; tds_temp->memaddr = reg_w; tds_temp->opcode = op; tds_temp->source = TaintedAddrs[mem_r]; tds_temp->pointer = TaintedAddrs[mem_r]->pointer; switch(mem_scale) { case 1: tds_temp->var_type = type_BYTE; break; case 2: tds_temp->var_type = type_WORD; break; case 4: tds_temp->var_type = type_DWORD; break; default: tds_temp->var_type = type_unknown; break; } TaintedRegs[reg_w] = tds_temp; if(reg_index!=REG_INVALID()) { if(TaintedRegs[reg_index]) { out<<endl<<" tainted reg point this tainted mem: "<<reg_index<<" && "<<reg_base<<" type: "<<tds_temp->var_type<<endl; TaintedRegs[reg_index]->pointer=1; } else if(TaintedRegs[reg_base]) { out<<endl<<" tainted reg point this tainted mem: "<<reg_index<<" && "<<reg_base<<" type: "<<tds_temp->var_type<<endl; TaintedRegs[reg_base]->pointer=1; } else out<<endl<<" untainted reg point this tainted mem: "<<reg_index<<" && "<<reg_base<<" type: "<<tds_temp->var_type<<endl; } else if(reg_base!=REG_INVALID()) { if(TaintedRegs[reg_base]) { out<<endl<<"a tainted reg point this tainted mem: "<<reg_base<<" type: "<<tds_temp->var_type<<endl; TaintedRegs[reg_base]->pointer=1; } else out<<endl<<"a untainted reg point this tainted mem: "<<reg_base<<" type: "<<tds_temp->var_type<<endl; } pointer[reg_base][reg_index].pointer=1; pointer[reg_base][reg_index].pointaddr=mem_r; pointer[reg_base][reg_index].var_type=tds_temp->var_type; out << endl; out << "memory to register " <<inst_addr<<endl; if ( op >= XED_ICLASS_MOV && op <= XED_ICLASS_MOVZX) out << "MOV " <<" scale: "<<mem_scale<<endl; out << "T " << reg_w << " source " << TaintedAddrs[mem_r]->memaddr <<endl; } else if(TaintedRegs[reg_index])//first taint index reg { out << endl; out <<"tainted index-register point to this untainted mem "<<inst_addr<<endl; //RegTaintMem(reg_index,mem_scale,reg_base,reg_index,mem_r,0,inst_addr); TaintedRegPointMem(reg_base,reg_index,mem_r,mem_scale,1); TaintedRegs[reg_index]->pointer=1;//after taint mem,set pointer of reg,because can't propagate this attribute to mem TDS *tds_temp = new TDS; tds_temp->offset = TaintedAddrs[mem_r]->offset; tds_temp->var_length = TaintedAddrs[mem_r]->var_length; tds_temp->memaddr = reg_w; tds_temp->opcode = op; tds_temp->source = TaintedRegs[mem_r]; tds_temp->pointer = TaintedRegs[mem_r]->pointer; switch(mem_scale) { case 1: tds_temp->var_type = type_BYTE; break; case 2: tds_temp->var_type = type_WORD; break; case 4: tds_temp->var_type = type_DWORD; break; default: tds_temp->var_type = type_unknown; break; } TaintedRegs[reg_w] = tds_temp; if ( op >= XED_ICLASS_MOV && op <= XED_ICLASS_MOVZX) out << "MOV " <<" scale: "<<mem_scale<<endl; out << "T " << reg_w << " source " << TaintedRegs[mem_r]->memaddr<<endl; TaintedAddrs.erase(mem_r);//clean [base+index] after move } else if(TaintedRegs[reg_base]&®_index!=REG_INVALID())//second taint base reg if index reg exist { out << endl; out <<"tainted base-register point to this untainted mem " <<inst_addr<<endl; //RegTaintMem(reg_base,mem_scale,reg_base,reg_index,mem_r,0,inst_addr); TaintedRegPointMem(reg_base,reg_index,mem_r,mem_scale,0);//reg_base is the index reg!!! TaintedRegs[reg_base]->pointer=1;//after taint mem,set pointer of reg,because can't propagate this attribute to mem TDS *tds_temp = new TDS; tds_temp->offset = TaintedAddrs[mem_r]->offset; tds_temp->var_length = TaintedAddrs[mem_r]->var_length; tds_temp->memaddr = reg_w; tds_temp->opcode = op; tds_temp->source = TaintedAddrs[mem_r]; tds_temp->pointer = TaintedAddrs[mem_r]->pointer; switch(mem_scale) { case 1: tds_temp->var_type = type_BYTE; break; case 2: tds_temp->var_type = type_WORD; break; case 4: tds_temp->var_type = type_DWORD; break; default: tds_temp->var_type = type_unknown; break; } TaintedRegs[reg_w] = tds_temp; if ( op >= XED_ICLASS_MOV && op <= XED_ICLASS_MOVZX) out << "MOV " <<" scale: "<<mem_scale<<endl; out << "T " << reg_w << " source " << TaintedAddrs[mem_r]->memaddr<<endl; TaintedAddrs.erase(mem_r);//clean [base+index] after move } else { TaintedRegs[reg_w] = NULL; } }
VOID Trace(TRACE trace, VOID *v) { if(TAINT_Analysis_On&&TAINT_Instrumentation_On) { for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { if(bbl_taintedmem) BBL_InsertCall(bbl,IPOINT_BEFORE,(AFUNPTR)bblBegin,IARG_END); for (INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)checkEIP,IARG_INST_PTR,IARG_END); if(INS_IsCall(ins))//detect overflow of stack { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)MemofRetAddr, IARG_MEMORYOP_EA, 0, IARG_END); } if ( INS_Opcode(ins) >= XED_ICLASS_MOV && INS_Opcode(ins) <= XED_ICLASS_MOVZX )//&& INS_Address(ins) == 0x7c80a2f0)//||INS_Address(ins)==0x7c80a2f3))//||( (INS_Opcode(ins) >= XED_ICLASS_POP) && (INS_Opcode(ins) <= XED_ICLASS_POPFQ))||((INS_Opcode(ins) >= XED_ICLASS_PUSH) && (INS_Opcode(ins) <= XED_ICLASS_PUSHFQ))||(INS_Opcode(ins) == XED_ICLASS_LEA)) { if (INS_has_immed(ins)) { if (INS_IsMemoryWrite(ins)) //immed -> mem { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)ImmedCleanMem, IARG_MEMORYOP_EA, 0, IARG_END); } else //immed -> reg { REG insreg1 = INS_get_write_reg(ins); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)ImmedCleanReg, IARG_ADDRINT, (ADDRINT)insreg1, IARG_END); } } else if (INS_IsMemoryRead(ins)) //mem -> reg { //in this case we call MemTaintReg to copy the taint if relevant REG insreg2 = INS_get_write_reg(ins); REG basereg2 = INS_get_mem_basereg(ins); REG indexreg2 = INS_get_mem_indexreg(ins); //ADDRINT insadd = INS_Address(ins); //string insdis = INS_Disassemble(ins); //out << "instruction 2 opcode " << INS_Opcode(ins)<<endl; INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)MemTaintReg, IARG_MEMORYOP_EA, 0, IARG_UINT32,INS_MemoryScale(ins), IARG_ADDRINT, (ADDRINT)basereg2, IARG_ADDRINT, (ADDRINT)indexreg2, IARG_ADDRINT, (ADDRINT)insreg2, IARG_UINT32, INS_Opcode(ins), IARG_INST_PTR, IARG_END); } else if (INS_IsMemoryWrite(ins)) //reg -> mem { //in this case we call RegTaintMem to copy the taint if relevant REG insreg3 = INS_get_read_reg(ins); REG basereg3 = INS_get_memwr_basereg(ins); REG indexreg3 = INS_get_memwr_indexreg(ins); //ADDRINT insadd = INS_Address(ins); //IARG_INST_PTR INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)RegTaintMem, IARG_ADDRINT,(ADDRINT)insreg3, IARG_UINT32,INS_MemoryScale(ins), IARG_ADDRINT, (ADDRINT)basereg3, IARG_ADDRINT, (ADDRINT)indexreg3, IARG_MEMORYOP_EA, 0, IARG_UINT32, INS_Opcode(ins), IARG_INST_PTR, IARG_END); } else if (INS_RegR(ins, 0) != REG_INVALID()) //reg -> reg { //in this case we call RegTaintReg REG Rreg = INS_get_read_reg(ins); REG Wreg = INS_get_write_reg(ins); //ADDRINT insadd = INS_Address(ins); INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)RegTaintReg, IARG_ADDRINT, (ADDRINT)Rreg, IARG_ADDRINT, (ADDRINT)Wreg, IARG_UINT32, INS_Opcode(ins), IARG_INST_PTR, IARG_END); } else //should never happen { out << "serious error?!\n" << endl; } } // IF opcode is a MOV /* if(bbl_taintedmem == 1&&INS_IsBranch(ins)) { out << BBL_Address(bbl) <<endl; out << INS_Address(ins)<<endl; out << INS_NextAddress(ins)<<endl; out << INS_DirectBranchOrCallTargetAddress(ins)<<endl; out << " taintBBL: "<<endl; out << INS_Disassemble(ins) <<endl; if(INS_NextAddress(ins)>=BBL_Address(bbl)&&INS_NextAddress(ins)<=INS_Address(ins)) { out << "find bbl loop"<<endl; //bblLoop = 1; } } */ if(bbl_taintedmem ==1 && ins==BBL_InsTail(bbl)) { // out <<"find tainted bbl " <<endl; // out <<"bbl start address: "<< BBL_Address(bbl) <<endl; // out <<"bbl size: "<<BBL_Size(bbl) << endl; // out <<"bbl head: "<< INS_Disassemble(BBL_InsHead(bbl))<<endl; // out <<"bbl tail: "<< INS_Disassemble(ins) <<endl; if(INS_DirectBranchOrCallTargetAddress(ins)>=BBL_Address(bbl)&&INS_DirectBranchOrCallTargetAddress(ins)<=INS_Address(ins)) { out<<endl<<"this tainted bbl is a loop"<<endl; //BBL_InsertCall(bbl,IPOINT_AFTER,(AFUNPTR)loopBblEnd,IARG_END); } } }// For INS } // For BBL }//for enable DTA } // VOID Trace
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); } } }
// CALLBACKS void SEMAPHORE::cCMPXCHG(INS &ins) { // CMPXCHG : d'abord une comparaison destination (R ou M) avec // puis 1 MOV selon le resultat de la comparaison // Opérande 0 : ModRM:r/m (si reg : regDest) // Opérande 1 : reg (dénommé regSrc) // CMPXCHG compare opérande 0 avec AL/AX/EAX/RAX // Si égal, ZF = 1 (comme une vraie comparaison) et opérande 1 -> opérande 0 // Si différent : ZF = 0 (comme une vraie comparaison) et opérande 0 -> AL/AX/EAX/RAX // Dans les arguments des callbacks, il vaut ajouter la valeur de AL/AX/EAX/RAX // Et celle du registre dest (cas RR) pour faire la comparaison. // opérande 1 : regSrc REG regSrc = INS_OperandReg(ins, 1); UINT32 regSrcSize = getRegSize(regSrc); if (!regSrcSize) return; // registre non suivi // registre de comparasion avec la destination REG cmpReg = REG_INVALID(); // selon la taille, AL/AX/EAX/RAX // pointeur vers fonction à appeler void (*callback)() = nullptr; if (INS_IsMemoryRead(ins)) // CMPXCHG_RM (source 0 = mémoire) { switch (regSrcSize) { case 1: callback = (AFUNPTR) sCMPXCHG_RM<8>; cmpReg = REG_AL; break; case 2: callback = (AFUNPTR) sCMPXCHG_RM<16>; cmpReg = REG_AX; break; case 4: callback = (AFUNPTR) sCMPXCHG_RM<32>; cmpReg = REG_EAX; break; #if TARGET_IA32E case 8: callback = (AFUNPTR) sCMPXCHG_RM<64>; cmpReg = REG_RAX; break; #endif } INS_InsertCall (ins, IPOINT_BEFORE, callback, IARG_THREAD_ID, IARG_UINT32, regSrc, // pas besoin de la valeur du registre, le déplacement se fera octet par octet IARG_MEMORYREAD_EA, IARG_UINT32, cmpReg, IARG_REG_VALUE, cmpReg, IARG_INST_PTR, IARG_END); } else // CMPXCHG_RR (source 0 = registre) { REG regDest = INS_OperandReg(ins, 0); // registre de destination (comparé à AL/AX/EAX/RAX) switch (getRegSize(regDest)) { case 0: return; // non suivi en instrumentation case 1: callback = (AFUNPTR) sCMPXCHG_RR<8>; cmpReg = REG_AL; break; case 2: callback = (AFUNPTR) sCMPXCHG_RR<16>; cmpReg = REG_AX; break; case 4: callback = (AFUNPTR) sCMPXCHG_RR<32>; cmpReg = REG_EAX; break; #if TARGET_IA32E case 8: callback = (AFUNPTR) sCMPXCHG_RR<64>; cmpReg = REG_RAX; break; #endif } INS_InsertCall (ins, IPOINT_BEFORE, callback, IARG_THREAD_ID, IARG_UINT32, regSrc, IARG_UINT32, regDest, IARG_REG_VALUE, regDest,// valeur indispendable pour comparaison à RAX IARG_UINT32, cmpReg, IARG_REG_VALUE, cmpReg, IARG_INST_PTR, IARG_END); } } // cCMPXCHG
/* Unwind to previous to frame. Returns 0 if successful, negative * number in case of an error. */ int unwind(struct unwind_frame_info *frame, int is_ehframe) { #define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs]) const u32 *fde = NULL, *cie = NULL; const u8 *ptr = NULL, *end = NULL; unsigned long startLoc = 0, endLoc = 0, cfa; unsigned i; signed ptrType = -1; uleb128_t retAddrReg = 0; // struct unwind_table *table; void *unwind_table; struct local_unwind_table *table; struct unwind_state state; u64 reg_ptr = 0; if (UNW_PC(frame) == 0) return -EINVAL; if ((table = find_table(UNW_PC(frame)))) { // unsigned long tableSize = unwind_table_size; unsigned long tableSize = table->size; unwind_table = table->address; for (fde = unwind_table; tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde; tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) { if (!*fde || (*fde & (sizeof(*fde) - 1))) break; if (is_ehframe && !fde[1]) continue; /* this is a CIE */ else if (fde[1] == 0xffffffff) continue; /* this is a CIE */ if ((fde[1] & (sizeof(*fde) - 1)) || fde[1] > (unsigned long)(fde + 1) - (unsigned long)unwind_table) continue; /* this is not a valid FDE */ if (is_ehframe) cie = fde + 1 - fde[1] / sizeof(*fde); else cie = unwind_table + fde[1]; if (*cie <= sizeof(*cie) + 4 || *cie >= fde[1] - sizeof(*fde) || (*cie & (sizeof(*cie) - 1)) || (cie[1] != 0xffffffff && cie[1]) || (ptrType = fde_pointer_type(cie)) < 0) { cie = NULL; /* this is not a (valid) CIE */ continue; } ptr = (const u8 *)(fde + 2); startLoc = read_pointer(&ptr, (const u8 *)(fde + 1) + *fde, ptrType); endLoc = startLoc + read_pointer(&ptr, (const u8 *)(fde + 1) + *fde, ptrType & DW_EH_PE_indirect ? ptrType : ptrType & (DW_EH_PE_FORM|DW_EH_PE_signed)); if (UNW_PC(frame) >= startLoc && UNW_PC(frame) < endLoc) break; cie = NULL; } } if (cie != NULL) { memset(&state, 0, sizeof(state)); state.cieEnd = ptr; /* keep here temporarily */ ptr = (const u8 *)(cie + 2); end = (const u8 *)(cie + 1) + *cie; if ((state.version = *ptr) != 1) cie = NULL; /* unsupported version */ else if (*++ptr) { /* check if augmentation size is first (and thus present) */ if (*ptr == 'z') { /* check for ignorable (or already handled) * nul-terminated augmentation string */ while (++ptr < end && *ptr) if (strchr("LPR", *ptr) == NULL) break; } if (ptr >= end || *ptr) cie = NULL; } ++ptr; } if (cie != NULL) { /* get code aligment factor */ state.codeAlign = get_uleb128(&ptr, end); /* get data aligment factor */ state.dataAlign = get_sleb128(&ptr, end); if (state.codeAlign == 0 || state.dataAlign == 0 || ptr >= end) cie = NULL; else { retAddrReg = state.version <= 1 ? *ptr++ : get_uleb128(&ptr, end); /* skip augmentation */ if (((const char *)(cie + 2))[1] == 'z') ptr += get_uleb128(&ptr, end); if (ptr > end || retAddrReg >= ARRAY_SIZE(reg_info) || REG_INVALID(retAddrReg) || reg_info[retAddrReg].width != sizeof(unsigned long)) cie = NULL; } } if (cie != NULL) { state.cieStart = ptr; ptr = state.cieEnd; state.cieEnd = end; end = (const u8 *)(fde + 1) + *fde; /* skip augmentation */ if (((const char *)(cie + 2))[1] == 'z') { uleb128_t augSize = get_uleb128(&ptr, end); if ((ptr += augSize) > end) fde = NULL; } } if (cie == NULL || fde == NULL) return -ENXIO; state.org = startLoc; memcpy(&state.cfa, &badCFA, sizeof(state.cfa)); /* process instructions */ if (!processCFI(ptr, end, UNW_PC(frame), ptrType, &state) || state.loc > endLoc || state.regs[retAddrReg].where == Nowhere || state.cfa.reg >= ARRAY_SIZE(reg_info) || reg_info[state.cfa.reg].width != sizeof(unsigned long) || state.cfa.offs % sizeof(unsigned long)) { return -EIO; } /* update frame */ cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs; startLoc = min((unsigned long)UNW_SP(frame), cfa); endLoc = max((unsigned long)UNW_SP(frame), cfa); if (STACK_LIMIT(startLoc) != STACK_LIMIT(endLoc)) { startLoc = min(STACK_LIMIT(cfa), cfa); endLoc = max(STACK_LIMIT(cfa), cfa); } #ifndef CONFIG_64BIT # define CASES CASE(8); CASE(16); CASE(32) #else # define CASES CASE(8); CASE(16); CASE(32); CASE(64) #endif for (i = 0; i < ARRAY_SIZE(state.regs); ++i) { if (REG_INVALID(i)) { if (state.regs[i].where == Nowhere) continue; return -EIO; } switch(state.regs[i].where) { default: break; case Register: if (state.regs[i].value >= ARRAY_SIZE(reg_info) || REG_INVALID(state.regs[i].value) || reg_info[i].width > reg_info[state.regs[i].value].width){ return -EIO; } switch(reg_info[state.regs[i].value].width) { #define CASE(n) \ case sizeof(u##n): \ state.regs[i].value = FRAME_REG(state.regs[i].value, \ const u##n); \ break CASES; #undef CASE default: return -EIO; } break; } } for (i = 0; i < ARRAY_SIZE(state.regs); ++i) { if (REG_INVALID(i)) continue; switch(state.regs[i].where) { case Nowhere: if (reg_info[i].width != sizeof(UNW_SP(frame)) || &FRAME_REG(i, __typeof__(UNW_SP(frame))) != &UNW_SP(frame)) continue; UNW_SP(frame) = cfa; break; case Register: switch(reg_info[i].width) { #define CASE(n) case sizeof(u##n): \ FRAME_REG(i, u##n) = state.regs[i].value; \ break CASES; #undef CASE default: return -EIO; } break; case Value: if (reg_info[i].width != sizeof(unsigned long)){ return -EIO;} FRAME_REG(i, unsigned long) = cfa + state.regs[i].value * state.dataAlign; break; case Memory: { unsigned long addr = cfa + state.regs[i].value * state.dataAlign; if ((state.regs[i].value * state.dataAlign) % sizeof(unsigned long) || addr < startLoc || addr + sizeof(unsigned long) < addr || addr + sizeof(unsigned long) > endLoc){ return -EIO;} switch(reg_info[i].width) { #define CASE(n) case sizeof(u##n): \ readmem(addr, KVADDR, ®_ptr,sizeof(u##n), "register", RETURN_ON_ERROR|QUIET); \ FRAME_REG(i, u##n) = (u##n)reg_ptr;\ break CASES; #undef CASE default: return -EIO; } } break; } } return 0; #undef CASES #undef FRAME_REG }
PyObject* Python_REG_INVALID(PyObject* self, PyObject* args) { return Py_BuildValue("L", REG_INVALID()); }
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 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); } }