PVOID JMPHook::hook(PVOID tgt, PVOID rep){ this->target = tgt; this->replacer = rep; PVOID orig_fn = tgt; PVOID dest_fn = rep; newregion = (byte*) VirtualAlloc(0, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); memcpy(newregion, orig_fn, size); int p = memcmp(newregion, orig_fn, size); //printf("%d\n", p); unsigned long oldprotect = 0; VirtualProtect(orig_fn, size, PAGE_EXECUTE_READWRITE, &oldprotect); __asm{ mov eax, dword ptr [orig_fn]; // eax = orig_fn address mov ecx, 0xe9; // ecx = jmp relative mov [eax], ecx; // *orig_fn = jmp relative mov ecx, dword ptr [dest_fn]; // ecx = dest_fn address sub ecx, dword ptr [orig_fn]; // ecx = address(dest_fn) - address(orig_fn) sub ecx, 5; inc eax; // eax = orig_fn address + 1 mov dword ptr [eax], ecx; // *orig_fn = jmp relative to [dest_fn] } VirtualProtect(orig_fn, size, oldprotect, &oldprotect); VirtualProtect(newregion, size, PAGE_EXECUTE_READ, 0); FlushInstructionCache(0, orig_fn, size); FlushInstructionCache(0, newregion, size); return (PVOID) newregion; // address of the copied function }
int ThreadWaitUntil(HANDLE hProcess, HANDLE hThread, void *addr) { CONTEXT context = {0}; BYTE entry_asm_orig[2]; const BYTE entry_asm_delay[2] = {0xEB, 0xFE}; // JMP SHORT YADA YADA MEMORY_BASIC_INFORMATION mbi; DWORD byte_ret; DWORD old_prot; if(!VirtualQueryEx(hProcess, addr, &mbi, sizeof(mbi))) { return 1; } VirtualProtectEx(hProcess, mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &old_prot); ReadProcessMemory(hProcess, addr, entry_asm_orig, sizeof(entry_asm_orig), &byte_ret); WriteProcessMemory(hProcess, addr, entry_asm_delay, sizeof(entry_asm_delay), &byte_ret); FlushInstructionCache(hProcess, addr, sizeof(entry_asm_delay)); VirtualProtectEx(hProcess, mbi.BaseAddress, mbi.RegionSize, old_prot, &old_prot); context.ContextFlags = CONTEXT_CONTROL; while(context.Eip != (DWORD)addr) { ResumeThread(hThread); Sleep(10); SuspendThread(hThread); GetThreadContext(hThread, &context); } // Write back the original code WriteProcessMemory(hProcess, addr, entry_asm_orig, sizeof(entry_asm_orig), &byte_ret); FlushInstructionCache(hProcess, addr, sizeof(entry_asm_orig)); return 0; }
void ResetSoftwareBreakpoint(HANDLE hProcess, DWORD dwAddr, BYTE original) { DWORD dwRead; WriteProcessMemory(hProcess, (LPVOID)dwAddr, &original, 1, &dwRead); FlushInstructionCache(hProcess, (LPVOID)dwAddr, 1); }
extern "C" int __declspec(dllexport) FixBP(DWORD dwAddress,BYTE bInstruction,DWORD dwFinalClean) { BOOL bret; DWORD dw; HANDLE hThread; CONTEXT context; if (dwFinalClean) { bret = WriteProcessMemory(hProcess,(LPVOID)dwAddress,&bInstruction,1,&dw); return 0; } hThread = OpenThread(THREAD_ALL_ACCESS,0,dbg_event.dwThreadId); memset(&context,0,sizeof(CONTEXT)); context.ContextFlags = CONTEXT_ALL; bret = GetThreadContext(hThread,&context); if (bret == 0) return 0; bret = WriteProcessMemory(hProcess,(LPVOID)dwAddress,&bInstruction,1,&dw); FlushInstructionCache(hProcess,(LPVOID)dwAddress, 1); if (bret == 0) return 0; context.Eip = context.Eip - 1; context.EFlags |= 0x100; bret = SetThreadContext(hThread,&context); if (bret == 0) return 0; Log("hThread:%x EIP:%x bret:%d gle:%d",hThread,context.Eip,bret,GetLastError()); return 1; }
extern "C" int __declspec(dllexport) SetBP(DWORD dwAddress,BYTE &bInstruction) { DWORD dwRead,dwWritten; BYTE int3=0xCC; if (!ReadProcessMemory(hProcess,(LPCVOID)dwAddress,&bInstruction,1,&dwRead)) { Log("set_breakpoint: ReadMemory Err:%d hProcess:%x dwAddress:%x",GetLastError(),hProcess,dwAddress); return 0; } Log("call to set BP at %x : %02x",dwAddress,bInstruction); if (bInstruction != 0xcc) { if (!WriteProcessMemory(hProcess,(LPVOID)dwAddress,&int3,1,&dwWritten)) { Log("BP WriteProcessMemory Failed: %d",GetLastError()); } FlushInstructionCache(hProcess,(LPCVOID)dwAddress,1); Log("setting BP at %x : %02x",dwAddress,bInstruction); } else { Log("setting BP Failed CC present already."); return 0; } return 1; }
/** * @brief Injects redirection code into the target function. * * Replaces the first 6 Bytes of the function indicated by baseptr * with the replacement code previously generated (usually a jump * to mumble code). If a trampoline is available this injection is not needed * as control flow was already permanently redirected by HardHook::setup . * * @param force Perform injection even when trampoline is available. */ void HardHook::inject(bool force) { if (! baseptr) return; if (! force && bTrampoline) return; DWORD origProtect; if (VirtualProtect(baseptr, CODEREPLACESIZE, PAGE_EXECUTE_READWRITE, &origProtect)) { for (int i = 0; i < CODEREPLACESIZE; ++i) { baseptr[i] = replace[i]; // Replace with jump to new code } DWORD tempProtect; VirtualProtect(baseptr, CODEREPLACESIZE, origProtect, &tempProtect); FlushInstructionCache(GetCurrentProcess(), baseptr, CODEREPLACESIZE); } // Verify that the injection was successful for (int i = 0; i < CODEREPLACESIZE; ++i) { if (baseptr[i] != replace[i]) { fods("HardHook: Injection failure noticed at byte %d", i); } } }
CompiledProgram::CompiledProgram(Program in_program) { mProgSize=0; for (Program::iterator i=in_program.begin(); i!=in_program.end(); i++) { mProgSize+=i->size(); } mpProg=VirtualAlloc( NULL, mProgSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE ); if (mpProg == NULL ) exit(0); size_t progPos=0; for (Program::iterator i=in_program.begin(); i!=in_program.end(); i++) { memcpy((unsigned char*) mpProg+progPos, &(*i)[0], i->size()); progPos+=i->size(); } DWORD flOldProtect; if (!VirtualProtect(mpProg, size(), PAGE_EXECUTE, &flOldProtect)) exit(0); if (!FlushInstructionCache(GetCurrentProcess(), mpProg, size())) exit(0); }
LPVOID InjectData(HANDLE hProcess,LPVOID lpData,ULONG ulFuncLen) { LPVOID lpAddress=NULL; DWORD dwOldProtect; DWORD BytesWritten=0; // Allocate memory for lpData int the remote process lpAddress=VirtualAllocEx(hProcess,NULL,ulFuncLen,MEM_COMMIT|MEM_TOP_DOWN,PAGE_EXECUTE_READWRITE); if (lpAddress) { // Change the protection for the allocated memory if (VirtualProtectEx(hProcess,lpAddress,ulFuncLen,PAGE_EXECUTE_READWRITE,&dwOldProtect)) { // ... FlushInstructionCache(hProcess,lpAddress,ulFuncLen); // Write lpData into the remote process if (WriteProcessMemory(hProcess,lpAddress,lpData,ulFuncLen,&BytesWritten)) { // Restore old protection :) VirtualProtectEx(hProcess,lpAddress,ulFuncLen,dwOldProtect,NULL); // Return remote address for lpData return lpAddress; } // Restore old protection :) VirtualProtectEx(hProcess,lpAddress,ulFuncLen,dwOldProtect,NULL); } } return 0; }
/* Transfer memory from/to the debugged process. */ static int child_xfer_memory (CORE_ADDR memaddr, char *our, int len, int write, struct target_ops *target) { BOOL success; SIZE_T done = 0; DWORD lasterror = 0; uintptr_t addr = (uintptr_t) memaddr; if (write) { success = WriteProcessMemory (current_process_handle, (LPVOID) addr, (LPCVOID) our, len, &done); if (!success) lasterror = GetLastError (); FlushInstructionCache (current_process_handle, (LPCVOID) addr, len); } else { success = ReadProcessMemory (current_process_handle, (LPCVOID) addr, (LPVOID) our, len, &done); if (!success) lasterror = GetLastError (); } if (!success && lasterror == ERROR_PARTIAL_COPY && done > 0) return done; else return success ? done : -1; }
// !TODO: Add auto alloc for missing stub void *HookSub(void *oldProc, void *newProc) { void *jmpAddr = (void *)((char *)newProc - (char *)oldProc - 5); // patch DWORD oldProtect = NULL; VirtualProtect(oldProc, 5, PAGE_EXECUTE_WRITECOPY, &oldProtect); __asm { push eax push ebx mov eax, oldProc mov ebx, jmpAddr mov byte ptr [eax], 0xE9 // long jmp mov dword ptr [eax + 1], ebx pop ebx pop eax } VirtualProtect(oldProc, 5, oldProtect, &oldProtect); FlushInstructionCache(GetCurrentProcess(), oldProc, 5); return ((void *)((char *)oldProc + 5)); }
bool CDetour::Remove ( BYTE *orig, BYTE *jmp, int iPatchType, int len ) { int iMinLen = 0; DWORD dwBack = 0; if ( !(iMinLen = GetDetourLen(iPatchType)) ) return false; if ( len != 0 && len < iMinLen ) return false; // Try and find the end of the instruction automatically if ( len == 0 ) { len = GetDetourLenAuto( jmp, iMinLen ); if ( len == 0 ) len = GetDetourLen( iPatchType ); if ( len == 0 || iMinLen == 0 ) return false; if ( len < iMinLen ) return false; } // Write the bytes @ the jmp back to the orig MEMORY_BASIC_INFORMATION mbi; VirtualQuery( (void *)orig, &mbi, sizeof(mbi) ); VirtualProtect( mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &mbi.Protect ); memcpy( orig, jmp, len ); VirtualProtect( mbi.BaseAddress, mbi.RegionSize, mbi.Protect, &mbi.Protect ); FlushInstructionCache( GetCurrentProcess(), (void *)orig, len ); return true; }
BOOL HEStopHook(PHOOKINFO HookInfo) { BOOL CallRet; DWORD dwTmp; DWORD OldProtect; LPVOID FuncAddr = HookInfo->FuncAddr; DWORD CodeLength = HookInfo->CodeLength; CallRet = VirtualProtect(FuncAddr, CodeLength, PAGE_EXECUTE_READWRITE, &OldProtect); if (!CallRet) { return 1; } CallRet = WriteProcessMemory(GetCurrentProcess(), FuncAddr, HookInfo->Stub, CodeLength, &dwTmp); if (!CallRet || dwTmp != CodeLength) { return 2; } FlushInstructionCache(GetCurrentProcess(), FuncAddr, CodeLength); VirtualProtect(FuncAddr, CodeLength, OldProtect, &dwTmp); free(HookInfo->Stub); return 0; }
BOOL UnhookFunction(LPTSTR ModuleName, LPCSTR FunctionName, PVOID proxyFunction) { PVOID oldFunction = NULL; DWORD oldProtect = 0; TCHAR tzTemp[MAX_PATH] = {0}; oldFunction = GetProcAddress(GetModuleHandle(ModuleName), FunctionName); if (!oldFunction) { wsprintf(tzTemp, TEXT("Failed to find the function: %hs\n"), FunctionName); OutputDebugText(tzTemp); return FALSE; } // Recover the function VirtualProtect(oldFunction, JumpCodeSize, PAGE_EXECUTE_READWRITE, &oldProtect); RtlCopyMemory(oldFunction, proxyFunction, JumpCodeSize); VirtualProtect(oldFunction, JumpCodeSize, oldProtect, &oldProtect); FlushInstructionCache(GetModuleHandle(NULL), oldFunction, JumpCodeSize); if (!VirtualFree(proxyFunction, 0, MEM_RELEASE)) { wsprintf(tzTemp, TEXT("Failed to free memory for the function: %hs\n"), FunctionName); OutputDebugText(tzTemp); } return TRUE; }
void DoTest(void *Buffer, int Size, int Expected) { int ret; SetLastError(0); ret = FlushInstructionCache(GetCurrentProcess(), Buffer, Size); if (!ret && Expected) { Fail("Expected FlushInstructionCache to return non-zero, got zero!\n" "region: %p, size: %d, GetLastError: %d\n", Buffer, Size, GetLastError()); } else if (ret && !Expected) { Fail("Expected FlushInstructionCache to return zero, got non-zero!\n" "region: %p, size: %d, GetLastError: %d\n", Buffer, Size, GetLastError()); } if (!Expected && ERROR_NOACCESS != GetLastError()) { Fail("FlushInstructionCache failed to set the last error to " "ERROR_NOACCESS!\n"); } }
void FixupInlineGetters(DWORD tlsSlot, const LPVOID * pLocations, int nLocations) { BYTE* pInlineGetter; DWORD dwOldProtect; for (int i=0; i<nLocations; i++) { pInlineGetter = (BYTE*)GetEEFuncEntryPoint((BYTE*)pLocations[i]); static const DWORD cbPatch = 9; if (!ClrVirtualProtect(pInlineGetter, cbPatch, PAGE_EXECUTE_READWRITE, &dwOldProtect)) { ThrowLastError(); } DWORD offset = (tlsSlot * sizeof(LPVOID) + offsetof(TEB, TlsSlots)); #if defined(_TARGET_AMD64_) // mov r??, gs:[TLS offset] _ASSERTE_ALL_BUILDS("clr/src/VM/JITinterfaceGen.cpp", pInlineGetter[0] == 0x65 && pInlineGetter[2] == 0x8B && pInlineGetter[4] == 0x25 && "Initialization failure while stomping instructions for the TLS slot offset: the instruction at the given offset did not match what we expect"); *((DWORD*)(pInlineGetter + 5)) = offset; #else // _TARGET_AMD64_ PORTABILITY_ASSERT("FixupInlineGetters"); #endif //_TARGET_AMD64_ FlushInstructionCache(GetCurrentProcess(), pInlineGetter, cbPatch); ClrVirtualProtect(pInlineGetter, cbPatch, dwOldProtect, &dwOldProtect); } }
//------------------------------------------------------------------------------ void* hook_jmp(const char* dll, const char* func_name, void* hook) { void* func_addr; void* trampoline; // Get the address of the function we're going to hook. func_addr = get_proc_addr(dll, func_name); if (func_addr == NULL) { LOG_INFO("Failed to find function '%s' in '%s'", dll, func_name); return NULL; } LOG_INFO("Attemping jump hook."); LOG_INFO("Target is %s, %s @ %p", dll, func_name, func_addr); // Install the hook. trampoline = hook_jmp_impl(func_addr, hook); if (trampoline == NULL) { LOG_INFO("Jump hook failed."); return NULL; } LOG_INFO("Success!"); FlushInstructionCache(current_proc(), 0, 0); return trampoline; }
void finalize() { IF_ZERO_THROW_LAST_ERROR(VirtualProtect(_memory, _size, PAGE_EXECUTE_READ)); IF_ZERO_THROW_LAST_ERROR(FlushInstructionCache(GetCurrentProcess(), _memory, _size)); }
void *HotPatchSub(void *oldProc, void *newProc) { void *hotPatchAddr = (void *)((char *)oldProc - 5); void *jmpAddr = (void *)((char *)newProc - (char *)oldProc); // patch DWORD oldProtect = NULL; VirtualProtect(hotPatchAddr, 7, PAGE_EXECUTE_READWRITE, &oldProtect); __asm { push eax push ebx mov eax, oldProc mov ebx, jmpAddr mov byte ptr [eax - 5], 0xE9 // long jmp mov dword ptr [eax - 4], ebx mov word ptr [eax], 0xF9EB // EB F9 = jmp - 7 pop ebx pop eax } VirtualProtect(hotPatchAddr, 7, oldProtect, &oldProtect); FlushInstructionCache(GetCurrentProcess(), hotPatchAddr, 7); return ((void *)((char *)oldProc + 2)); }
bool ApplyPatch(const PatchInfo& patch) { auto module = GetModuleHandleW(patch.module_name); if (module == nullptr) { return false; } auto ucrtbase_pe = (PIMAGE_NT_HEADERS)((uintptr_t)module + ((PIMAGE_DOS_HEADER)module)->e_lfanew); if (ucrtbase_pe->OptionalHeader.CheckSum != patch.checksum) { return false; } void* patch_addr = (void*)((uintptr_t)module + patch.rva); size_t patch_size = patch.length; DWORD old_protect; if (!VirtualProtect(patch_addr, patch_size, PAGE_EXECUTE_READWRITE, &old_protect)) { return false; } memset(patch_addr, 0x90, patch_size); VirtualProtect(patch_addr, patch_size, old_protect, &old_protect); FlushInstructionCache(GetCurrentProcess(), patch_addr, patch_size); return true; }
BOOL WindowsDebugger::debugger_set_breakpoint( unsigned long ulAddress ) { IMemory * lpMemory = this->windowsdebugger_get_proc_memory(); DEBUGGER_BREAKPOINT * lpBp = new DEBUGGER_BREAKPOINT(); lpBp->ulAddress = ulAddress; lpBp->nTimesHit = 0; if( lpMemory->memory_get_address_contents( this->nProcessId, (void *)ulAddress, 1, &lpBp->lpOriginalCode ) == FALSE ) { PrintError( "Error Reading Breakpoint address" ); return FALSE; } lpBp->bEnabled = TRUE; this->vBreakpoints.push_back(lpBp); if( lpMemory->memory_write_to_address( this->nProcessId, (void *)ulAddress, lpBpInstruction, sizeof(lpBpInstruction ) ) == FALSE ) { PrintError( "Unable to set breakpoint" ); lpBp->bEnabled = FALSE; this->debugger_clear_breakpoint( ulAddress ); return FALSE; } FlushInstructionCache( this->hProcess, (LPCVOID)lpBp->ulAddress, sizeof(lpBpInstruction) ); return TRUE; }
void WritePattern(LPVOID address, const signed short *data, SIZE_T size, MemorySegment *mem) { DWORD oldProtect; // Allowing reading from and writing to this memory space. VirtualProtect(address, size, PAGE_EXECUTE_READWRITE, &oldProtect); // Backup memory. if(mem != NULL) { mem->address = address; mem->size = size; mem->data = (unsigned char*)malloc(size * sizeof(unsigned char)); memcpy(mem->data, address, size); } unsigned char *a, *end = (unsigned char*)address + size; for(a = (unsigned char*)address; a < end; ++a, ++data) { // Ignore -1s. if(*data != -1) *a = (unsigned char)*data; } // Restore permissions to this memory space. VirtualProtect(address, size, oldProtect, &oldProtect); FlushInstructionCache(GetCurrentProcess(), address, size); }
PVOID HookFunction(LPTSTR ModuleName, LPCSTR FunctionName, PVOID MyFunction) { PVOID oldFunction = NULL; PVOID proxyFunction = NULL; LPBYTE opCode = NULL; DWORD backupLen = 0; DWORD oldProtect = 0; TCHAR tzTemp[MAX_PATH] = {0}; // Get original function address oldFunction = GetProcAddress(GetModuleHandle(ModuleName), FunctionName); if (!oldFunction) { wsprintf(tzTemp, TEXT("Failed to find the function: %hs\n"), FunctionName); OutputDebugText(tzTemp); return NULL; } // Get the exact length while (backupLen < JumpCodeSize) backupLen += size_of_code((LPBYTE)((DWORD)oldFunction + backupLen), &opCode); // Fill the data *(DWORD *)(JumpCode + 1) = (DWORD)MyFunction; *(DWORD *)(JumpbackCode + 1) = (DWORD)oldFunction + backupLen; // Allocate space for proxy function proxyFunction = VirtualAlloc(NULL, backupLen + JumpCodeSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (!proxyFunction) { wsprintf(tzTemp, TEXT("Failed to allocate space for the function: %hs\n"), FunctionName); OutputDebugText(tzTemp); return NULL; } // Fill proxy function and flush instructions RtlCopyMemory(proxyFunction, oldFunction, backupLen); RtlCopyMemory((PVOID)((DWORD)proxyFunction + backupLen), JumpbackCode, JumpbackCodeSize); FlushInstructionCache(GetModuleHandle(NULL), proxyFunction, backupLen + JumpCodeSize); // Modify original function VirtualProtect(oldFunction, JumpCodeSize, PAGE_EXECUTE_READWRITE, &oldProtect); RtlCopyMemory(oldFunction, JumpCode, JumpCodeSize); VirtualProtect(oldFunction, JumpCodeSize, oldProtect, &oldProtect); FlushInstructionCache(GetModuleHandle(NULL), oldFunction, JumpCodeSize); return proxyFunction; }
void OsMisc_flush_icache(address start, int size) { #if defined(_WIN32_WCE) /* Currently the PocketPC API doesn't seem to support selective flushing of the icache => ignore start, size for now */ BOOL ret = FlushInstructionCache(GetCurrentProcess(), 0, 0); #else javacall_os_flush_icache((unsigned char*)start, size); #endif }
HL_API bool hl_debug_flush( int pid, vbyte *addr, int size ) { # if defined(HL_WIN) return (bool)FlushInstructionCache(OpenPID(pid),addr,size); # elif defined(USE_PTRACE) return true; # else return false; # endif }
U NCodeHook<ArchT>::createHook(U originalFunc, U hookFunc) { // check if this function is already hooked std::map<uintptr_t, NCodeHookItem>::const_iterator cit = hookedFunctions_.begin(); while(cit != hookedFunctions_.end()) { if ((uintptr_t)cit->second.OriginalFunc == (uintptr_t)originalFunc) return (U)cit->second.Trampoline; ++cit; } bool useAbsJump = forceAbsJmp_; int offset = 0; if (useAbsJump || architecture_.requiresAbsJump((uintptr_t)originalFunc, (uintptr_t)hookFunc)) { offset = getMinOffset((const unsigned char*)originalFunc, ArchT::AbsJumpPatchSize); useAbsJump = true; } else offset = getMinOffset((const unsigned char*)originalFunc, ArchT::NearJumpPatchSize); if (offset == -1) return false; DWORD oldProtect = 0; BOOL retVal = VirtualProtect((LPVOID)originalFunc, ArchT::MaxTrampolineSize, PAGE_EXECUTE_READWRITE, &oldProtect); if (!retVal) return false; // Get trampoline memory and copy instructions to trampoline. uintptr_t trampolineAddr = getFreeTrampoline(); memcpy((void*)trampolineAddr, (void*)originalFunc, offset); if (useAbsJump) { architecture_.writeAbsJump((uintptr_t)originalFunc, (uintptr_t)hookFunc); architecture_.writeAbsJump(trampolineAddr + offset, (uintptr_t)originalFunc + offset); } else { architecture_.writeNearJump((uintptr_t)originalFunc, (uintptr_t)hookFunc); architecture_.writeNearJump(trampolineAddr + offset, (uintptr_t)originalFunc + offset); } DWORD dummy; VirtualProtect((LPVOID)originalFunc, ArchT::MaxTrampolineSize, oldProtect, &dummy); FlushInstructionCache(GetCurrentProcess(), (LPCVOID)trampolineAddr, MaxTotalTrampolineSize); FlushInstructionCache(GetCurrentProcess(), (LPCVOID)originalFunc, useAbsJump ? ArchT::AbsJumpPatchSize : ArchT::NearJumpPatchSize); NCodeHookItem item((uintptr_t)originalFunc, (uintptr_t)hookFunc, trampolineAddr, offset); hookedFunctions_.insert(std::make_pair((uintptr_t)hookFunc, item)); return (U)trampolineAddr; }
VOID BtrUnregisterProbes( VOID ) { PBTR_PROBE Probe; PBTR_TRAP Trap; ULONG Protect; ULONG Number; HANDLE ProcessHandle; PUCHAR CopyFrom; LIST_ENTRY ProcessList; PLIST_ENTRY ListHead; PLIST_ENTRY ListEntry; InitializeListHead(&ProcessList); BtrSuspendProcess(&ProcessList); ProcessHandle = GetCurrentProcess(); for (Number = 0; Number < BtrProbeDatabase.NumberOfBuckets; Number += 1) { ListHead = &BtrProbeDatabase.ListEntry[Number]; while (IsListEmpty(ListHead) != TRUE) { ListEntry = RemoveHeadList(ListHead); Probe = CONTAINING_RECORD(ListEntry, BTR_PROBE, ListEntry); Trap = Probe->Trap; ASSERT(Trap != NULL); VirtualProtect(Probe->PatchAddress, BtrPageSize, PAGE_EXECUTE_READWRITE, &Protect); __try { if (!FlagOn(Probe->Flags, BTR_FLAG_FUSELITE)) { CopyFrom = Trap->OriginalCopy; } else { CopyFrom = Trap->OriginalCopy; } RtlCopyMemory(Probe->PatchAddress, CopyFrom, Trap->HijackedLength); FlushInstructionCache(ProcessHandle, Probe->PatchAddress, Trap->HijackedLength); } __except(EXCEPTION_EXECUTE_HANDLER) { } VirtualProtect(Probe->PatchAddress, BtrPageSize, PAGE_EXECUTE_READWRITE, &Protect); } } BtrResumeProcess(&ProcessList); }
void* CDetour::memcpy_s( void* pvAddress, const void* pvBuffer, size_t stLen ) { MEMORY_BASIC_INFORMATION mbi; VirtualQuery( ( void* )pvAddress, &mbi, sizeof( mbi ) ); VirtualProtect( mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &mbi.Protect ); void* pvRetn = memcpy( ( void* )pvAddress, ( void* )pvBuffer, stLen ); VirtualProtect( mbi.BaseAddress, mbi.RegionSize, mbi.Protect, &mbi.Protect ); FlushInstructionCache( GetCurrentProcess( ), ( void* )pvAddress, stLen ); return pvRetn; }
template <typename TAlloc> inline void JITThunkEmitter<TAlloc>::FreeThunk(uintptr_t thunkAddress) { AutoCriticalSection autoCs(&this->cs); BVIndex thunkIndex = GetThunkIndexFromAddress(thunkAddress); if (thunkIndex >= this->freeThunks.Length() || this->freeThunks.TestAndSet(thunkIndex)) { Assert(UNREACHED); this->firstBitToCheck = 0; return; } if (thunkIndex < firstBitToCheck) { this->firstBitToCheck = thunkIndex; } if (CONFIG_FLAG(OOPCFGRegistration)) { #if ENABLE_OOP_NATIVE_CODEGEN if (JITManager::GetJITManager()->IsJITServer()) { HANDLE fileHandle = nullptr; PVOID baseAddress = nullptr; bool found = this->codeAllocator->GetFileInfo((PVOID)thunkAddress, &fileHandle, &baseAddress); AssertOrFailFast(found); this->threadContext->SetValidCallTargetFile((PVOID)thunkAddress, fileHandle, baseAddress, false); } else #endif { this->threadContext->SetValidCallTargetForCFG((PVOID)thunkAddress, false); } } uintptr_t pageStartAddress = GetThunkPageStart(thunkAddress); if (IsThunkPageEmpty(pageStartAddress)) { this->codeAllocator->Free((PVOID)pageStartAddress, AutoSystemInfo::PageSize, MEM_DECOMMIT); } else { char * localAddress = (char *)this->codeAllocator->AllocLocal((PVOID)thunkAddress, ThunkSize); if (localAddress == nullptr) { return; } UnprotectPage(localAddress); memset(localAddress, 0xCC, ThunkSize); ProtectPage(localAddress); this->codeAllocator->FreeLocal(localAddress); } FlushInstructionCache(this->processHandle, (PVOID)thunkAddress, ThunkSize); }
void *IATPatchSub(TCHAR *imageName, char *importImageName, char *oldImport, void *newProc) { HANDLE hDll = NULL; hDll = GetModuleHandle(imageName); void *oldProcAddr = NULL; IMAGE_NT_HEADERS *header = NULL; IMAGE_DATA_DIRECTORY *importsDirectoryEntry = NULL; IMAGE_IMPORT_DESCRIPTOR *imageImports = NULL; header = ImageNtHeader((void *)hDll); // First, unprotect the assembly. DWORD oldProtect = 0; importsDirectoryEntry = (IMAGE_DATA_DIRECTORY *)&header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; imageImports = (IMAGE_IMPORT_DESCRIPTOR *)PE_RvaToVa(hDll, importsDirectoryEntry->VirtualAddress); while (imageImports->Name != 0) { char *currentModule = (char *)PE_RvaToVa(hDll, imageImports->Name); if (strcmp(currentModule, importImageName) == 0) { PIMAGE_THUNK_DATA pOriginalThunks = NULL; PIMAGE_THUNK_DATA pThunks = NULL; pOriginalThunks = (PIMAGE_THUNK_DATA)PE_RvaToVa(hDll, imageImports->OriginalFirstThunk); pThunks = (PIMAGE_THUNK_DATA)PE_RvaToVa(hDll, imageImports->FirstThunk); for (int i = 0; pOriginalThunks[i].u1.AddressOfData != 0; i++) { IMAGE_IMPORT_BY_NAME *name = (IMAGE_IMPORT_BY_NAME *)PE_RvaToVa(hDll, pOriginalThunks[i].u1.AddressOfData); char *currentProc = (char *)&(name->Name); if (strcmp(currentProc, oldImport) == 0) { oldProcAddr = (void *)pThunks[i].u1.Function; VirtualProtect((void *)&pThunks[i], sizeof(pThunks[i]), PAGE_READWRITE, &oldProtect); pThunks[i].u1.Function = (DWORD)newProc; VirtualProtect((void *)&pThunks[i], sizeof(pThunks[i]), oldProtect, &oldProtect); FlushInstructionCache(GetCurrentProcess(), NULL, 0); return (oldProcAddr); } } } imageImports++; } return (NULL); }
bool Pdb::RemoveBp(adr_t address) { int pos = bp_set.Find(address); if(pos < 0) return true; if(!WriteProcessMemory(hProcess, (LPVOID)address, &bp_set[pos], 1, NULL)) return false; FlushInstructionCache(hProcess, (LPCVOID)address, 1); bp_set.Unlink(pos); return true; }