VOID ImageLoad( IMG img, VOID *v ) { RTN rtn; fprintf( LogFile, "Loaded %s\r\n", IMG_Name( img ).c_str() ); // UDP if ( (rtn = RTN_FindByName( img, "recvfrom" )) != RTN_Invalid() ) { HookRecvFrom( img ); } if ( (rtn = RTN_FindByName( img, "sendto" )) != RTN_Invalid() ) { HookSendTo( img ); } // TCP if ( (rtn = RTN_FindByName( img, "recv" )) != RTN_Invalid() ) { HookRecv( img ); } if ( (rtn = RTN_FindByName( img, "send" )) != RTN_Invalid() ) { HookSend( img ); } /* Uncomment if necessary, untested though! if ( (rtn = RTN_FindByName( img, "WSASendTo" )) != RTN_Invalid() ) { HookWSASendTo( img, (AFUNPTR)replacementWSASendTo, "WSASendTo" ); } */ }
static void I_ImageLoad(IMG img, void *v) { static bool main_rtn_instrumented = false; if( !main_rtn_instrumented ) { RTN rtn = RTN_FindByName(img, "main"); if( rtn == RTN_Invalid() ) { rtn = RTN_FindByName(img, "__libc_start_main"); } // Instrument main if( rtn != RTN_Invalid() ) { main_rtn_instrumented = true; RTN_Open(rtn); RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)A_EnterMainImage, IARG_INST_PTR, IARG_ADDRINT, RTN_Address(rtn), IARG_REG_VALUE, REG_STACK_PTR, IARG_END); RTN_Close(rtn); } } for( SYM sym = IMG_RegsymHead(img); SYM_Valid(sym); sym = SYM_Next(sym) ) { if( strstr(SYM_Name(sym).c_str(), "MAID_register_address" ) ) { RTN rtn; rtn = RTN_FindByName(img, SYM_Name(sym).c_str()); ASSERTX(RTN_Valid(rtn)); RTN_Open(rtn); RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)A_RegisterAddr, IARG_G_ARG0_CALLEE, IARG_END); RTN_Close(rtn); } else if( strstr(SYM_Name(sym).c_str(), "MAID_unregister_address" ) ) { RTN rtn; rtn = RTN_FindByName(img, SYM_Name(sym).c_str()); ASSERTX(RTN_Valid(rtn)); RTN_Open(rtn); RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)A_UnregisterAddr, IARG_G_ARG0_CALLEE, IARG_END); RTN_Close(rtn); } } }
// Pin calls this function every time a new img is loaded VOID ImageLoad(IMG img, VOID *v) { if (!IMG_IsMainExecutable(img)) return; printf("%s loaded\n", IMG_Name(img).c_str()); fflush(stdout); ADDRINT imageBase = IMG_LowAddress(img); WINDOWS::PIMAGE_DATA_DIRECTORY pExpDir = GetExportDirectory(imageBase); if ((pExpDir == 0) || (pExpDir->Size == 0)) { // Failure: Executable image lacks export directory. printf("ERROR: No export directory in executable image\n"); fflush(stdout); exit(3); } ADDRINT exportBase = imageBase + pExpDir->VirtualAddress; // First check that bytes in export directory range do not belong to a RTN for (ADDRINT addr = exportBase; addr < exportBase + pExpDir->Size; ++addr) { if (RTN_FindByAddress(addr) != RTN_Invalid()) { // Test failure. Byte in export directory belongs to a RTN. printf("ERROR: Data from export directory included in RTN\n"); fflush(stdout); exit(1); } } // Second check RTN size. RTN range should not overlap with export directory range. for (SEC sec = IMG_SecHead(img); sec != SEC_Invalid(); sec = SEC_Next(sec)) { for (RTN rtn = SEC_RtnHead(sec); rtn != RTN_Invalid(); rtn = RTN_Next(rtn)) { if (((RTN_Address(rtn) <= exportBase) && (RTN_Address(rtn) + RTN_Size(rtn) > exportBase)) || ((RTN_Address(rtn) > exportBase) && (exportBase + pExpDir->Size > RTN_Address(rtn)))) { // Test failure. RTN overlaps with export directory. printf("ERROR: RTN overlaps with export directory\n"); fflush(stdout); exit(2); } } } return; }
// - Get initial entropy // - Get PE section data // - Add filtered library void imageLoadCallback(IMG img,void *){ Section item; static int va_hooked = 0; //get the initial entropy of the PE //we have to consder only the main executable and avìvoid the libraries if(IMG_IsMainExecutable(img)){ ProcInfo *proc_info = ProcInfo::getInstance(); //get the address of the first instruction proc_info->setFirstINSaddress(IMG_Entry(img)); //get the program name proc_info->setProcName(IMG_Name(img)); //get the initial entropy MYINFO("----------------------------------------------"); float initial_entropy = proc_info->GetEntropy(); proc_info->setInitialEntropy(initial_entropy); MYINFO("----------------------------------------------"); //retrieve the section of the PE for( SEC sec= IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec) ){ item.name = SEC_Name(sec); item.begin = SEC_Address(sec); item.end = item.begin + SEC_Size(sec); proc_info->insertSection(item); } //DEBUG proc_info->PrintSections(); } //build the filtered libtrary list FilterHandler *filterH = FilterHandler::getInstance(); ADDRINT startAddr = IMG_LowAddress(img); ADDRINT endAddr = IMG_HighAddress(img); const string name = IMG_Name(img); if(!IMG_IsMainExecutable(img) && filterH->isKnownLibrary(name)){ /* searching for VirtualAlloc */ RTN rtn = RTN_FindByName( img, "VirtualAlloc"); if(rtn != RTN_Invalid()){ MYINFO("BECCATO LA VIRTUAL ALLOC\n"); ADDRINT va_address = RTN_Address(rtn); MYINFO("Address of VirtualAlloc: %08x\n" , va_address); RTN_Open(rtn); RTN_InsertCall(rtn, IPOINT_AFTER, (AFUNPTR)VirtualAllocHook , IARG_G_ARG0_CALLEE , IARG_G_ARG1_CALLEE , IARG_G_RESULT0, IARG_END); RTN_Close(rtn); } filterH->addLibrary(name,startAddr,endAddr); } }
// This function is called whenever Pin wants to report a breakpoint event to the // debugger. // static BOOL InterceptBreakpoint(THREADID tid, DEBUGGING_EVENT eventType, CONTEXT *ctxt, VOID *) { if (eventType != DEBUGGING_EVENT_BREAKPOINT) { std::cout << "FAILURE: Wrong event type in InterceptBreakpoint()" << std::endl; std::exit(1); } ADDRINT pc = PIN_GetContextReg(ctxt, REG_INST_PTR); RTN rtn = RTN_FindByAddress(pc); // When the application triggers the breakpoint in Breakpoint1(), squash the breakpoint // and roll the application back to the Checkpoint() call. The application will NOT stop // at the breakpoint, and it will immediately resume from Checkpoint(). // if (rtn != RTN_Invalid() && RTN_Name(rtn) == "Breakpoint1") { std::cout << "Intercepting breakpoint #1 at 0x" << std::hex << pc << std::endl; PIN_SaveContext(&SavedContext, ctxt); PIN_SetContextReg(ctxt, REG_GAX, 1); MemLog.Restore(); IsCheckpointing = FALSE; return FALSE; } // When the application triggers the breakpoint in Breakpoint2(), do not squash the // breakpoint, but change the return value from Breakpoint2(). The application will stop // in the debugger, and the debugger should see the modified return value. // if (rtn != RTN_Invalid() && (RTN_Name(rtn) == "Breakpoint2" || RTN_Name(rtn) == "Breakpoint2Label")) { std::cout << "Intercepting breakpoint #2 at 0x" << std::hex << pc << std::endl; std::cout << "RTN=" << RTN_Name(rtn) << std::endl; PIN_SetContextReg(ctxt, REG_GAX, 1); return TRUE; } std::cout << "Skipping breakpoint at 0x" << std::hex << pc << ", RTN=" << RTN_Name(rtn) << std::endl; return TRUE; }
// This routine is executed for each image VOID ImageLoad(IMG img, VOID *v) { if (!FlashPlayerConfigBuilder::instance().isSupportedFlashPlayer(img)) { return; } LOGF("Found supported Flash Player image: %s (0x%x - 0x%x)\n", IMG_Name(img).c_str(), IMG_LowAddress(img), IMG_HighAddress(img)); config = FlashPlayerConfigBuilder::instance().getConfig(); // config->setInterpRVA needs to be chosen in such way that // the value of _invoker can be found from [ESI+config->invinvokerOffsetInMethodInfookerOffset] RTN setInterp = RTN_CreateAt(config->loadOffset + config->setInterpRVA, "setInterp"); // config->setInterpRVA needs to be chosen in such way that // the value of _implGPR can be found from EAX RTN verifyOnCall = RTN_CreateAt(config->loadOffset + config->verifyOnCallRVA, "verifyOnCall"); if (setInterp == RTN_Invalid() || verifyOnCall == RTN_Invalid()) { LOGF("Instrumenting Flash Player failed. Check setInterp and verifyOnCall RVAs in config.\n"); return; } RTN_Open(setInterp); RTN_InsertCall(setInterp, IPOINT_BEFORE, (AFUNPTR)InterpretedMethodVerified, IARG_REG_VALUE, REG_ESI, IARG_END); RTN_Close(setInterp); RTN_Open(verifyOnCall); if(config->m_flash_version == VER_15){ RTN_InsertCall(verifyOnCall, IPOINT_AFTER, (AFUNPTR)JITedMethodVerified, IARG_REG_VALUE, REG_ECX, IARG_END); } else{ RTN_InsertCall(verifyOnCall, IPOINT_AFTER, (AFUNPTR)JITedMethodVerified, IARG_REG_VALUE, REG_EAX, IARG_END); } RTN_Close(verifyOnCall); // Register TraceCalls to be called to instrument instructions INS_AddInstrumentFunction(TraceCalls, 0); }
void ImageLoad (IMG img, void *context) { fprintf (stderr, "Notified of load of %s at [%p,%p]\n", IMG_Name(img).c_str(), (char *)IMG_LowAddress(img), (char *)IMG_HighAddress(img)); // See if this is ntdll.dll char szName[_MAX_FNAME]; char szExt[_MAX_EXT]; _splitpath_s (IMG_Name(img).c_str(), NULL, 0, NULL, 0, szName, _MAX_FNAME, szExt, _MAX_EXT); strcat_s (szName, _MAX_FNAME, szExt); if (0 != _stricmp ("ntdll.dll", szName)) return; RTN rtn = RTN_FindByName (img, "RtlAllocateHeap"); if (RTN_Invalid() == rtn) { fprintf (stderr, "Failed to find RtlAllocateHeap in %s\n", IMG_Name(img).c_str()); return; } fprintf(stderr,"Replacing\n"); PROTO protoRtlAllocateHeap = PROTO_Allocate (PIN_PARG(void *), CALLINGSTD_STDCALL, "RtlAllocateHeap", PIN_PARG(WINDOWS::PVOID), // HeapHandle PIN_PARG(WINDOWS::ULONG), // Flags PIN_PARG(WINDOWS::SIZE_T), // Size PIN_PARG_END()); RTN_ReplaceSignature (rtn, (AFUNPTR)replacement_RtlAllocateHeap, IARG_PROTOTYPE, protoRtlAllocateHeap, IARG_ORIG_FUNCPTR, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_FUNCARG_ENTRYPOINT_VALUE, 1, IARG_FUNCARG_ENTRYPOINT_VALUE, 2, IARG_CONTEXT, IARG_END); PROTO_Free (protoRtlAllocateHeap); }
//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); } } }
int instrument_function(IMG img, const char* function_name, AFUNPTR callback) { __init(); RTN rtn = RTN_FindByName(img, function_name); if(rtn == RTN_Invalid()) { //printf("RTN_FindByName failed\n"); return -1; } RTN_Open(rtn); RTN_InsertCall(rtn, IPOINT_BEFORE, callback, IARG_UINT32, 1, IARG_END ); RTN_InsertCall(rtn, IPOINT_AFTER, callback, IARG_UINT32, 2, IARG_END ); RTN_Close(rtn); printf("callback inserted for function %s\n", function_name); return 0; }
RTN FindRTN(IMG img, const char *func_name) { RTN rtn = RTN_FindByName(img, func_name); if (RTN_Valid(rtn)) return rtn; // handle those symbols with version numbers. // e.g. pthread_create has global name: pthread_create@@GLIBC... std::string func_name_v(func_name); func_name_v.append("@@"); for(SYM sym = IMG_RegsymHead(img); SYM_Valid(sym); sym = SYM_Next(sym)) { if (SYM_Name(sym).find(func_name_v) != std::string::npos) { RTN rtn = RTN_FindByAddress(SYM_Address(sym)); DEBUG_ASSERT(RTN_Valid(rtn)); return rtn; } } return RTN_Invalid(); }
PyObject* Python_RTN_Invalid(PyObject* self, PyObject* args) { RTN* rtn_return = (RTN*) malloc(sizeof(RTN)); *rtn_return = RTN_Invalid(); return Py_BuildValue("L", rtn_return); }
static VOID HookHeapFunctions(IMG img) { RTN rtn; // check this image actually has the heap functions. if ((rtn = RTN_FindByName(img, "RtlAllocateHeap")) == RTN_Invalid()) return; // hook RtlAllocateHeap RTN rtlAllocate = RTN_FindByName(img, "RtlAllocateHeap"); PROTO protoRtlAllocateHeap = \ PROTO_Allocate( PIN_PARG(void *), CALLINGSTD_STDCALL, "RtlAllocateHeap", PIN_PARG(WINDOWS::PVOID), // HeapHandle PIN_PARG(WINDOWS::ULONG), // Flags PIN_PARG(WINDOWS::SIZE_T), // Size PIN_PARG_END() ); RTN_ReplaceSignature(rtlAllocate,(AFUNPTR)replacementRtlAllocateHeap, IARG_PROTOTYPE, protoRtlAllocateHeap, IARG_ORIG_FUNCPTR, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_FUNCARG_ENTRYPOINT_VALUE, 1, IARG_FUNCARG_ENTRYPOINT_VALUE, 2, IARG_CONTEXT, IARG_END ); PROTO_Free(protoRtlAllocateHeap); // replace RtlReAllocateHeap() RTN rtlReallocate = RTN_FindByName(img, "RtlReAllocateHeap"); PROTO protoRtlReAllocateHeap = \ PROTO_Allocate( PIN_PARG(void *), CALLINGSTD_STDCALL, "RtlReAllocateHeap", PIN_PARG(WINDOWS::PVOID), // HeapHandle PIN_PARG(WINDOWS::ULONG), // Flags PIN_PARG(WINDOWS::PVOID), // MemoryPtr PIN_PARG(WINDOWS::SIZE_T),// Size PIN_PARG_END() ); RTN_ReplaceSignature(rtlReallocate,(AFUNPTR)replacementRtlReAllocateHeap, IARG_PROTOTYPE, protoRtlReAllocateHeap, IARG_ORIG_FUNCPTR, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_FUNCARG_ENTRYPOINT_VALUE, 1, IARG_FUNCARG_ENTRYPOINT_VALUE, 2, IARG_FUNCARG_ENTRYPOINT_VALUE, 3, IARG_CONTEXT, IARG_END ); PROTO_Free(protoRtlReAllocateHeap); // replace RtlFreeHeap RTN rtlFree = RTN_FindByName(img, "RtlFreeHeap"); PROTO protoRtlFreeHeap = \ PROTO_Allocate( PIN_PARG(void *), CALLINGSTD_STDCALL, "RtlFreeHeap", PIN_PARG(WINDOWS::PVOID), // HeapHandle PIN_PARG(WINDOWS::ULONG), // Flags PIN_PARG(WINDOWS::PVOID), // MemoryPtr PIN_PARG_END() ); RTN_ReplaceSignature(rtlFree,(AFUNPTR)replacementRtlFreeHeap, IARG_PROTOTYPE, protoRtlFreeHeap, IARG_ORIG_FUNCPTR, IARG_FUNCARG_ENTRYPOINT_VALUE, 0, IARG_FUNCARG_ENTRYPOINT_VALUE, 1, IARG_FUNCARG_ENTRYPOINT_VALUE, 2, IARG_CONTEXT, IARG_END ); PROTO_Free(protoRtlAllocateHeap); }