为什么SIGSEGV同时推指令


=> 0x7fffffffeefc:  xor    %eax,%eax
   0x7fffffffeefe:  movabs $0xff978cd091969dd1,%rbx
   0x7fffffffef08:  neg    %rbx
   0x7fffffffef0b:  push   %rbx
   0x7fffffffef0c:  push   %rsp
   0x7fffffffef0d:  pop    %rdi
   0x7fffffffef0e:  mov    $0x3b,%al
   0x7fffffffef10:  syscall 
   0x7fffffffef12:  add    %cl,0x4e(%rcx,%rcx,2)
   0x7fffffffef16:  rex.RB push %r11
(gdb) nexti
0x00007fffffffeefe in ?? ()
(gdb) nexti
0x00007fffffffef08 in ?? ()
(gdb) nexti
0x00007fffffffef0b in ?? ()
(gdb) nexti
0x00007fffffffef0c in ?? ()
(gdb) nexti
Program received signal SIGSEGV, Segmentation fault.
0x00007fffffffef12 in ?? ()

我不明白为什么0x7fffffffef0c会出现分段故障。分段故障后跳变到0x7fffffffef12而不是0x7fffffffef0c。这是否意味着0x7fffffffef0c是错误处理程序?

gdb似乎跳过了syscall指令和周围的一些指令。SIGSEGV可能与0x7fffffffef12指令中使用的rcx寄存器的值有关。如果您希望gdb在每个指令处停止而不是继续进行函数调用,那么stepi可能比nexti更好。

0x7fffffffef12(假定的坠机地点)的指令看起来很奇怪;拆解过程中的其他说明似乎也很奇怪。如果我在我自己的系统上的gdb会话中查看相同的地址范围,我在页面的那一部分看到的是一堆以空结尾的字符串,它们看起来非常像我的命令行,然后是我的环境。前三个地址与主框架中argv的前三个元素匹配,argv本身也在该页中。

检查用x/s而不是x/i反汇编的地址可能会很有趣。在我的会话中(在主框架中)x/29s argv[0]显示了该地址范围内的一堆东西。

如果在尝试将环境视为代码时发生崩溃,可能更有趣的问题是如何发生到该地址范围的分支。如果gdb显示了这次崩溃的前后一致的回溯,那可能会提供一些见解。

GDB说你错在0x00007fffffffef12,这是add %cl,0x4e(%rcx,%rcx,2),正如@Eirik的回答所解释的。

SYSCALL销毁rx和r11,同时用返回值修改rx。

请参阅来自x86标记wiki的其他链接,以及底部的gdb提示。使用layout asmlayout reg,使遵循RIP和注册值更容易。


ni可能跳过了多个指令,因为gdb认为它们来自内联函数或其他东西。(也许是汇编宏?)ni不下降到CALL指令,但我不认为它通常跳过任何其他。但只要使用si


添加后的

rex.RB push %r11也不太可能有用。您是否故意挑选了被SYSCALL销毁的两个寄存器?此外,还有一个带有REX前缀的PUSH。W=0将被视为非法指令。push r/m32在64位模式下不可编码,尽管英特尔手册中的文本措辞。

哦,我认为SYSCALL之后的代码只是数据("/bin/sh"或其他东西)或只是垃圾,根本不意味着要执行,因为SYS_execve是59 (0x3b), OP可能希望它不返回。

显然这是shellcode,所以这解释了push/pop而不是mov %rsp, %rdi和其他奇怪的东西,大概是为了避免0x00字节。如果能提到这一点就好了,这样我们这些错过了[shell]标签的人就可以避免浪费大量的时间来讨论这些奇怪的东西了。

最新更新