如何在运行时修补Windows API以使其在x64中返回0?

时间:2010-06-09 23:06:42

标签: winapi assembly 64-bit hook patch

在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

2 个答案:

答案 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 DetoursEasyHook这样的库,这两个库都支持这种修补方式,其中一个至少可以在x64中使用。