热补丁功能

发布于 2024-12-15 05:03:26 字数 932 浏览 5 评论 0原文

我正在尝试对内存中的 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 技术交流群。

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

发布评论

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

评论(1

回眸一笑 2024-12-22 05:03:26

我可以看到一些问题。

我假设 0x00477C3E 是原始 VM_Create 函数的地址。你真的不应该对此进行硬编码。请改用 &VM_Create。当然,这意味着您需要为替换函数使用不同的名称。

偏移量计算不正确。你把标志弄错了。更重要的是,偏移量应用于指令末尾的指令指针,而不是开头。所以你需要将其移位 5(指令的大小)。偏移量也应该是有符号整数。

理想情况下,如果您考虑到我的第一点,代码将如下所示:

int32_t offset = (int32_t)&New_VM_Create - ((int32_t)&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 original VM_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:

int32_t offset = (int32_t)&New_VM_Create - ((int32_t)&VM_Create+5);

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 call FlushInstructionCache.

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