当前位置: 首页 > 面试题库 >

为什么此代码在打开地址随机化后崩溃?

松昱
2023-03-14
问题内容

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

我试图在GNU调试器(gdb)中调试该程序。在gdb的默认配置下,该程序运行良好,但是如果启用地址随机化(set disable- randomization off),该程序将开始崩溃(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的数据,将其存储到堆栈中的缓冲区中,将读取的数据逐字节复制到输出缓冲区中,并将输出缓冲区的内容写入标准输出流。本质上,它应作为的受限版本cat

在我的计算机上,它要么按预期工作,要么因SIGSEGV崩溃,大约成功运行1次至崩溃4次。


问题答案:

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



 类似资料:
  • 问题内容: 以下打印语句将打印“ hello world”。有人可以解释吗? 而且是这样的: 问题答案: 当使用特定的种子参数(在这种情况下为或)构造的实例时,它遵循以该种子值 开头 的随机数生成算法。 每个使用相同种子构造的对象每次都会生成相同的数字模式。

  • 问题内容: 我正在尝试调试使用很多指针的二进制文件。有时为了快速查看输出以找出错误,我打印了对象的地址及其对应的值,但是对象地址是随机的,这违背了快速检查的目的。有没有一种方法可以暂时/永久禁用此功能,以便每次运行程序时都获得相同的值。 哎呀。操作系统是 问题答案: 在Ubuntu上,可以使用…禁用它。 在Windows上,这篇文章可能会有所帮助… http://blog.didiersteven

  • 语言的实现是一个很复杂的过程,这个复杂并非说它很难,虽然的确有一些难点,但总的来说并不是那么难以理解,复杂和简单相对,是指细节很多,很多事情需要具体到情况来讨论,比如龙书讲优化的部分,很多都是小的优化点;还有一些可能矛盾的地方,需要多种方案配合处理,比如前述静态类型推导,虽然纯粹的静态和动态类型都很容易实现,但要想各取所长就很麻烦了 幸运的是,至少在计算机领域,很多东西是非随机性的,语言也不例外,

  • 问题内容: 此代码段给出以下输出(换行符由空格代替): 问题答案: 从文档: 当处理字符变量而非C的算术运算时,PHP遵循Perl的约定。 例如,在Perl 变成,而用C 变成(,)。 请注意,字符变量可以递增但不能递减,即使如此,仅支持纯ASCII字符(az和AZ)。 还应该注意的是,按字典顺序比较。(自从开始。但是,这是第一次比较不正确。)例如,中断何时可以工作。

  • 下面的print语句将打印“helloworld”。有人能解释一下吗? 而如下所示:

  • 问题内容: 这是执行代码 当我执行它时,它给我以下输出 正确地将cx解释为指针。但是,当我打印cx时,它会打印,而当我打印或格式化cx时,它会正确地打印地址。为什么会这样呢? 问题答案: 默认的打印动词使用是。虽然在打印区分价值VS指针值,这就是为什么你看到前面。 接下来,您具体告诉使用动词,请参阅“ 打印”部分,然后进行打印。