mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-09-22 21:55:52 +00:00
Commit latest mhook changes from https://github.com/martona/mhook
This commit is contained in:
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2007-2008, Marton Anka
|
||||
Copyright (c) 2007-2014, Marton Anka
|
||||
Portions Copyright (c) 2007, Matt Conover
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
|
||||
+204
-90
@@ -112,9 +112,10 @@ struct MHOOKS_TRAMPOLINE {
|
||||
// in the original location
|
||||
BYTE codeUntouched[MHOOKS_MAX_CODE_BYTES]; // placeholder for unmodified original code
|
||||
// (we patch IP-relative addressing)
|
||||
MHOOKS_TRAMPOLINE* pPrevTrampoline; // When in the free list, thess are pointers to the prev and next entry.
|
||||
MHOOKS_TRAMPOLINE* pNextTrampoline; // When not in the free list, this is a pointer to the prev and next trampoline in use.
|
||||
};
|
||||
|
||||
|
||||
//=========================================================================
|
||||
// The patch data structures - store info about rip-relative instructions
|
||||
// during hook placement
|
||||
@@ -136,27 +137,29 @@ struct MHOOKS_PATCHDATA
|
||||
// Global vars
|
||||
static BOOL g_bVarsInitialized = FALSE;
|
||||
static CRITICAL_SECTION g_cs;
|
||||
static MHOOKS_TRAMPOLINE* g_pHooks[MHOOKS_MAX_SUPPORTED_HOOKS];
|
||||
static MHOOKS_TRAMPOLINE* g_pHooks = NULL;
|
||||
static MHOOKS_TRAMPOLINE* g_pFreeList = NULL;
|
||||
static DWORD g_nHooksInUse = 0;
|
||||
static BOOL g_bThreadsSuspended = FALSE;
|
||||
static HANDLE* g_hThreadHandles = NULL;
|
||||
static DWORD g_nThreadHandles = 0;
|
||||
#define MHOOK_JMPSIZE 5
|
||||
#define MHOOK_MINALLOCSIZE 4096
|
||||
|
||||
//=========================================================================
|
||||
// Toolhelp defintions so the functions can be dynamically bound to
|
||||
typedef HANDLE (WINAPI * _CreateToolhelp32Snapshot)(
|
||||
DWORD dwFlags,
|
||||
DWORD dwFlags,
|
||||
DWORD th32ProcessID
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI * _Thread32First)(
|
||||
HANDLE hSnapshot,
|
||||
HANDLE hSnapshot,
|
||||
LPTHREADENTRY32 lpte
|
||||
);
|
||||
|
||||
typedef BOOL (WINAPI * _Thread32Next)(
|
||||
HANDLE hSnapshot,
|
||||
HANDLE hSnapshot,
|
||||
LPTHREADENTRY32 lpte
|
||||
);
|
||||
|
||||
@@ -166,11 +169,48 @@ _CreateToolhelp32Snapshot fnCreateToolhelp32Snapshot = (_CreateToolhelp32Snapsho
|
||||
_Thread32First fnThread32First = (_Thread32First) GetProcAddress(GetModuleHandle(L"kernel32"), "Thread32First");
|
||||
_Thread32Next fnThread32Next = (_Thread32Next) GetProcAddress(GetModuleHandle(L"kernel32"), "Thread32Next");
|
||||
|
||||
//=========================================================================
|
||||
// Internal function:
|
||||
//
|
||||
// Remove the trampoline from the specified list, updating the head pointer
|
||||
// if necessary.
|
||||
//=========================================================================
|
||||
static VOID ListRemove(MHOOKS_TRAMPOLINE** pListHead, MHOOKS_TRAMPOLINE* pNode) {
|
||||
if (pNode->pPrevTrampoline) {
|
||||
pNode->pPrevTrampoline->pNextTrampoline = pNode->pNextTrampoline;
|
||||
}
|
||||
|
||||
if (pNode->pNextTrampoline) {
|
||||
pNode->pNextTrampoline->pPrevTrampoline = pNode->pPrevTrampoline;
|
||||
}
|
||||
|
||||
if ((*pListHead) == pNode) {
|
||||
(*pListHead) = pNode->pNextTrampoline;
|
||||
assert((*pListHead)->pPrevTrampoline == NULL);
|
||||
}
|
||||
|
||||
pNode->pPrevTrampoline = NULL;
|
||||
pNode->pNextTrampoline = NULL;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Internal function:
|
||||
//
|
||||
// Prepend the trampoline from the specified list and update the head pointer.
|
||||
//=========================================================================
|
||||
static VOID ListPrepend(MHOOKS_TRAMPOLINE** pListHead, MHOOKS_TRAMPOLINE* pNode) {
|
||||
pNode->pPrevTrampoline = NULL;
|
||||
pNode->pNextTrampoline = (*pListHead);
|
||||
if ((*pListHead)) {
|
||||
(*pListHead)->pPrevTrampoline = pNode;
|
||||
}
|
||||
(*pListHead) = pNode;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
static VOID EnterCritSec() {
|
||||
if (!g_bVarsInitialized) {
|
||||
InitializeCriticalSection(&g_cs);
|
||||
ZeroMemory(g_pHooks, sizeof(g_pHooks));
|
||||
g_bVarsInitialized = TRUE;
|
||||
}
|
||||
EnterCriticalSection(&g_cs);
|
||||
@@ -188,7 +228,17 @@ static VOID LeaveCritSec() {
|
||||
// jump tables, etc.
|
||||
//=========================================================================
|
||||
static PBYTE SkipJumps(PBYTE pbCode) {
|
||||
PBYTE pbOrgCode = pbCode;
|
||||
#ifdef _M_IX86_X64
|
||||
#ifdef _M_IX86
|
||||
//mov edi,edi: hot patch point
|
||||
if (pbCode[0] == 0x8b && pbCode[1] == 0xff)
|
||||
pbCode += 2;
|
||||
// push ebp; mov ebp, esp; pop ebp;
|
||||
// "collapsed" stackframe generated by MSVC
|
||||
if (pbCode[0] == 0x55 && pbCode[1] == 0x8b && pbCode[2] == 0xec && pbCode[3] == 0x5d)
|
||||
pbCode += 4;
|
||||
#endif
|
||||
if (pbCode[0] == 0xff && pbCode[1] == 0x25) {
|
||||
#ifdef _M_IX86
|
||||
// on x86 we have an absolute pointer...
|
||||
@@ -200,6 +250,11 @@ static PBYTE SkipJumps(PBYTE pbCode) {
|
||||
INT32 lOffset = *(INT32 *)&pbCode[2];
|
||||
// ... that shows us an absolute pointer
|
||||
return SkipJumps(*(PBYTE*)(pbCode + 6 + lOffset));
|
||||
} else if (pbCode[0] == 0x48 && pbCode[1] == 0xff && pbCode[2] == 0x25) {
|
||||
// or we can have the same with a REX prefix
|
||||
INT32 lOffset = *(INT32 *)&pbCode[3];
|
||||
// ... that shows us an absolute pointer
|
||||
return SkipJumps(*(PBYTE*)(pbCode + 7 + lOffset));
|
||||
#endif
|
||||
} else if (pbCode[0] == 0xe9) {
|
||||
// here the behavior is identical, we have...
|
||||
@@ -212,7 +267,7 @@ static PBYTE SkipJumps(PBYTE pbCode) {
|
||||
#else
|
||||
#error unsupported platform
|
||||
#endif
|
||||
return pbCode;
|
||||
return pbOrgCode;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
@@ -253,6 +308,95 @@ static PBYTE EmitJump(PBYTE pbCode, PBYTE pbJumpTo) {
|
||||
return pbCode;
|
||||
}
|
||||
|
||||
|
||||
//=========================================================================
|
||||
// Internal function:
|
||||
//
|
||||
// Round down to the next multiple of rndDown
|
||||
//=========================================================================
|
||||
static size_t RoundDown(size_t addr, size_t rndDown)
|
||||
{
|
||||
return (addr / rndDown) * rndDown;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Internal function:
|
||||
//
|
||||
// Will attempt allocate a block of memory within the specified range, as
|
||||
// near as possible to the specified function.
|
||||
//=========================================================================
|
||||
static MHOOKS_TRAMPOLINE* BlockAlloc(PBYTE pSystemFunction, PBYTE pbLower, PBYTE pbUpper) {
|
||||
SYSTEM_INFO sSysInfo = {0};
|
||||
::GetSystemInfo(&sSysInfo);
|
||||
|
||||
// Always allocate in bulk, in case the system actually has a smaller allocation granularity than MINALLOCSIZE.
|
||||
const ptrdiff_t cAllocSize = max(sSysInfo.dwAllocationGranularity, MHOOK_MINALLOCSIZE);
|
||||
|
||||
MHOOKS_TRAMPOLINE* pRetVal = NULL;
|
||||
PBYTE pModuleGuess = (PBYTE) RoundDown((size_t)pSystemFunction, cAllocSize);
|
||||
int loopCount = 0;
|
||||
for (PBYTE pbAlloc = pModuleGuess; pbLower < pbAlloc && pbAlloc < pbUpper; ++loopCount) {
|
||||
// determine current state
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
ODPRINTF((L"mhooks: BlockAlloc: Looking at address %p", pbAlloc));
|
||||
if (!VirtualQuery(pbAlloc, &mbi, sizeof(mbi)))
|
||||
break;
|
||||
// free & large enough?
|
||||
if (mbi.State == MEM_FREE && mbi.RegionSize >= (unsigned)cAllocSize) {
|
||||
// and then try to allocate it
|
||||
pRetVal = (MHOOKS_TRAMPOLINE*) VirtualAlloc(pbAlloc, cAllocSize, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
||||
if (pRetVal) {
|
||||
size_t trampolineCount = cAllocSize / sizeof(MHOOKS_TRAMPOLINE);
|
||||
ODPRINTF((L"mhooks: BlockAlloc: Allocated block at %p as %d trampolines", pRetVal, trampolineCount));
|
||||
|
||||
pRetVal[0].pPrevTrampoline = NULL;
|
||||
pRetVal[0].pNextTrampoline = &pRetVal[1];
|
||||
|
||||
// prepare them by having them point down the line at the next entry.
|
||||
for (size_t s = 1; s < trampolineCount; ++s) {
|
||||
pRetVal[s].pPrevTrampoline = &pRetVal[s - 1];
|
||||
pRetVal[s].pNextTrampoline = &pRetVal[s + 1];
|
||||
}
|
||||
|
||||
// last entry points to the current head of the free list
|
||||
pRetVal[trampolineCount - 1].pNextTrampoline = g_pFreeList;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// This is a spiral, should be -1, 1, -2, 2, -3, 3, etc. (* cAllocSize)
|
||||
ptrdiff_t bytesToOffset = (cAllocSize * (loopCount + 1) * ((loopCount % 2 == 0) ? -1 : 1));
|
||||
pbAlloc = pbAlloc + bytesToOffset;
|
||||
}
|
||||
|
||||
return pRetVal;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Internal function:
|
||||
//
|
||||
// Will try to allocate a big block of memory inside the required range.
|
||||
//=========================================================================
|
||||
static MHOOKS_TRAMPOLINE* FindTrampolineInRange(PBYTE pLower, PBYTE pUpper) {
|
||||
if (!g_pFreeList) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// This is a standard free list, except we're doubly linked to deal with soem return shenanigans.
|
||||
MHOOKS_TRAMPOLINE* curEntry = g_pFreeList;
|
||||
while (curEntry) {
|
||||
if ((MHOOKS_TRAMPOLINE*) pLower < curEntry && curEntry < (MHOOKS_TRAMPOLINE*) pUpper) {
|
||||
ListRemove(&g_pFreeList, curEntry);
|
||||
|
||||
return curEntry;
|
||||
}
|
||||
|
||||
curEntry = curEntry->pNextTrampoline;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// Internal function:
|
||||
//
|
||||
@@ -263,56 +407,29 @@ static MHOOKS_TRAMPOLINE* TrampolineAlloc(PBYTE pSystemFunction, S64 nLimitUp, S
|
||||
|
||||
MHOOKS_TRAMPOLINE* pTrampoline = NULL;
|
||||
|
||||
// do we have room to store this guy?
|
||||
if (g_nHooksInUse < MHOOKS_MAX_SUPPORTED_HOOKS) {
|
||||
// determine lower and upper bounds for the allocation locations.
|
||||
// in the basic scenario this is +/- 2GB but IP-relative instructions
|
||||
// found in the original code may require a smaller window.
|
||||
PBYTE pLower = pSystemFunction + nLimitUp;
|
||||
pLower = pLower < (PBYTE)(DWORD_PTR)0x0000000080000000 ?
|
||||
(PBYTE)(0x1) : (PBYTE)(pLower - (PBYTE)0x7fff0000);
|
||||
PBYTE pUpper = pSystemFunction + nLimitDown;
|
||||
pUpper = pUpper < (PBYTE)(DWORD_PTR)0xffffffff80000000 ?
|
||||
(PBYTE)(pUpper + (DWORD_PTR)0x7ff80000) : (PBYTE)(DWORD_PTR)0xfffffffffff80000;
|
||||
ODPRINTF((L"mhooks: TrampolineAlloc: Allocating for %p between %p and %p", pSystemFunction, pLower, pUpper));
|
||||
|
||||
// determine lower and upper bounds for the allocation locations.
|
||||
// in the basic scenario this is +/- 2GB but IP-relative instructions
|
||||
// found in the original code may require a smaller window.
|
||||
PBYTE pLower = pSystemFunction + nLimitUp;
|
||||
pLower = pLower < (PBYTE)(DWORD_PTR)0x0000000080000000 ?
|
||||
(PBYTE)(0x1) : (PBYTE)(pLower - (PBYTE)0x7fff0000);
|
||||
PBYTE pUpper = pSystemFunction + nLimitDown;
|
||||
pUpper = pUpper < (PBYTE)(DWORD_PTR)0xffffffff80000000 ?
|
||||
(PBYTE)(pUpper + (DWORD_PTR)0x7ff80000) : (PBYTE)(DWORD_PTR)0xfffffffffff80000;
|
||||
ODPRINTF((L"mhooks: TrampolineAlloc: Allocating for %p between %p and %p", pSystemFunction, pLower, pUpper));
|
||||
// try to find a trampoline in the specified range
|
||||
pTrampoline = FindTrampolineInRange(pLower, pUpper);
|
||||
if (!pTrampoline) {
|
||||
// if it we can't find it, then we need to allocate a new block and
|
||||
// try again. Just fail if that doesn't work
|
||||
g_pFreeList = BlockAlloc(pSystemFunction, pLower, pUpper);
|
||||
pTrampoline = FindTrampolineInRange(pLower, pUpper);
|
||||
}
|
||||
|
||||
SYSTEM_INFO sSysInfo = {0};
|
||||
::GetSystemInfo(&sSysInfo);
|
||||
|
||||
// go through the available memory blocks and try to allocate a chunk for us
|
||||
for (PBYTE pbAlloc = pLower; pbAlloc < pUpper;) {
|
||||
// determine current state
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
ODPRINTF((L"mhooks: TrampolineAlloc: Looking at address %p", pbAlloc));
|
||||
if (!VirtualQuery(pbAlloc, &mbi, sizeof(mbi)))
|
||||
break;
|
||||
// free & large enough?
|
||||
if (mbi.State == MEM_FREE && mbi.RegionSize >= sizeof(MHOOKS_TRAMPOLINE) && mbi.RegionSize >= sSysInfo.dwAllocationGranularity) {
|
||||
// yes, align the pointer to the 64K boundary first
|
||||
pbAlloc = (PBYTE)(ULONG_PTR((ULONG_PTR(pbAlloc) + (sSysInfo.dwAllocationGranularity-1)) / sSysInfo.dwAllocationGranularity) * sSysInfo.dwAllocationGranularity);
|
||||
// and then try to allocate it
|
||||
pTrampoline = (MHOOKS_TRAMPOLINE*)VirtualAlloc(pbAlloc, sizeof(MHOOKS_TRAMPOLINE), MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READ);
|
||||
if (pTrampoline) {
|
||||
ODPRINTF((L"mhooks: TrampolineAlloc: Allocated block at %p as the trampoline", pTrampoline));
|
||||
break;
|
||||
}
|
||||
}
|
||||
// continue the search
|
||||
pbAlloc = (PBYTE)mbi.BaseAddress + mbi.RegionSize;
|
||||
}
|
||||
|
||||
// found and allocated a trampoline?
|
||||
if (pTrampoline) {
|
||||
// put it into our list so we know we'll have to free it
|
||||
for (DWORD i=0; i<MHOOKS_MAX_SUPPORTED_HOOKS; i++) {
|
||||
if (g_pHooks[i] == NULL) {
|
||||
g_pHooks[i] = pTrampoline;
|
||||
g_nHooksInUse++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// found and allocated a trampoline?
|
||||
if (pTrampoline) {
|
||||
ListPrepend(&g_pHooks, pTrampoline);
|
||||
}
|
||||
|
||||
return pTrampoline;
|
||||
@@ -324,12 +441,16 @@ static MHOOKS_TRAMPOLINE* TrampolineAlloc(PBYTE pSystemFunction, S64 nLimitUp, S
|
||||
// Return the internal trampoline structure that belongs to a hooked function.
|
||||
//=========================================================================
|
||||
static MHOOKS_TRAMPOLINE* TrampolineGet(PBYTE pHookedFunction) {
|
||||
for (DWORD i=0; i<MHOOKS_MAX_SUPPORTED_HOOKS; i++) {
|
||||
if (g_pHooks[i]) {
|
||||
if (g_pHooks[i]->codeTrampoline == pHookedFunction)
|
||||
return g_pHooks[i];
|
||||
MHOOKS_TRAMPOLINE* pCurrent = g_pHooks;
|
||||
|
||||
while (pCurrent) {
|
||||
if (pCurrent->pHookFunction == pHookedFunction) {
|
||||
return pCurrent;
|
||||
}
|
||||
|
||||
pCurrent = pCurrent->pNextTrampoline;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -339,20 +460,17 @@ static MHOOKS_TRAMPOLINE* TrampolineGet(PBYTE pHookedFunction) {
|
||||
// Free a trampoline structure.
|
||||
//=========================================================================
|
||||
static VOID TrampolineFree(MHOOKS_TRAMPOLINE* pTrampoline, BOOL bNeverUsed) {
|
||||
for (DWORD i=0; i<MHOOKS_MAX_SUPPORTED_HOOKS; i++) {
|
||||
if (g_pHooks[i] == pTrampoline) {
|
||||
g_pHooks[i] = NULL;
|
||||
// It might be OK to call VirtualFree, but quite possibly it isn't:
|
||||
// If a thread has some of our trampoline code on its stack
|
||||
// and we yank the region from underneath it then it will
|
||||
// surely crash upon returning. So instead of freeing the
|
||||
// memory we just let it leak. Ugly, but safe.
|
||||
if (bNeverUsed)
|
||||
VirtualFree(pTrampoline, 0, MEM_RELEASE);
|
||||
g_nHooksInUse--;
|
||||
break;
|
||||
}
|
||||
ListRemove(&g_pHooks, pTrampoline);
|
||||
|
||||
// If a thread could feasinbly have some of our trampoline code
|
||||
// on its stack and we yank the region from underneath it then it will
|
||||
// surely crash upon returning. So instead of freeing the
|
||||
// memory we just let it leak. Ugly, but safe.
|
||||
if (bNeverUsed) {
|
||||
ListPrepend(&g_pFreeList, pTrampoline);
|
||||
}
|
||||
|
||||
g_nHooksInUse--;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
@@ -565,7 +683,7 @@ static DWORD DisassembleAndSkip(PVOID pFunction, DWORD dwMinLen, MHOOKS_PATCHDAT
|
||||
|
||||
ODPRINTF((L"mhooks: DisassembleAndSkip: Disassembling %p", pLoc));
|
||||
while ( (dwRet < dwMinLen) && (pins = GetInstruction(&dis, (ULONG_PTR)pLoc, pLoc, dwFlags)) ) {
|
||||
ODPRINTF(("mhooks: DisassembleAndSkip: %p: %s", pLoc, pins->String));
|
||||
ODPRINTF(("mhooks: DisassembleAndSkip: %p:(0x%2.2x) %s", pLoc, pins->Length, pins->String));
|
||||
if (pins->Type == ITYPE_RET ) break;
|
||||
if (pins->Type == ITYPE_BRANCH ) break;
|
||||
if (pins->Type == ITYPE_BRANCHCC) break;
|
||||
@@ -688,15 +806,13 @@ bool Mhook_SetHook(PVOID *ppSystemFunction, PVOID pHookFunction) {
|
||||
pTrampoline = TrampolineAlloc((PBYTE)pSystemFunction, patchdata.nLimitUp, patchdata.nLimitDown);
|
||||
if (pTrampoline) {
|
||||
ODPRINTF((L"mhooks: Mhook_SetHook: allocated structure at %p", pTrampoline));
|
||||
// open ourselves so we can VirtualProtectEx
|
||||
HANDLE hProc = GetCurrentProcess();
|
||||
DWORD dwOldProtectSystemFunction = 0;
|
||||
DWORD dwOldProtectTrampolineFunction = 0;
|
||||
// set the system function to PAGE_EXECUTE_READWRITE
|
||||
if (VirtualProtectEx(hProc, pSystemFunction, dwInstructionLength, PAGE_EXECUTE_READWRITE, &dwOldProtectSystemFunction)) {
|
||||
if (VirtualProtect(pSystemFunction, dwInstructionLength, PAGE_EXECUTE_READWRITE, &dwOldProtectSystemFunction)) {
|
||||
ODPRINTF((L"mhooks: Mhook_SetHook: readwrite set on system function"));
|
||||
// mark our trampoline buffer to PAGE_EXECUTE_READWRITE
|
||||
if (VirtualProtectEx(hProc, pTrampoline, sizeof(MHOOKS_TRAMPOLINE), PAGE_EXECUTE_READWRITE, &dwOldProtectTrampolineFunction)) {
|
||||
if (VirtualProtect(pTrampoline, sizeof(MHOOKS_TRAMPOLINE), PAGE_EXECUTE_READWRITE, &dwOldProtectTrampolineFunction)) {
|
||||
ODPRINTF((L"mhooks: Mhook_SetHook: readwrite set on trampoline structure"));
|
||||
|
||||
// create our trampoline function
|
||||
@@ -728,7 +844,7 @@ bool Mhook_SetHook(PVOID *ppSystemFunction, PVOID pHookFunction) {
|
||||
pbCode = pTrampoline->codeJumpToHookFunction;
|
||||
pbCode = EmitJump(pbCode, (PBYTE)pHookFunction);
|
||||
ODPRINTF((L"mhooks: Mhook_SetHook: created reverse trampoline"));
|
||||
FlushInstructionCache(hProc, pTrampoline->codeJumpToHookFunction,
|
||||
FlushInstructionCache(GetCurrentProcess(), pTrampoline->codeJumpToHookFunction,
|
||||
pbCode - pTrampoline->codeJumpToHookFunction);
|
||||
|
||||
// update the API itself
|
||||
@@ -747,16 +863,16 @@ bool Mhook_SetHook(PVOID *ppSystemFunction, PVOID pHookFunction) {
|
||||
pTrampoline->pHookFunction = (PBYTE)pHookFunction;
|
||||
|
||||
// flush instruction cache and restore original protection
|
||||
FlushInstructionCache(hProc, pTrampoline->codeTrampoline, dwInstructionLength);
|
||||
VirtualProtectEx(hProc, pTrampoline, sizeof(MHOOKS_TRAMPOLINE), dwOldProtectTrampolineFunction, &dwOldProtectTrampolineFunction);
|
||||
FlushInstructionCache(GetCurrentProcess(), pTrampoline->codeTrampoline, dwInstructionLength);
|
||||
VirtualProtect(pTrampoline, sizeof(MHOOKS_TRAMPOLINE), dwOldProtectTrampolineFunction, &dwOldProtectTrampolineFunction);
|
||||
} else {
|
||||
ODPRINTF((L"mhooks: Mhook_SetHook: failed VirtualProtectEx 2: %d", gle()));
|
||||
ODPRINTF((L"mhooks: Mhook_SetHook: failed VirtualProtect 2: %d", gle()));
|
||||
}
|
||||
// flush instruction cache and restore original protection
|
||||
FlushInstructionCache(hProc, pSystemFunction, dwInstructionLength);
|
||||
VirtualProtectEx(hProc, pSystemFunction, dwInstructionLength, dwOldProtectSystemFunction, &dwOldProtectSystemFunction);
|
||||
FlushInstructionCache(GetCurrentProcess(), pSystemFunction, dwInstructionLength);
|
||||
VirtualProtect(pSystemFunction, dwInstructionLength, dwOldProtectSystemFunction, &dwOldProtectSystemFunction);
|
||||
} else {
|
||||
ODPRINTF((L"mhooks: Mhook_SetHook: failed VirtualProtectEx 1: %d", gle()));
|
||||
ODPRINTF((L"mhooks: Mhook_SetHook: failed VirtualProtect 1: %d", gle()));
|
||||
}
|
||||
if (pTrampoline->pSystemFunction) {
|
||||
// this is what the application will use as the entry point
|
||||
@@ -789,19 +905,17 @@ bool Mhook_Unhook(PVOID *ppHookedFunction) {
|
||||
// make sure nobody's executing code where we're about to overwrite a few bytes
|
||||
SuspendOtherThreads(pTrampoline->pSystemFunction, pTrampoline->cbOverwrittenCode);
|
||||
ODPRINTF((L"mhooks: Mhook_Unhook: found struct at %p", pTrampoline));
|
||||
// open ourselves so we can VirtualProtectEx
|
||||
HANDLE hProc = GetCurrentProcess();
|
||||
DWORD dwOldProtectSystemFunction = 0;
|
||||
// make memory writable
|
||||
if (VirtualProtectEx(hProc, pTrampoline->pSystemFunction, pTrampoline->cbOverwrittenCode, PAGE_EXECUTE_READWRITE, &dwOldProtectSystemFunction)) {
|
||||
if (VirtualProtect(pTrampoline->pSystemFunction, pTrampoline->cbOverwrittenCode, PAGE_EXECUTE_READWRITE, &dwOldProtectSystemFunction)) {
|
||||
ODPRINTF((L"mhooks: Mhook_Unhook: readwrite set on system function"));
|
||||
PBYTE pbCode = (PBYTE)pTrampoline->pSystemFunction;
|
||||
for (DWORD i = 0; i<pTrampoline->cbOverwrittenCode; i++) {
|
||||
pbCode[i] = pTrampoline->codeUntouched[i];
|
||||
}
|
||||
// flush instruction cache and make memory unwritable
|
||||
FlushInstructionCache(hProc, pTrampoline->pSystemFunction, pTrampoline->cbOverwrittenCode);
|
||||
VirtualProtectEx(hProc, pTrampoline->pSystemFunction, pTrampoline->cbOverwrittenCode, dwOldProtectSystemFunction, &dwOldProtectSystemFunction);
|
||||
FlushInstructionCache(GetCurrentProcess(), pTrampoline->pSystemFunction, pTrampoline->cbOverwrittenCode);
|
||||
VirtualProtect(pTrampoline->pSystemFunction, pTrampoline->cbOverwrittenCode, dwOldProtectSystemFunction, &dwOldProtectSystemFunction);
|
||||
// return the original function pointer
|
||||
*ppHookedFunction = pTrampoline->pSystemFunction;
|
||||
bRet = true;
|
||||
@@ -810,7 +924,7 @@ bool Mhook_Unhook(PVOID *ppHookedFunction) {
|
||||
TrampolineFree(pTrampoline, FALSE);
|
||||
ODPRINTF((L"mhooks: Mhook_Unhook: unhook successful"));
|
||||
} else {
|
||||
ODPRINTF((L"mhooks: Mhook_Unhook: failed VirtualProtectEx 1: %d", gle()));
|
||||
ODPRINTF((L"mhooks: Mhook_Unhook: failed VirtualProtect 1: %d", gle()));
|
||||
}
|
||||
// make the other guys runnable
|
||||
ResumeOtherThreads();
|
||||
|
||||
-2
@@ -38,5 +38,3 @@ bool Mhook_Unhook(void **ppHookedFunction);
|
||||
void Mhook_SuspendOtherThreads();
|
||||
void Mhook_ResumeOtherThreads();
|
||||
|
||||
#define MHOOKS_MAX_SUPPORTED_HOOKS 512
|
||||
|
||||
|
||||
Reference in New Issue
Block a user