x64 MOV,JMP指令崩溃程序

时间:2013-12-19 18:20:55

标签: c++ c++11 inline-assembly hotpatching

我正在学习如何编写函数,我有以下代码可以在32位程序中正常工作。但是,我试图让它在64位程序中工作,但它只是崩溃。

#ifndef __x86_64
std::uint8_t Store[8] = {0};
#else
std::uint8_t Store[15] = {0};
#endif

void Patch(std::uint8_t* OriginalAddress, std::uint8_t* ReplacementAddress)
{
    #ifndef __x86_64
    const static std::uint8_t jmp[] = {0xb8, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0}; /** movl $0x0, %eax ;;; jmp *%eax **/
    #else
    const static std::uint8_t jmp[] = {0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0x90, 0x90}; /** movq $0x0, %rax ;;; jmp *%rax **/
    #endif

    DWORD dwProtect = 0;
    const static std::int8_t jmp_size = sizeof(jmp) / sizeof(std::uint8_t);
    VirtualProtect(OriginalAddress, jmp_size, PAGE_EXECUTE_READWRITE, &dwProtect);
    memcpy(Store, OriginalAddress, jmp_size);
    memcpy(OriginalAddress, jmp, jmp_size);
    memcpy(OriginalAddress + 1, &ReplacementAddress, sizeof(void*));
    VirtualProtect(OriginalAddress, jmp_size, dwProtect, &dwProtect);
}

任何想法代码有什么问题?

1 个答案:

答案 0 :(得分:3)

const static std::uint8_t jmp[] = {0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0x90, 0x90};
     

...

memcpy(OriginalAddress + 1, &ReplacementAddress, sizeof(void*));

对于x86-64指令,跳转到jmp数组中的0x0000000000000000的地址从第三个字节开始,而不是从第二个字节开始。你正在覆盖mov指令的一部分,如果你幸运的话,你最终得到的是无效指令。

作为旁注,我很怀疑像这样覆盖%eax / %rax是安全的。您是否确定这些寄存器永远不会包含任何感兴趣的值?