关于system()栈16字节对齐

关于system()栈16字节对齐

Atomic Lv1

system()中的栈对齐问题

笔者初学pwn的时候发现直接栈溢出覆盖retn的地址为system("/bin/sh")函数,执行会报错,并不能直接获得shell。查阅文章后了解到retn两次即可解决此问题,本文对此进行深入探究。

本文以→这道题←为例题,配合食用效果更佳


[0x00] 对直接retn至system()的情况进行gdb调试

首先在main起始处和main的retn处打俩断点。

1
2
b main
b *0x0000000000401185

gdb stack查看栈:
stack-bigen

main的返回地址储存在0x7fffffffe388处。gdb执行set *(long*)0x7fffffffe388 = fun使main结束后返回至fun函数。

gdb执行continue,程序会读取输入,这里我们不进行溢出,随便输个123然后回车。程序会执行至刚刚我们打的第二个断点处(即main的retn)。

此时我们开始步进调试,会发现main执行完之后程序确实会如我们预期返回至fun函数执行,fun函数执行call 0x401040 <system@plt>进入系统调用。但继续执行,我们发现程序在接下来这里卡住了:

bug-here


[0x01] Why? What’s movaps?

为什么这个指令执行不了了?

查阅资料 得知,movaps这个指令在执行时需要保证栈必须16字节对齐,在16进制的情况下即,栈顶寄存器rsp的地址必须以0x0结尾(例如0x1a2b30,0x1a2b40,0x1a2b50…)。若未对齐则程序会报错。

在我们正常编程时调用system(),编译器逻辑会保证16字节对齐,但这里我们强行对程序进行篡改(不管是使用gdb还是利用栈溢出)使其执行至system()时,栈顶rsp并不一定对齐,比如说这道题。

使用stack指令查看栈,发现rsp果然没对齐(rsp: 0x7fffffffdfc8):

stack-didnt-aligned

其实,在main函数retn的时候,函数的栈是对齐了的。但是在进入fun后,程序在为fun函数创建栈帧时,执行了push rbx指令,这导致后续call system@plt的时候,栈是未对齐的。

[0x02] 总结

由于system()函数执行时对于其内含movaps指令,该指令要求栈顶指针与16字节对齐,有时我们无法执行system函数获取shell。解决办法如本篇开始时所引用的那篇文章,我们可以多返回一次使栈指针升高8字节(栈是由高地址向低地址增长的),这样本来没对齐的栈顶便对齐0x10了。

  • 标题: 关于system()栈16字节对齐
  • 作者: Atomic
  • 创建于 : 2024-08-01 18:49:02
  • 更新于 : 2024-08-07 15:35:12
  • 链接: https://blog.atom1c.icu/2024/08/01/stack-alignment/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。