热修补功能

时间:2011-11-11 05:00:25

标签: c winapi assembly reverse-engineering

我正在尝试在内存中对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,我希望调用它而不是原始函数。我还没写过蹦床,所以它崩溃了(正如预期的那样)。但是,我没有弹出消息框,因为我已将原始VM创建到我自己的。我相信这是我覆盖原始指令的方式。

1 个答案:

答案 0 :(得分:4)

我可以看到一些问题。

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

偏移计算错误。你的标志有误。更多的偏移应用于指令的 end 处的指令指针而不是开头。所以你需要将它移动5(指令的大小)。偏移量也应该是有符号整数。

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

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

感谢Hans Passant在原始版本中修复了我自己的愚蠢标志错误!

如果您正在使用64位机器,则需要以64位进行算术运算,一旦计算出偏移量,就将其截断为32位偏移量。

另一个细微差别是你应该在写完新的JMP指令后将内存重置为只读,然后调用FlushInstructionCache