首页 > 解决方案 > 当调试器可以手动写入同一内​​存时,为什么在尝试执行写入内存的指令时会出现分段错误?

问题描述

这是针对 x86-64 的,是某些堆栈溢出漏洞的一部分。

gdb 输出:

=> 0x000055555555e996:  48 89 18    mov    QWORD PTR [rax],rbx

将 rbx 移动到存储在 rax 的内存地址中,很简单。由于这条指令出现了段错误,让我们来看看它。

什么是 rax?

(gdb) i r rax
rax            0x7ffff79f4c80      140737347800192

这个记忆有效吗?

(gdb) x/16b $rax
0x7ffff79f4c80 <_itoa_upper_digits>:    0x30    0x31    0x32    0x33    0x34    0x35    0x36    0x37
0x7ffff79f4c88 <_itoa_upper_digits+8>:  0x38    0x39    0x41    0x42    0x43    0x44    0x45    0x46

好吧,至少我可以阅读。我可以写吗?

(gdb) set $rbx = 0x4141414141414141
(gdb) set {unsigned long} $rax = $rbx
(gdb) x/16b $rax
0x7ffff79f4c80 <_itoa_upper_digits>:    0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0x7ffff79f4c88 <_itoa_upper_digits+8>:  0x38    0x39    0x41    0x42    0x43    0x44    0x45    0x46

似乎工作正常,并且这个设置操作确实似乎确实写入了内存,尝试对已知的无效地址进行相同的操作将导致错误。所以看来我可以读写这个内存。

让我们尝试执行这条指令。还是一样的:

(gdb) x/i $pc
=> 0x55555555e996:  mov    QWORD PTR [rax],rbx
(gdb) si

Program received signal SIGSEGV, Segmentation fault.
(a=<error reading variable: Cannot access memory at address 0x376141366141355d>)
    at test.c:371
371     asm volatile("mov %rbx,(%rax);"
=> 0x000055555555e996:  48 89 18    mov    QWORD PTR [rax],rbx
   0x000055555555e999:  c3  ret    

为什么当我刚刚验证我可以在那里写信时它会失败?

标签: linuxsegmentation-faultgdbx86-64exploit

解决方案


为什么当我刚刚验证我可以在那里写信时它会失败?

程序不能在那里写,只有GDB可以。

您尝试写入的地址位于该.text部分中,该部分通常mmap带有PROT_READ|PROT_EXEC PROT_WRITE带有.

但是,允许 GDB(或任何正在ptrace处理这个的进程)写入此类映射。这是 GDB 能够插入断点所必需的(这通常需要重写程序指令)。


推荐阅读