在x86中,我使用GetProcAddress()
获取函数地址,并在其中编写一个简单的XOR EAX,EAX; RET 4;
。简单有效。如何在x64中执行相同操作?
bool DisableSetUnhandledExceptionFilter()
{
const BYTE PatchBytes[5] = { 0x33, 0xC0, 0xC2, 0x04, 0x00 }; // XOR EAX,EAX; RET 4;
// Obtain the address of SetUnhandledExceptionFilter
HMODULE hLib = GetModuleHandle( _T("kernel32.dll") );
if( hLib == NULL )
return false;
BYTE* pTarget = (BYTE*)GetProcAddress( hLib, "SetUnhandledExceptionFilter" );
if( pTarget == 0 )
return false;
// Patch SetUnhandledExceptionFilter
if( !WriteMemory( pTarget, PatchBytes, sizeof(PatchBytes) ) )
return false;
// Ensures out of cache
FlushInstructionCache(GetCurrentProcess(), pTarget, sizeof(PatchBytes));
// Success
return true;
}
static bool WriteMemory( BYTE* pTarget, const BYTE* pSource, DWORD Size )
{
// Check parameters
if( pTarget == 0 )
return false;
if( pSource == 0 )
return false;
if( Size == 0 )
return false;
if( IsBadReadPtr( pSource, Size ) )
return false;
// Modify protection attributes of the target memory page
DWORD OldProtect = 0;
if( !VirtualProtect( pTarget, Size, PAGE_EXECUTE_READWRITE, &OldProtect ) )
return false;
// Write memory
memcpy( pTarget, pSource, Size );
// Restore memory protection attributes of the target memory page
DWORD Temp = 0;
if( !VirtualProtect( pTarget, Size, OldProtect, &Temp ) )
return false;
// Success
return true;
}
此示例改编自以下代码:http://www.debuginfo.com/articles/debugfilters.html#overwrite。
最佳答案
在x64中,返回值在RAX中,这是EAX的64位版本。但是,由于在写入32位子寄存器时会清除高32位,因此“xor eax,eax”等效于“xor rax,rax”,无需更改。
但是,由于x64上的调用约定不同,因此相同的返回指令在此处不起作用:
在x86 winapi函数中,使用stdcall约定,在该约定中,被调用者从堆栈中弹出参数(因此,“retn 4”指令将SetUnhandledExceptionFilter中的一个参数从堆栈中弹出(您可能要在代码中修复该注释)) 。
在x64中,被调用者不会清除堆栈,因此需要使用常规的“retn”指令:
const BYTE PatchBytes[3] = { 0x33, 0xC0, 0xC3 }; // XOR EAX,EAX; RET;
关于winapi - 如何在运行时修补Windows API,以使其在x64中返回0?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3010626/