热补丁功能
我正在尝试对内存中的 exe 进行热修补,源代码可用,但我这样做是为了学习目的。 (所以请不要发表评论建议我修改原始源或使用弯路或任何其他库)
以下是我遇到问题的功能。
vm_t* VM_Create( const char *module, intptr_t (*systemCalls)(intptr_t *), vmInterpret_t interpret )
{
MessageBox(NULL, L"Oh snap! We hooked VM_Create!", L"Success!", MB_OK);
return NULL;
}
void Hook_VM_Create(void)
{
DWORD dwBackup;
VirtualProtect((void*)0x00477C3E, 7, PAGE_EXECUTE_READWRITE, &dwBackup);
//Patch the original VM_Create to jump to our detoured one.
BYTE *jmp = (BYTE*)malloc(5);
uint32_t offset = 0x00477C3E - (uint32_t)&VM_Create; //find the offset of the original function from our own
memset((void*)jmp, 0xE9, 1);
memcpy((void*)(jmp+1), &offset, sizeof(offset));
memcpy((void*)0x00477C3E, jmp, 5);
free(jmp);
}
我有一个函数 VM_Create 我想调用它而不是原始函数。我还没有写一个蹦床,所以它崩溃了(如预期的那样)。但是,不会弹出消息框,表明我已将原始虚拟机创建绕道为我自己的虚拟机创建。我相信这是我覆盖原始指令的方式。
I'm trying to hot patch an exe in memory, the source is available but I'm doing this for learning purposes. (so please no comments suggesting i modify the original source or use detours or any other libs)
Below are the functions I am having problems with.
vm_t* VM_Create( const char *module, intptr_t (*systemCalls)(intptr_t *), vmInterpret_t interpret )
{
MessageBox(NULL, L"Oh snap! We hooked VM_Create!", L"Success!", MB_OK);
return NULL;
}
void Hook_VM_Create(void)
{
DWORD dwBackup;
VirtualProtect((void*)0x00477C3E, 7, PAGE_EXECUTE_READWRITE, &dwBackup);
//Patch the original VM_Create to jump to our detoured one.
BYTE *jmp = (BYTE*)malloc(5);
uint32_t offset = 0x00477C3E - (uint32_t)&VM_Create; //find the offset of the original function from our own
memset((void*)jmp, 0xE9, 1);
memcpy((void*)(jmp+1), &offset, sizeof(offset));
memcpy((void*)0x00477C3E, jmp, 5);
free(jmp);
}
I have a function VM_Create that I want to be called instead of the original function. I have not yet written a trampoline so it crashes (as expected). However the message box does not popup that I have detoured the original VM create to my own. I believe it is the way I'm overwriting the original instructions.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我可以看到一些问题。
我假设
0x00477C3E
是原始VM_Create
函数的地址。你真的不应该对此进行硬编码。请改用&VM_Create
。当然,这意味着您需要为替换函数使用不同的名称。偏移量计算不正确。你把标志弄错了。更重要的是,偏移量应用于指令末尾的指令指针,而不是开头。所以你需要将其移位 5(指令的大小)。偏移量也应该是有符号整数。
理想情况下,如果您考虑到我的第一点,代码将如下所示:
感谢 Hans Passant 修复了我自己在原始版本中愚蠢的符号错误!
如果您在 64 位机器上工作,则需要以 64 位进行算术,并且计算出偏移量后,将其截断为 32 位偏移量。
另一个细微差别是,您应该在写入新的 JMP 指令后将内存重置为只读,并调用
FlushInstructionCache
。I can see a few issues.
I assume that
0x00477C3E
is the address of the originalVM_Create
function. You really should not hard code this. Use&VM_Create
instead. Of course this will mean that you need to use a different name for your replacement function.The offset is calculated incorrectly. You have the sign wrong. What's more the offset is applied to the instruction pointer at the end of the instruction and not the beginning. So you need to shift it by 5 (the size of the instruction). The offset should be a signed integer also.
Ideally, if you take into account my first point the code would look like this:
Thanks to Hans Passant for fixing my own silly sign error in the original version!
If you are working on a 64 bit machine you need to do your arithmetic in 64 bits and, once you have calculated the offset, truncate it to a 32 bit offset.
Another nuance is that you should reset the memory to being read-only after having written the new
JMP
instruction, and callFlushInstructionCache
.