我正在尝试获取__declspec(naked)
函数的原始字节,但是memcpy
返回的是我不期望的字节。
我已使用调试器检查字节/地址。一切看起来都很好,但是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调试器中,我在中间窗口中执行了
&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]
为什么我没有得到我期望的字节?
答案 0 :(得分:3)
您正在观察的原因是由于MSVC的“调试模式”中的incremental linking。 widget_click_fix_asm
的地址实际上不是函数本身,而是JMP Thunk Table中JMP指令的地址。该表用于将功能的新版本修补到现有的可执行文件中。这是通过在具有足够空间的可执行文件的可用区域中写入新功能,然后用新地址更新JMP thunk表来完成的。这有助于Visual Studio中的编辑和继续调试功能。
在您的示例中,对memcpy
的调用最终将JMP Thunk表的一部分复制到了buf
而不是函数本身。您不妨考虑关闭增量链接功能,以获取所需的行为。