x86 JMP по адресу хранится в реестре - PullRequest
0 голосов
/ 21 мая 2018

Я хочу перейти на адрес, сохраненный в% rax, и этот адрес будет известен только во время выполнения.Вот что я пытался сделать с самоизменяющимся кодом:

mov    $0x0, %rax
jmp    *%rax 

Операнд $ 0x0 будет изменен на адрес во время выполнения.Однако при выполнении кода я получаю ошибку сегментации.Я использую MacOS и GCC.Ниже приведена полная версия кода:

            .data
fmt_int:
        .ascii "%ld\n\0"
fmt_hex:
        .ascii "%#08x\n\0"

        .global _main


        .text
_main: 
        push    %rbp
        mov     %rsp, %rbp

        # allow us to write to section .text
        lea     _main(%rip), %rdi
        mov     %rdi, %rbx
        call    _getpagesize
        mov     %rax, %rsi
        xor     %rdx, %rdx
        mov     %rbx, %rax
        div     %rsi
        sub     %rdx, %rbx
        lea     _main(%rip), %rcx
        lea     _end(%rip), %rsi
        sub     %rcx, %rsi
        add     %rdx, %rsi
        inc     %rsi
        mov     %rbx, %rdi
        mov     $7, %rdx
        call    _mprotect    

        # change the mov statement at l0
        lea     l0(%rip), %rdi
        lea     l2(%rip), %rax
        movl    %eax, 3(%rdi)

        mov     $2, %rsi

l0:
        mov     $0x0, %rax
        jmp     *%rax
l1:
        mov     $0, %rsi
l2:
        lea     fmt_int(%rip), %rdi
        call    _printf

        pop     %rbp
        ret
_end:

Таким образом, код под строкой # change the mov statement at l0 изменяет операнд инструкции mov $0x0, %rax на mov $addr_l2, %rax, где addr_l2 - адрес l2.Поэтому, когда он выполняется, он должен перейти к l2.Тем не менее, код дает ошибку сегментации при переходе.

Я пробовал другой код, который не включает самоизменяющийся код:

            .data
fmt_int:
        .ascii "%ld\n\0"
fmt_hex:
        .ascii "%#08x\n\0"

        .global _main


        .text
_main: 
        push    %rbp
        mov     %rsp, %rbp

        mov     $2, %rsi

l0:
        lea     l2(%rip), %rax
        jmp     *%rax
l1:
        mov     $0, %rsi
l2:
        lea     fmt_int(%rip), %rdi
        call    _printf

        pop     %rbp
        ret
_end:

Этот код работает нормально.Но в обоих случаях jmp также переходит на адрес l2, поэтому я не знаю, почему предыдущий не работает, а другой работает.

Почему происходит сбой самоизменяющейся версии кода и как ее исправить?

...