x86_64汇编 - 在x64汇编中尝试编辑数组中的字节时的Segfault

Myk*_*one 2 assembly x86-64 segmentation-fault

我所遵循的教程是针对x86的,并且是使用32位汇编编写的,我正在尝试跟进,同时在此过程中学习x64汇编.在本课程中我已经进行了很好的练习,我有以下简单的程序,它只是尝试修改字符串中的单个字符; 它运行时编译好但是段错误.

section .text

global _start ; Declare global entry oint for ld
_start:

    jmp short message ; Jump to where or message is at so we can do a call to push the address onto the stack

    code:   
    xor rax, rax    ; Clean up the registers
    xor rbx, rbx
    xor rcx, rcx
    xor rdx, rdx

    ; Try to change the N to a space
    pop rsi ; Get address from stack
    mov al, 0x20 ; Load 0x20 into RAX
    mov [rsi], al; Why segfault?
    xor rax, rax; Clear again

    ; write(rdi, rsi, rdx) = write(file_descriptor, buffer, length)
    mov al, 0x01    ; write the command for 64bit Syscall Write (0x01) into the lower 8 bits of RAX
    mov rdi, rax    ; First Paramter, RDI = 0x01 which is STDOUT, we move rax to ensure the upper 56 bits of RDI are zero
    ;pop rsi        ; Second Parameter, RSI = Popped address of message from stack
    mov dl, 25  ; Third Parameter, RDX = Length of message
    syscall     ; Call Write

    ; exit(rdi) = exit(return value)    
    xor rax, rax    ; write returns # of bytes written in rax, need to clean it up again
    add rax, 0x3C   ; 64bit syscall exit is 0x3C
    xor rdi, rdi    ; Return value is in rdi (First parameter), zero it to return 0
    syscall     ; Call Exit

    message:
    call code   ; Pushes the address of the string onto the stack
    db 'AAAABBBNAAAAAAAABBBBBBBB',0x0A
Run Code Online (Sandbox Code Playgroud)

这个罪魁祸首就是这条线:

mov [rsi], al; Why segfault?
Run Code Online (Sandbox Code Playgroud)

如果我发表评论,那么程序运行正常,输出消息'AAAABBBNAAAAAAAABBBBBBB',为什么我不能修改字符串?

作者代码如下:

global _start


_start:
        jmp short ender

        starter:

        pop ebx                 ;get the address of the string
        xor eax, eax

        mov al, 0x20
        mov [ebx+7], al        ;put a NULL where the N is in the string

        mov al, 4       ;syscall write
        mov bl, 1       ;stdout is 1
        pop ecx         ;get the address of the string from the stack
        mov dl, 25       ;length of the string
        int 0x80

        xor eax, eax
        mov al, 1       ;exit the shellcode
        xor ebx,ebx
        int 0x80

        ender:
        call starter
        db 'AAAABBBNAAAAAAAABBBBBBBB'0x0A
Run Code Online (Sandbox Code Playgroud)

我用以下方法编译了:

nasm -f elf <infile> -o <outfile>
ld -m elf_i386 <infile> -o <outfile>
Run Code Online (Sandbox Code Playgroud)

但即使这会导致段错误,页面上的图像显示它正常工作并将N更改为空格,但是我似乎陷入了段错误:(谷歌在这种情况下并没有真正有用,所以我转向你stackoverflow,任何指针(没有双关语!)将不胜感激

Sam*_*nen 5

我认为这是因为您正在尝试访问该text部分中的数据.通常,您不能写入代码段以获得安全性.可修改的数据应在该data部分中.

此外,我永远不会建议使用call将地址推送到堆栈后的副作用,以获得指向其后的数据的指针.有没有解释为什么要这样做?

  • @MykelStone:I386 Linux的历史上有R + X文字和R + X + W数据,因为直到NX位(和AMD64),有没有办法让一个页面可读,但不能执行.但总有写保护,Linux将它用于可执行文件的文本段.我很确定将作者的代码构建为普通的32位可执行文件并以正常方式运行它总是会产生segfaulted. (2认同)