系统相关
首页 > 系统相关> > linux – 为什么这段代码会因地址随机化而崩溃?

linux – 为什么这段代码会因地址随机化而崩溃?

作者:互联网

我正在学习amd64汇编程序,并试图实现一个简单的Unix过滤器.由于未知原因,即使简化为最低版本(下面的代码),它也会随机崩溃.

我试图在GNU Debugger(gdb)中调试这个程序.在gdb的默认配置中,程序运行正常,但如果我启用地址随机化(设置禁用 – 随机化关闭),程序将开始崩溃(SIGSEGV).有问题的指令在清单中标出:

format ELF64 executable

sys_read                        =       0
sys_write                       =       1
sys_exit                        =       60

entry $
foo:
    label .inbuf   at rbp - 65536
    label .outbuf  at .inbuf - 65536
    label .endvars at .outbuf
    mov rbp, rsp

    mov rax, sys_read
    mov rdi, 0
    lea rsi, [.inbuf]
    mov rdx, 65536
    syscall

    xor ebx, ebx
    cmp eax, ebx
    jl .read_error
    jz .exit

    mov r8, rax  ; r8  - count of valid bytes in input buffer
    xor r9, r9   ; r9  - index of byte in input buffer, that is being processed.
    xor r10, r10 ; r10 - index of next free position in output buffer.

.next_byte:
    cmp r9, r8
    jg .exit
    mov al, [.inbuf + r9]
    mov [.outbuf + r10], al ;; SIGSEGV here in GDB
    inc r10
    inc r9
    jmp .next_byte

.read_error:
    mov rax, sys_exit
    mov rdi, 1
    syscall
.exit:
    mov rax, sys_write
    mov rdi, 1
    lea rsi, [.outbuf]
    mov rdx, r10
    syscall

    mov rax, sys_exit
    xor rdi, rdi
    syscall


该程序旨在从stdin读取最多64kB,将其存储到堆栈中的缓冲区中,将读取的数据逐字节复制到输出缓冲区中,并将输出缓冲区的内容写入标准输出流.从本质上讲,它应该表现为猫的有限版本.

在我的计算机上,它可以按预期工作,或者与SIGSEGV崩溃,大约1次成功运行到4次崩溃.

解决方法:

amd64中的红色区域只有128个字节长,但是你使用的是低于rsp的131072个字节.向下移动堆栈指针以包含要存储在堆栈中的缓冲区.

标签:linux,x86-64,fasm
来源: https://codeday.me/bug/20190928/1825210.html