__declspec 裸 returns 意外字节上的 memcpy

memcpy on __declspec naked returns unexpected bytes

我正在尝试获取 __declspec(naked) 函数的原始字节,但 memcpy 正在返回我不期望的字节。

我已经使用调试器检查 bytes/addresses。一切看起来都很好,但是 memcpy 的结果产生了不同的、看似不变的字节。

void __declspec(naked) widget_click_fix_asm()
{
    __asm {
        nop
        call patched_widget_handler
    }
}

void test_patch()
{
    char buf[7];

    ::memcpy(&buf, &widget_click_fix_asm, 7);
}

在VS调试器中,在中间window我执行了:

&widget_click_fix_asm
0x778816f0

导航到该内存位置显示以下字节:

778816F0 90
778816F1 FF 15 38 91 88 77

我希望 buf 是以下字节的容器:

[0x90, 0xFF, 0x15, 0x38, 0x91, 0x88, 0x77]

而是 buf 我每次测试时都包含以下常量字节:

[0xE9, 0xD8, 0x05, 0x00, 0x00, 0xE9, 0x63]

为什么我没有得到预期的字节数?

您所观察到的是由于 incremental linking in MSVC's Debug Mode. The address of widget_click_fix_asm isn't actually the function itself, but the address of a JMP instruction in the JMP Thunk Table。此 table 用于将新版本的函数修补到现有的 executable 中。这是通过在具有足够 space 的 executable 的空闲区域写入新函数,然后用新地址更新 JMP thunk table 来完成的。这有助于 Visual Studio.

中的编辑和继续调试功能

在您的示例中,您对 memcpy 的调用最终将 JMP Thunk Table 的一部分复制到 buf 而不是函数本身。您可能希望考虑关闭增量链接功能以获得您想要的行为。