在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。
答案 0 :(得分:2)
在x64中,返回值在RAX中,即64位版本的EAX。但由于在写入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;
答案 1 :(得分:0)
使用像Microsoft Detours或EasyHook这样的库,这两个库都支持这种修补方式,其中一个至少可以在x64中使用。