x64 MOV, JMP инструкция вылетает программа

Я учусь, как исправлять функции, и у меня есть следующий код, который отлично работает в 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 ответ

Решение
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, адрес для перехода, 0x0000000000000000 в вашем jmp массив, начинается с третьего байта, а не со второго. Вы перезаписываете часть mov инструкция, и то, что вы в конечном итоге, является неверной инструкцией, если вам повезет.

Как примечание стороны, я сомневаюсь, что это безопасно, просто перезаписать %eax/%rax как это. Определили ли вы, что эти регистры никогда не будут содержать какие-либо значения, представляющие интерес?

Другие вопросы по тегам