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

发布于 2024-09-04 19:51:11 字数 1677 浏览 10 评论 0原文

在 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

In x86, I get the function address using GetProcAddress() and write a simple XOR EAX,EAX; RET 4; in it. Simple and effective. How do I do the same in 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;
}

This example is adapted from code found here: http://www.debuginfo.com/articles/debugfilters.html#overwrite .

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

风吹短裙飘 2024-09-11 19:51:11

在 x64 中,返回值位于 RAX 中,这是 EAX 的 64 位版本。但由于写入 32 位子寄存器时高 32 位被清除,因此“xor eax, eax”相当于“xor rax, rax”,不需要更改。

但是,由于 x64 上的调用约定不同,因此相同的返回指令在 x64 上不起作用:
在 x86 winapi 函数中,使用 stdcall 约定,其中被调用者从堆栈中弹出参数(因此出现了“retn 4”指令,它将 SetUnhandledExceptionFilter 中的一个参数从堆栈中弹出(您可能希望在代码中修复该注释)) 。
在 x64 中,堆栈不会被被调用者清理,因此需要使用普通的“retn”指令:

const BYTE PatchBytes[3] = { 0x33, 0xC0, 0xC3 }; // XOR EAX,EAX; RET;

In x64 the return value is in RAX, which is the 64bit version of EAX. But because the upper 32 bits are cleared when a 32 bit sub-register is written, "xor eax, eax" is equivalent to "xor rax, rax" and doesn't need to be changed.

However, because the calling convention is different on x64, the same return instruction won't work there:
In x86 winapi functions use the stdcall convention, where the callee pops the arguments from the stack (hence the "retn 4" instruction, which pops that one argument from SetUnhandledExceptionFilter off the stack (you may want to fix that comment in your code)).
In x64 the stack is not cleaned by the callee, so a normal "retn" instruction needs to be used:

const BYTE PatchBytes[3] = { 0x33, 0xC0, 0xC3 }; // XOR EAX,EAX; RET;
带上头具痛哭 2024-09-11 19:51:11

使用 Microsoft DetoursEasyHook,两者都支持这种类型的修补,其中之一至少可以在 x64 上运行。

Use a library like Microsoft Detours or EasyHook, both of which support exactly this kind of patching, and one of which at least works in x64.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文