VOID Trace(TRACE trace, VOID *v) { BOOL rewrite = false; 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)) { // If we see an instruction that needs rewriting, then rewrite all if (SwizzleRefs.find(INS_Address(ins)) != SwizzleRefs.end()) rewrite = true; if (rewrite) { // If we suspect this instruction needs to be swizzled, generate safe, but slow code RewriteIns(ins); } else { // Generate code to check if swizzling is needed, but not do it CheckIns(ins, TRACE_Address(trace)); } } } }
VOID PolymorphicCodeHandlerModule::inspectTrace(TRACE trace){ // set the range of address in which the current trace resides this->trace_head = TRACE_Address(trace); this->trace_tail = trace_head + TRACE_Size(trace); 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)) { // for ech instruction we have to check if it has been overwritten by a previous instruction of the current trace (polimiorfic code detection) INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(checkIfWrittenAddress), IARG_INST_PTR, IARG_CONTEXT, IARG_UINT32, INS_Size(ins), IARG_PTR, this, IARG_END); for (UINT32 op = 0; op<INS_MemoryOperandCount(ins); op++) { if(INS_MemoryOperandIsWritten(ins,op)){ // for each write operation we have to check if the traget address is inside the current trace (attempt to write polimorfic code) INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(polimorficCodeHandler), IARG_INST_PTR, IARG_MEMORYOP_EA, op, IARG_PTR, this, IARG_END); } } } } }
static VOID Trace(TRACE trace, VOID *v) { RTN rtn = TRACE_Rtn(trace); if (!RTN_Valid(rtn) || RTN_Name(rtn) != watch_rtn) { return; } if (TRACE_Address(trace) == RTN_Address(rtn)) { // Pin does not support issuing an RTN_ReplaceSignature from the TRACE instrumentation callback // This will cause Pin to terminate with an error PROTO proto_watch_rtn = PROTO_Allocate(PIN_PARG(void), CALLINGSTD_DEFAULT, "watch_rtn", PIN_PARG(int), PIN_PARG_END()); RTN_ReplaceSignature(rtn, AFUNPTR(WatchRtnReplacement), IARG_PROTOTYPE, proto_watch_rtn, IARG_CONST_CONTEXT, IARG_THREAD_ID, IARG_ORIG_FUNCPTR, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_END); }
// Pin calls this function every time a new trace is encountered VOID InstrumentTrace(TRACE trace, VOID *v) { VOID * traceAddr; VOID * traceCopyAddr; USIZE traceSize; traceAddr = (VOID *)TRACE_Address(trace); #if 0 if (traceAddr < (void*)0xbf000000) return; fprintf(stderr,"Instrumenting trace at %p\n",traceAddr); #endif traceSize = TRACE_Size(trace); traceCopyAddr = malloc(traceSize); if (traceCopyAddr != 0) { memcpy(traceCopyAddr, traceAddr, traceSize); // Insert a call to DoSmcCheck before every trace TRACE_InsertCall(trace, IPOINT_BEFORE, (AFUNPTR)DoSmcCheck, IARG_PTR, traceAddr, IARG_PTR, traceCopyAddr, IARG_UINT32 , traceSize, IARG_CONTEXT, IARG_END); } }
// We have to instrument traces in order to instrument each BBL, the API doesn't have a BBL_AddInstrumentFunction VOID trace_instrumentation(TRACE trace, VOID *v) { // We don't want to instrument the BBL contained in the Windows API if(is_address_in_blacklisted_modules(TRACE_Address(trace))) return; for(BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { // What's going on under the hood // LOG("[INSTRU] BBL Address: " + hexstr(BBL_Address(bbl)) + ", " + hexstr(BBL_NumIns(bbl)) + "\n"); // Insert a call to handle_basic_block before every basic block, passing the number of instructions BBL_InsertCall( bbl, IPOINT_ANYWHERE, (AFUNPTR)handle_basic_block, IARG_FAST_ANALYSIS_CALL, // Use a faster linkage for calls to analysis functions. Add PIN_FAST_ANALYSIS_CALL to the declaration between the return type and the function name. You must also add IARG_FAST_ANALYSIS_CALL to the InsertCall. For example: IARG_UINT32, BBL_NumIns(bbl), IARG_ADDRINT, BBL_Address(bbl), IARG_END ); } }
static VOID Trace(TRACE trace, VOID *v) { RTN rtn = TRACE_Rtn(trace); ADDRINT version = TRACE_Version(trace); // If we are not in watch_rtn, switch back to base version if (!RTN_Valid(rtn) || RTN_Name(rtn) != watch_rtn) { if (version != VERSION_BASE) BBL_SetTargetVersion(TRACE_BblHead(trace), VERSION_BASE); return; } if (TRACE_Address(trace) == RTN_Address(rtn)) { INS ins = BBL_InsHead(TRACE_BblHead(trace)); if (version == VERSION_BASE) { // version_reg is used to select the version, use the first // argument of watch_rtn to set it INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(select_version), IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_RETURN_REGS, version_reg, IARG_END); // IF we are in the base version, decide if we should go to the // other versions // Note that the version instrumentation will occur before any // following instrumentation done on this ins INS_InsertVersionCase(ins, version_reg, 10, VERSION_1, IARG_END); INS_InsertVersionCase(ins, version_reg, 20, VERSION_2, IARG_END); printf ("Instrumentation at %p\n", reinterpret_cast<void *>(INS_Address(ins))); } } INS ins = BBL_InsHead(TRACE_BblHead(trace)); for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { // Instrumentation depends on version // These instrumentations occur after the preceeding version instrumentation // (i.e. the instrumentation inserted by the above INS_InsertVersionCase calls switch(version) { case VERSION_BASE: INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(Emit), IARG_PTR, "version base", IARG_END); break; case VERSION_1: INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(Emit), IARG_PTR, "version 1", IARG_END); break; case VERSION_2: INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(Emit), IARG_PTR, "version 2", IARG_END); break; default: assert(0); break; } } }
VOID Trace(TRACE trace, VOID *v) { // If current trace is the actual memcpy address insert memcpy instrumentation func if (TRACE_Address(trace) == actual_memcpy_add) { TRACE_InsertCall(trace, IPOINT_BEFORE, (AFUNPTR)MemcpyBefore, IARG_ADDRINT, "memcpy (ifunc)", IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_FUNCARG_ENTRYPOINT_VALUE, 1, IARG_FUNCARG_ENTRYPOINT_VALUE, 2, IARG_END); } }
// Inspect the sequence, but do not instrument VOID Trace(TRACE trace, VOID *v) { fprintf(out, "Trace address %p\n",(CHAR*)(TRACE_Address(trace))); 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)) { fprintf(out, " %p\n",(CHAR*)(INS_Address(ins))); } } fprintf(out, "\n"); }
static VOID Trace(TRACE trace, VOID *v) { RTN rtn = TRACE_Rtn(trace); if (!RTN_Valid(rtn) || RTN_Name(rtn) != watch_rtn) { return; } if (TRACE_Address(trace) == RTN_Address(rtn)) { BBL_InsertCall(TRACE_BblHead(trace), IPOINT_BEFORE, AFUNPTR(Emit), IARG_PTR, "Trace_BBL instrumentation", IARG_CALL_ORDER, CALL_ORDER_FIRST+2, IARG_END); printf("Trace Instrumenting %s\n", watch_rtn); } }
VOID Trace(TRACE trace, VOID *v){ ADDRINT addr; addr = TRACE_Address(trace); if (!(addr >= process_start & addr < process_end)) return; 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)){ INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)InstrumentFunction, IARG_PTR, 0, //new string(INS_Disassemble(ins)), IARG_INST_PTR, IARG_THREAD_ID, IARG_CONTEXT, IARG_END); } } }
static VOID Trace(TRACE trace, VOID *v) { RTN rtn = TRACE_Rtn(trace); if (!RTN_Valid(rtn) || RTN_Name(rtn) != watch_rtn) { return; } if (TRACE_Address(trace) == RTN_Address(rtn)) { // Pin does not support issuing an RTN_Replace from the TRACE instrumentation callback // This will cause Pin to terminate with an error RTN_Replace(rtn, AFUNPTR(WatchRtnReplacement)); } }
VOID instrumentTrace(TRACE trace, VOID *v) { IMG img = IMG_FindByAddress(TRACE_Address(trace)); if (!IMG_Valid(img) || !IMG_IsMainExecutable(img)) return; const char* imageName = IMG_Name(img).c_str(); 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)) { processMemoryWriteInstruction(ins, imageName); processMemoryReadInstruction(ins, imageName); } } }
static VOID Trace(TRACE trace, VOID *v) { RTN rtn = TRACE_Rtn(trace); if (!RTN_Valid(rtn) || RTN_Name(rtn) != watch_rtn) { return; } if (TRACE_Address(trace) == RTN_Address(rtn)) { // Pin does not support issuing an RTN_InsertCall from the TRACE instrumentation callback // This will cause Pin to terminate with an error RTN_Open(rtn); RTN_InsertCall(rtn, IPOINT_BEFORE, AFUNPTR(Emit), IARG_PTR, "Ins instrumentation1", IARG_END); RTN_Close(rtn); } }
static VOID Trace(TRACE trace, VOID *v) { RTN rtn = TRACE_Rtn(trace); if (!RTN_Valid(rtn) || RTN_Name(rtn) != watch_rtn) { return; } if (TRACE_Address(trace) == RTN_Address(rtn)) { INS ins = BBL_InsHead(TRACE_BblHead(trace)); INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(Emit), IARG_PTR, "Trace instrumentation3", IARG_END); BBL_InsertCall(TRACE_BblHead(trace), IPOINT_BEFORE, AFUNPTR(Emit), IARG_PTR, "Trace instrumentation2", IARG_END); TRACE_InsertCall(trace, IPOINT_BEFORE, AFUNPTR(Emit), IARG_PTR, "Trace instrumentation1", IARG_END); printf("Trace Instrumenting %s\n", watch_rtn); } }
int trace_address (lua_State *L) { TRACE* v1 = check_trace(L,1); ADDRINT r = TRACE_Address(*v1); lua_pushnumber(L, r); return 1; }
// ------------------------------------------------------------- // Trace instrumentation function // ------------------------------------------------------------- void I_Trace(TRACE trace, void *v) { BOOL isPLT = IsPLT(TRACE_Rtn(trace)); #if DEBUG_INS printf("-- Instrumenting trace %X of function %s\n", TRACE_Address(trace), RTN_Valid(TRACE_Rtn(trace)) ? RTN_Name(TRACE_Rtn(trace)).c_str() : "<unknown_routine>"); #endif // scan BBLs within the current trace for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { // instrument memory reads and writes for(INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) Instruction(ins); INS tail = BBL_InsTail(bbl); // skip system calls if ( INS_IsSyscall(tail) ) continue; // instrument .plt stub calls if ( isPLT ) { #if DEBUG_INS printf(" > .plt stub call\n"); #endif if (gSetup.callingSite) { if (gSetup.memBuf) INS_InsertCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessIndirectCallCSBuf, IARG_FAST_ANALYSIS_CALL, IARG_INST_PTR, IARG_BRANCH_TARGET_ADDR, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_CONTEXT, IARG_END); else INS_InsertCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessIndirectCallCS, IARG_FAST_ANALYSIS_CALL, IARG_INST_PTR, IARG_BRANCH_TARGET_ADDR, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_END); } else { if (gSetup.memBuf) INS_InsertCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessIndirectCallBuf, IARG_FAST_ANALYSIS_CALL, IARG_BRANCH_TARGET_ADDR, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_CONTEXT, IARG_END); else INS_InsertCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessIndirectCall, IARG_FAST_ANALYSIS_CALL, IARG_BRANCH_TARGET_ADDR, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_END); } continue; } // instrument all calls and returns if ( INS_IsCall(tail) ) { // direct call if( INS_IsDirectBranchOrCall(tail) ) { // get target address ADDRINT target = Target2FunAddr(INS_DirectBranchOrCallTargetAddress(tail)); #if DEBUG_INS printf(" > Direct call to %s\n", Target2RtnName(target).c_str()); #endif // instrument direct call: target address determined here if (gSetup.callingSite) { if (gSetup.memBuf) INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessDirectCallCSBuf, IARG_FAST_ANALYSIS_CALL, IARG_INST_PTR, IARG_ADDRINT, target, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_CONTEXT, IARG_END); else INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessDirectCallCS, IARG_FAST_ANALYSIS_CALL, IARG_INST_PTR, IARG_ADDRINT, target, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_END); } else { if (gSetup.memBuf) INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessDirectCallBuf, IARG_FAST_ANALYSIS_CALL, IARG_ADDRINT, target, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_CONTEXT, IARG_END); else INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessDirectCall, IARG_FAST_ANALYSIS_CALL, IARG_ADDRINT, target, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_END); } } // indirect call: target address determined at call time else { #if DEBUG_INS printf(" > Indirect call\n"); #endif // instrument indirect call if (gSetup.callingSite) { if (gSetup.memBuf) INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessIndirectCallCSBuf, IARG_FAST_ANALYSIS_CALL, IARG_INST_PTR, IARG_BRANCH_TARGET_ADDR, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_CONTEXT, IARG_END); else INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessIndirectCallCS, IARG_FAST_ANALYSIS_CALL, IARG_INST_PTR, IARG_BRANCH_TARGET_ADDR, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_END); } else { if (gSetup.memBuf) INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessIndirectCallBuf, IARG_FAST_ANALYSIS_CALL, IARG_BRANCH_TARGET_ADDR, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_CONTEXT, IARG_END); else INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessIndirectCall, IARG_FAST_ANALYSIS_CALL, IARG_BRANCH_TARGET_ADDR, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_END); } } continue; } if ( INS_IsRet(tail) ) { #if DEBUG_INS printf(" > return\n"); #endif if (gSetup.memBuf) INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessReturnBuf, IARG_FAST_ANALYSIS_CALL, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_CONTEXT, IARG_END); else INS_InsertPredicatedCall(tail, IPOINT_BEFORE, (AFUNPTR)A_ProcessReturn, IARG_FAST_ANALYSIS_CALL, IARG_REG_VALUE, REG_STACK_PTR, IARG_THREAD_ID, IARG_END); } } }
VOID Trace(TRACE trace, VOID *v){ char sAddr[16]; snprintf(sAddr,16,"%llx",TRACE_Address(trace)); *out << "addr: " << sAddr <<endl; }