mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Fixed hooking of functions using call instruction with relative addressing
See issue #149.
This commit is contained in:
parent
19899f81c9
commit
b35fddad24
@ -186,33 +186,42 @@ namespace
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned totalInstructionSize = 0;
|
const DWORD trampolineSize = 32;
|
||||||
while (totalInstructionSize < 5)
|
BYTE* trampoline = static_cast<BYTE*>(
|
||||||
|
VirtualAlloc(nullptr, trampolineSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE));
|
||||||
|
BYTE* src = targetFunc;
|
||||||
|
BYTE* dst = trampoline;
|
||||||
|
while (src - targetFunc < 5)
|
||||||
{
|
{
|
||||||
unsigned instructionSize = getInstructionSize(targetFunc + totalInstructionSize);
|
unsigned instructionSize = getInstructionSize(src);
|
||||||
if (0 == instructionSize)
|
if (0 == instructionSize)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
totalInstructionSize += instructionSize;
|
|
||||||
|
memcpy(dst, src, instructionSize);
|
||||||
|
if (0xE8 == *src && 5 == instructionSize)
|
||||||
|
{
|
||||||
|
*reinterpret_cast<int*>(dst + 1) += src - dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
src += instructionSize;
|
||||||
|
dst += instructionSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DEBUG << "Hooking function: " << funcName
|
LOG_DEBUG << "Hooking function: " << funcName
|
||||||
<< " (" << oss.str() << Compat::hexDump(targetFunc, totalInstructionSize) << ')';
|
<< " (" << oss.str() << Compat::hexDump(targetFunc, src - targetFunc) << ')';
|
||||||
|
|
||||||
BYTE* trampoline = static_cast<BYTE*>(
|
*dst = 0xE9;
|
||||||
VirtualAlloc(nullptr, totalInstructionSize + 5, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE));
|
*reinterpret_cast<int*>(dst + 1) = src - (dst + 5);
|
||||||
memcpy(trampoline, targetFunc, totalInstructionSize);
|
|
||||||
trampoline[totalInstructionSize] = 0xE9;
|
|
||||||
reinterpret_cast<int&>(trampoline[totalInstructionSize + 1]) = targetFunc - (trampoline + 5);
|
|
||||||
DWORD oldProtect = 0;
|
DWORD oldProtect = 0;
|
||||||
VirtualProtect(trampoline, totalInstructionSize + 5, PAGE_EXECUTE_READ, &oldProtect);
|
VirtualProtect(trampoline, trampolineSize, PAGE_EXECUTE_READ, &oldProtect);
|
||||||
|
|
||||||
VirtualProtect(targetFunc, totalInstructionSize, PAGE_EXECUTE_READWRITE, &oldProtect);
|
VirtualProtect(targetFunc, src - targetFunc, PAGE_EXECUTE_READWRITE, &oldProtect);
|
||||||
targetFunc[0] = 0xE9;
|
targetFunc[0] = 0xE9;
|
||||||
reinterpret_cast<int&>(targetFunc[1]) = static_cast<BYTE*>(newFuncPtr) - (targetFunc + 5);
|
*reinterpret_cast<int*>(targetFunc + 1) = static_cast<BYTE*>(newFuncPtr) - (targetFunc + 5);
|
||||||
memset(targetFunc + 5, 0xCC, totalInstructionSize - 5);
|
memset(targetFunc + 5, 0xCC, src - targetFunc - 5);
|
||||||
VirtualProtect(targetFunc, totalInstructionSize, PAGE_EXECUTE_READ, &oldProtect);
|
VirtualProtect(targetFunc, src - targetFunc, PAGE_EXECUTE_READ, &oldProtect);
|
||||||
|
|
||||||
FlushInstructionCache(GetCurrentProcess(), nullptr, 0);
|
FlushInstructionCache(GetCurrentProcess(), nullptr, 0);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user