VOID CallTrace(TRACE trace, INS ins) { if (!KnobTraceCalls) return; // RTN = TRACE_Rtn(trace); // ADDRINT rtn_addr = RTN_Address(rtn); if (INS_IsBranchOrCall(ins) && !INS_IsDirectBranchOrCall(ins)) { // Indirect Call INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmitIndirectCall), IARG_THREAD_ID, IARG_INST_PTR, IARG_BRANCH_TARGET_ADDR, IARG_REG_VALUE, REG_STACK_PTR, IARG_END ); } else if (INS_IsDirectBranchOrCall(ins)) { // Direct call.. ADDRINT target = INS_DirectBranchOrCallTargetAddress(ins); INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmitDirectCall), IARG_THREAD_ID, IARG_INST_PTR, IARG_ADDRINT, target, IARG_REG_VALUE, REG_STACK_PTR, IARG_END ); } else if (INS_IsRet(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmitReturn), IARG_THREAD_ID, IARG_INST_PTR, IARG_FUNCRET_EXITPOINT_VALUE, IARG_REG_VALUE, REG_STACK_PTR, IARG_END ); } }
inline static AFUNPTR execute (const Routine & rtn, const Prototype & prototype, CALLINGSTD_TYPE callstd_type) { return RTN_ReplaceSignature (rtn, AFUNPTR (REPLACEMENT::execute), IARG_PROTOTYPE, (PROTO)prototype, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_FUNCARG_ENTRYPOINT_VALUE, 1, IARG_FUNCARG_ENTRYPOINT_VALUE, 2, IARG_END); }
VOID Image(IMG img, VOID *v) { // hook the functions in the image. If these functions are called then it means // that pin has not lost control. RTN rtn = RTN_FindByName(img, "OutputDebugStringA"); if (RTN_Valid(rtn)) { RTN_Open(rtn); RTN_InsertCall(rtn, IPOINT_BEFORE, AFUNPTR(BeforeOutputDebugString), IARG_END); RTN_Close(rtn); } rtn = RTN_FindByName(img, "OutputDebugStringW"); if (RTN_Valid(rtn)) { RTN_Open(rtn); RTN_InsertCall(rtn, IPOINT_BEFORE, AFUNPTR(BeforeOutputDebugString), IARG_END); RTN_Close(rtn); } }
// 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); } }
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 } }
static void InstrumentRtn(RTN rtn, VOID *) { ADDRINT a = RTN_Address(rtn); IMG img = IMG_FindByAddress(a); if (IMG_Valid(img) && IMG_IsMainExecutable(img)) { RTN_Open(rtn); RTN_InsertCall(rtn, IPOINT_BEFORE, AFUNPTR(FunctionHook), IARG_ADDRINT, a, IARG_END); RTN_Close(rtn); } }
static VOID imageLoad(IMG img, VOID *v) { TraceFile << "in image callback of image: " << IMG_Name(img).c_str() << endl; if ( IMG_IsMainExecutable(img)) { RTN rtn = RTN_FindByName(img, "AfterAttach"); if (RTN_Valid(rtn)) { RTN_ReplaceProbed(rtn, AFUNPTR(afterAttachProbe)); } } }
static void InstrumentIns(INS ins, VOID *) { for (UINT32 memIndex = 0; memIndex < INS_MemoryOperandCount(ins); memIndex++) { REG scratchReg = GetScratchReg(memIndex); INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(GetMemAddress), IARG_MEMORYOP_EA, memIndex, IARG_RETURN_REGS, scratchReg, IARG_END); INS_RewriteMemoryOperand(ins, memIndex, scratchReg); } }
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; } }
// When an image is loaded, check for a MyAlloc function VOID Image(IMG img, VOID *v) { //fprintf(stderr, "Loading %s\n",IMG_name(img)); for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)) { //fprintf(stderr, " sec %s\n", SEC_name(sec).c_str()); for (RTN rtn = SEC_RtnHead(sec); RTN_Valid(rtn); rtn = RTN_Next(rtn)) { //fprintf(stderr, " rtn %s\n", RTN_name(rtn).c_str()); // Swizzle the return value of MyAlloc #if defined(TARGET_MAC) if (RTN_Name(rtn) == "_MyAlloc") #else if (RTN_Name(rtn) == "MyAlloc") #endif { RTN_Open(rtn); fprintf(stderr, "Adding swizzle to %s\n", "MyAlloc"); RTN_InsertCall(rtn, IPOINT_AFTER, AFUNPTR(Swizzle), IARG_REG_VALUE, REG_GAX, IARG_RETURN_REGS, REG_GAX, IARG_END); RTN_Close(rtn); } #if defined(TARGET_MAC) if (RTN_Name(rtn) == "_MyFree") #else if (RTN_Name(rtn) == "MyFree") #endif { RTN_Open(rtn); fprintf(stderr, "Adding unswizzle to %s\n", "MyFree"); RTN_InsertCall(rtn, IPOINT_BEFORE, AFUNPTR(SwizzleArg), IARG_FUNCARG_ENTRYPOINT_REFERENCE, 0, IARG_END); RTN_Close(rtn); } } } }
VOID Trace(TRACE trace, VOID *v) { if ( KnobNoSharedLibs.Value() && IMG_Type(SEC_Img(RTN_Sec(TRACE_Rtn(trace)))) == IMG_TYPE_SHAREDLIB) return; const BOOL accurate_handling_of_predicates = KnobProfilePredicated.Value(); for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { // Summarize the stats for the bbl in a 0 terminated list // This is done at instrumentation time UINT16 * stats = new UINT16[BBL_NumIns(bbl) + 1]; INT32 index = 0; for (INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) { // Count the number of times a predicated instruction is actually executed // this is expensive and hence disabled by default if( INS_IsPredicated(ins) && accurate_handling_of_predicates ) { INS_InsertPredicatedCall(ins, IPOINT_BEFORE, AFUNPTR(docount), IARG_PTR, &(GlobalStatsDynamic.predicated_true[INS_Category(ins)]), IARG_END); } stats[index++] = INS_GetStatsIndex(ins); } stats[index] = 0; // Insert instrumentation to count the number of times the bbl is executed BBLSTATS * bblstats = new BBLSTATS(stats); INS_InsertCall(BBL_InsHead(bbl), IPOINT_BEFORE, AFUNPTR(docount), IARG_PTR, &(bblstats->_counter), IARG_END); // Remember the counter and stats so we can compute a summary at the end statsList.push_back(bblstats); } }
VOID Trace(TRACE trace, VOID *v) { for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) { string traceString = ""; for ( INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) { traceString += "%" + INS_Disassemble(ins) + "\n"; } // we try to keep the overhead small // so we only insert a call where control flow may leave the current trace if (KnobNoCompress) { INS_InsertCall(BBL_InsTail(bbl), IPOINT_BEFORE, AFUNPTR(docount), IARG_PTR, new string(traceString), IARG_END); } else { // Identify traces with an id count_trace++; // Write the actual trace once at instrumentation time string m = "@" + decstr(count_trace) + "\n"; TraceFile.write(m.c_str(), m.size()); TraceFile.write(traceString.c_str(), traceString.size()); // at run time, just print the id string *s = new string(decstr(count_trace) + "\n"); INS_InsertCall(BBL_InsTail(bbl), IPOINT_BEFORE, AFUNPTR(docount), IARG_PTR, s, IARG_END); } } }
static VOID Instruction(INS ins, VOID *v) { IARG_TYPE ea; if (INS_SegmentPrefix(ins)) { if (INS_IsMemoryRead(ins)) ea = IARG_MEMORYREAD_EA; else ea = IARG_MEMORYWRITE_EA; INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(OnSegReference), IARG_UINT32, INS_SegmentRegPrefix(ins), IARG_REG_VALUE, INS_SegmentRegPrefix(ins), IARG_INST_PTR, IARG_THREAD_ID, ea, IARG_END); } REG seg; if (WritesSegment(ins, &seg)) { INS_InsertCall(ins, IPOINT_AFTER, AFUNPTR(OnSegWrite), IARG_UINT32, seg, IARG_REG_VALUE, seg, IARG_INST_PTR, IARG_THREAD_ID, IARG_END); } }
static VOID Rtn(RTN rtn, VOID *v) { if (!RTN_Valid(rtn) || RTN_Name(rtn) != watch_rtn) { return; } printf("Rtn Instrumenting %s\n", watch_rtn, reinterpret_cast<void *>(RTN_Address(rtn))); RTN_Open(rtn); RTN_InsertCall(rtn, IPOINT_BEFORE, AFUNPTR(Emit), IARG_PTR, "RTN instrumentation", IARG_CALL_ORDER, CALL_ORDER_FIRST+1, IARG_END); RTN_Close(rtn); }
VOID Instruction(INS ins, VOID *v) { //if (RTN_Valid(INS_Rtn(ins)) && RTN_Name(INS_Rtn(ins)) == "__SEH_epilog4") { // cerr << "image " << IMG_Name(SEC_Img(RTN_Sec(INS_Rtn(ins)))) << endl; //} if (INS_IsRet(ins)) { INS prev = INS_Prev(ins); //cout<< "CALL TO RET" << endl; INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(Ret), IARG_THREAD_ID, IARG_REG_VALUE, REG_ESP, IARG_BRANCH_TARGET_ADDR, IARG_INST_PTR, IARG_UINT32, (INS_Valid(prev) && INS_Opcode(prev) == XED_CATEGORY_PUSH), IARG_END); } else if (INS_IsCall(ins)) { //cout << "CALL TO CALL" << endl; INS_InsertCall(ins, IPOINT_TAKEN_BRANCH, AFUNPTR(Call), IARG_THREAD_ID, IARG_REG_VALUE, REG_ESP, IARG_BRANCH_TARGET_ADDR, IARG_INST_PTR, IARG_END); } else if (INS_IsMemoryWrite(ins)) { //cout<< "CALL TO MEWRITE" << endl; INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(MemWrite), IARG_THREAD_ID, IARG_MEMORYWRITE_EA, IARG_END); } }
static void InstrumentIns(INS ins, VOID *) { if (IsFirstIns) { IsFirstIns = FALSE; INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(DoBreakpoint), IARG_CONTEXT, // IARG_CONST_CONTEXT has much lower overhead // than IARG_CONTEX for passing the CONTEXT* // to the analysis routine. Note that IARG_CONST_CONTEXT // passes a read-only CONTEXT* to the analysis routine IARG_THREAD_ID, 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)) { 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); } }
/** * 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) { ADDRINT nextIns; if (INS_IsRet(ins)) { INS prev = INS_Prev(ins); INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(Ret), IARG_THREAD_ID, IARG_REG_VALUE, REG_STACK_PTR, IARG_BRANCH_TARGET_ADDR, IARG_INST_PTR, IARG_UINT32, (INS_Valid(prev) && INS_Opcode(prev) == XED_CATEGORY_PUSH), IARG_END); } else if (INS_IsCall(ins)) { nextIns = INS_NextAddress(ins); INS_InsertCall(ins, IPOINT_TAKEN_BRANCH, AFUNPTR(Call), IARG_THREAD_ID, IARG_REG_VALUE, REG_STACK_PTR, IARG_BRANCH_TARGET_ADDR, IARG_INST_PTR, IARG_ADDRINT, nextIns, IARG_END); } else if (INS_IsMemoryWrite(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(MemWrite), IARG_THREAD_ID, IARG_MEMORYWRITE_EA, IARG_INST_PTR, IARG_END); } }
VOID Ins(INS ins, VOID *v) { if (!INS_IsCall(ins)) return; if (foobarAddress != 0 && INS_IsDirectBranchOrCall(ins) && INS_DirectBranchOrCallTargetAddress(ins) == foobarAddress) { TraceFile << "Instrument call to foobar" << endl; INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(FoobarArgs), IARG_G_ARG0_CALLER, IARG_G_ARG1_CALLER, IARG_END); } static BOOL first = true; if (!first) return; first = false; INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(CallArgs), IARG_G_ARG0_CALLER, IARG_END); }
VOID Image(IMG img, void *v) { RTN rtn = RTN_FindByName(img, "Replaced"); if (RTN_Valid(rtn)) { PROTO proto = PROTO_Allocate(PIN_PARG(int), CALLINGSTD_DEFAULT, "Replaced", PIN_PARG_END()); RTN_ReplaceSignature(rtn, AFUNPTR(REPLACE_Replaced), IARG_PROTOTYPE, proto, (KnobUseIargConstContext)?IARG_CONST_CONTEXT:IARG_CONTEXT, IARG_THREAD_ID, IARG_ORIG_FUNCPTR, IARG_END); PROTO_Free(proto); } rtn = RTN_FindByName(img, "Inner"); if (RTN_Valid(rtn)) { RTN_Open(rtn); RTN_InsertCall(rtn, IPOINT_BEFORE, AFUNPTR(AtInner), IARG_REG_VALUE, scratchReg, IARG_END); RTN_Close(rtn); } }
static VOID BasicBlockTrace(TRACE trace, BBL bbl) { if (!KnobTraceBasicBlocks) return; INS ins = BBL_InsHead(bbl); INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmitBasicBlock), IARG_THREAD_ID, IARG_INST_PTR, IARG_END ); }
static void InstrumentIndirects(INS ins, VOID *) { if (INS_IsIndirectBranchOrCall(ins)) { Out << "Instrumenting Indirect branch or call at 0x" << std::hex << INS_Address(ins) << " " << INS_Disassemble(ins) << std::endl; INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(RecordTargetAddrBefore), IARG_BRANCH_TARGET_ADDR, IARG_END); INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(CheckPcBefore), IARG_ADDRINT, INS_Address(ins), IARG_CONTEXT, IARG_CONST_CONTEXT, IARG_INST_PTR, IARG_ADDRINT, GetDisassembly(ins), IARG_END); INS_InsertCall(ins, IPOINT_TAKEN_BRANCH, AFUNPTR(CheckTargetAddrAfter), IARG_BRANCH_TARGET_ADDR, IARG_INST_PTR, IARG_ADDRINT, GetDisassembly(ins), IARG_END); INS_InsertCall(ins, IPOINT_TAKEN_BRANCH, AFUNPTR(CheckPcAtBranchTarget), IARG_BRANCH_TARGET_ADDR, // is also expected CONTEXT PC IARG_ADDRINT, INS_Address(ins), // expected INST_PTR PC IARG_CONTEXT, IARG_CONST_CONTEXT, IARG_INST_PTR, IARG_ADDRINT, GetDisassembly(ins), IARG_END); } }
void convert_load_addr(INS ins, void* v) { if (INS_Opcode(ins) == XED_ICLASS_MOV && INS_IsMemoryRead(ins) && INS_OperandIsReg(ins, 0) && INS_OperandIsMemory(ins, 1)) { // op0 <- *op1 INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(convert), IARG_MEMORYREAD_EA, IARG_END); } }
static VOID OnImage(IMG img, VOID *) { #if defined(TARGET_MAC) RTN rtn = RTN_FindByName(img, "_HandlerIsEstablished"); #else RTN rtn = RTN_FindByName(img, "HandlerIsEstablished"); #endif if (RTN_Valid(rtn)) { RTN_Open(rtn); RTN_InsertCall(rtn, IPOINT_BEFORE, AFUNPTR(Check), IARG_THREAD_ID, IARG_END); RTN_Close(rtn); } }
/* ===================================================================== * Called upon image load to instrument the function GlobalFunction * ===================================================================== */ static void Image(IMG img, VOID *) { if (IMG_IsMainExecutable(img)) { RTN rtn = RTN_FindByName(img, "GlobalFunction"); ASSERT(RTN_Valid(rtn), "Failed to find GlobalFunction() in main application image"); RTN_Open(rtn); INS ins = RTN_InsHeadOnly(rtn); INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(DoBreakpoint), IARG_THREAD_ID, IARG_CONTEXT, IARG_END); RTN_Close(rtn); } }
static VOID OnImage(IMG img, VOID *) { #if defined(TARGET_MAC) RTN rtn = RTN_FindByName(img, "_MakeSegv"); #else RTN rtn = RTN_FindByName(img, "MakeSegv"); #endif if (RTN_Valid(rtn)) { RTN_Open(rtn); RTN_InsertCall(rtn, IPOINT_BEFORE, AFUNPTR(DoSafeCopy), IARG_END); RTN_Close(rtn); } }
static VOID on_module_loading(IMG img, VOID *data) { if (IMG_IsMainExecutable(img)) { RTN routine = RTN_FindByName(img, "foo"); if (!RTN_Valid(routine)) { routine = RTN_FindByName(img, "@foo@28"); } if (RTN_Valid(routine)) { PROTO foo_proto = PROTO_Allocate( PIN_PARG(int), CALL_TYPE, "foo", PIN_PARG(int), PIN_PARG(int), PIN_PARG(int), PIN_PARG(int), PIN_PARG(int), PIN_PARG(int), PIN_PARG(int), PIN_PARG_END() ); RTN_InsertCallProbed(routine, IPOINT_BEFORE, AFUNPTR( foo_before ), IARG_PROTOTYPE, foo_proto, IARG_FUNCARG_ENTRYPOINT_VALUE, 6, IARG_FUNCARG_ENTRYPOINT_VALUE, 5, IARG_FUNCARG_ENTRYPOINT_VALUE, 4, IARG_FUNCARG_ENTRYPOINT_VALUE, 3, IARG_FUNCARG_ENTRYPOINT_VALUE, 2, IARG_FUNCARG_ENTRYPOINT_VALUE, 1, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_END); RTN_InsertCallProbed(routine, IPOINT_AFTER, AFUNPTR( foo_after ), IARG_PROTOTYPE, foo_proto, IARG_RETURN_IP, 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); } } }
//scan the image and try to hook all the function specified above void HookFunctions::hookDispatcher(IMG img){ //for each function that we want to hook or replace for (std::map<string,int>::iterator item = this->functionsMap.begin(); item != this->functionsMap.end(); ++item){ //get the pointer to the specified function const char * func_name = item->first.c_str(); RTN rtn = RTN_FindByName(img, func_name); //if we found a valid routine if(rtn != RTN_Invalid()){ ADDRINT va_address = RTN_Address(rtn); MYINFO("Inside %s Address of %s: %08x" ,IMG_Name(img).c_str(),func_name, va_address); RTN_Open(rtn); int index = item->second; //decide what to do based on the function hooked //Different arguments are passed to the hooking routine based on the function switch(index){ case(VIRTUALALLOC_INDEX): RTN_InsertCall(rtn, IPOINT_AFTER, (AFUNPTR)VirtualAllocHook , IARG_FUNCARG_ENTRYPOINT_VALUE,1 , IARG_FUNCRET_EXITPOINT_VALUE, IARG_END); break; case(RTLALLOCATEHEAP_INDEX): //need to be IPOINT_AFTER because the allocated address is returned as return value RTN_InsertCall(rtn, IPOINT_AFTER, (AFUNPTR)RtlAllocateHeapHook , IARG_FUNCARG_ENTRYPOINT_VALUE,2, IARG_FUNCRET_EXITPOINT_VALUE, IARG_END); break; case(ISDEBUGGERPRESENT_INDEX): RTN_Replace(rtn, AFUNPTR(IsDebuggerPresentHook)); break; case(RTLREALLOCATEHEAP_INDEX): //IPOINT_BEFORE because the address to be realloc is passed as an input paramenter RTN_InsertCall(rtn,IPOINT_BEFORE,(AFUNPTR)RtlReAllocateHeapHook, IARG_FUNCARG_ENTRYPOINT_VALUE,2 , IARG_FUNCARG_ENTRYPOINT_VALUE,3, IARG_END); break; case(MAPVIEWOFFILE_INDEX): //need to be IPOINT_AFTER because the allocated address is returned as return value RTN_InsertCall(rtn,IPOINT_AFTER,(AFUNPTR)MapViewOfFileHookAfter,IARG_FUNCARG_ENTRYPOINT_VALUE,1,IARG_FUNCARG_ENTRYPOINT_VALUE,2,IARG_FUNCARG_ENTRYPOINT_VALUE,3, IARG_FUNCARG_ENTRYPOINT_VALUE,4,IARG_FUNCRET_EXITPOINT_VALUE, IARG_END); break; case(VIRTUALFREE_INDEX): RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)VirtualFreeHook , IARG_FUNCARG_ENTRYPOINT_VALUE,0, IARG_END); break; case(VIRTUALQUERY_INDEX): //IPOINT_AFTER because we have to check if the query is on a whitelisted address RTN_InsertCall(rtn, IPOINT_AFTER, (AFUNPTR)VirtualQueryHook, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_FUNCARG_ENTRYPOINT_VALUE, 1, IARG_FUNCRET_EXITPOINT_REFERENCE, IARG_END); break; case(VIRTUALQUERYEX_INDEX): //IPOINT_AFTER because we have to check if the query is on a whitelisted address RTN_InsertCall(rtn, IPOINT_AFTER, (AFUNPTR)VirtualQueryExHook, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_FUNCARG_ENTRYPOINT_VALUE, 1, IARG_FUNCARG_ENTRYPOINT_VALUE, 2, IARG_FUNCRET_EXITPOINT_REFERENCE, IARG_END); break; } RTN_Close(rtn); } } }