【问题标题】:x86_64 Assembly - Segfault when trying to edit a byte within an array in x64 assemblyx86_64 程序集 - 尝试在 x64 程序集中编辑数组中的字节时出现段错误
【发布时间】:2017-12-13 18:38:26
【问题描述】:

我正在学习的教程是针对 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

罪魁祸首是这一行:

mov [rsi], al; Why segfault?

如果我把它注释掉,那么程序运行正常,输出消息'AAAABBBNAAAAAAAAAABBBBBBBB',为什么我不能修改字符串?

作者代码如下:

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

我已经编译了:

nasm -f elf <infile> -o <outfile>
ld -m elf_i386 <infile> -o <outfile>

但即使这会导致段错误,页面上的图像显示它正常工作并将 N 更改为空格,但是我似乎被困在段错误领域:(谷歌在这种情况下并没有真正提供帮助,所以我求助于stackoverflow,任何指针(没有双关语!)将不胜感激

【问题讨论】:

  • 因为您的 .text 段被标记为只读。

标签: assembly segmentation-fault x86-64


【解决方案1】:

我认为这是因为您正在尝试访问 .text 部分中的数据。通常,为了安全起见,您不允许写入代码段。可修改的数据应该在.data 部分。 (或者 .bss 如果零初始化。)

对于您不想使用单独部分的实际 shellcode,请参阅Segfault when writing to string allocated by db [assembly] 了解替代解决方法。


此外,我绝不建议使用call 将其后面的地址推入堆栈以获取指向其后面数据的指针的副作用,除了 shellcode。

这是 shellcode 中的一个常见技巧(必须与位置无关); 32 位模式需要调用才能以某种方式获取 EIP。 call 必须有一个向后位移以避免机器代码中出现 00 字节,因此将调用放在创建您特别想要的“返回”地址的地方可以保存 add 或 lea。

即使在可以进行 RIP 相对寻址的 64 位代码中,jmp / call / pop 也与跳过带有负位移的 RIP 相对 LEA 的字符串一样紧凑。

在 shellcode / constrained-machine-code 用例之外,这是一个糟糕的主意,你应该像普通人一样使用lea reg, [rel buf],数据在.data,代码在@ 987654333@。 (或.rodata 中的只读数据。)这样您就不会尝试在数据旁边执行代码,或将数据放在代码旁边。

(允许 shellcode 的代码注入漏洞已经暗示存在具有写入和执行权限的页面,但是来自现代工具链的正常进程没有任何 W+X 页面,除非您采取措施实现这一点。@987654322由于这个原因,@ 是一个很好的安全功能,因此必须破坏正常的工具链安全功能/默认值才能测试 shellcode。)

【讨论】:

  • 他不是在尝试写入 .text 部分的内存地址,而是在尝试不存在的内存地址。他想要 rsi 中的堆栈地址,但他做了一个 pop rsi, no mov rsi, rsp
  • @sinkmanu 是的,他们是。阅读代码: call 将地址放入堆栈,然后将其弹出到 rsi 中。他们不希望 rsp 在 rsi 中。
  • 是的,我没有看到他没有将消息保存在 .data 部分。这种技术被称为“jump call pop”
  • @MykelStone:i386 Linux 历史上具有 R+X 文本和 R+X+W 数据,因为在 NX 位(和 AMD64)之前,没有办法使页面可读但不可执行。但是,始终存在写保护,Linux 将其用于可执行文件的文本段。我很确定将作者的代码构建成普通的 32 位可执行文件并以正常方式运行它总是会出现段错误。
  • call 推送指向以下数据的指针是我以前在 shellcode 示例中看到的,但在 shellcode 漏洞利用中,您没有将数据放在不同部分的奢侈。并且代码+数据通常仅在它位于 RWX 页面中时才有效,通常在堆栈上。 TL:DR:某些 shellcode hack 在具有只读文本段的普通可执行文件中不起作用。禁用randomize_va_space 仅在您将其注入某些东西时才有意义。 call推送以下地址是PIC,其余代码@MykelStone也是。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-15
  • 1970-01-01
相关资源
最近更新 更多