Pregunta

I'm learning how to hotpatch functions and I have the following code which works fine in 32-bit programs. However, I'm trying to get it to work in 64-bit programs as well but it just crashes.

#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);
}

Any ideas what is wrong with the code?

¿Fue útil?

Solución

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*));

For your x86-64 instructions, the address to jump to, the 0x0000000000000000 in your jmp array, starts at the third byte, not at the second. You're overwriting part of the mov instruction, and what you end up with is an invalid instruction if you're lucky.

As a side note, I'm doubtful it's safe to just overwrite %eax/%rax like that. Have you determined that those registers will never contain any values of interest?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top