![关于system()栈16字节对齐](/images/article_images/myfirstpwn/cover.png)
关于system()栈16字节对齐
![](/images/avatar.jpg)
system()中的栈对齐问题
笔者初学pwn的时候发现直接栈溢出覆盖retn的地址为system("/bin/sh")
函数,执行会报错,并不能直接获得shell。查阅文章后了解到retn两次即可解决此问题,本文对此进行深入探究。
本文以→这道题←为例题,配合食用效果更佳
[0x00] 对直接retn至system()的情况进行gdb调试
首先在main起始处和main的retn处打俩断点。
1 | b main |
gdb stack
查看栈:
main的返回地址储存在0x7fffffffe388处。gdb执行set *(long*)0x7fffffffe388 = fun
使main结束后返回至fun函数。
gdb执行continue
,程序会读取输入,这里我们不进行溢出,随便输个123然后回车。程序会执行至刚刚我们打的第二个断点处(即main的retn)。
此时我们开始步进调试,会发现main执行完之后程序确实会如我们预期返回至fun函数执行,fun函数执行call 0x401040 <system@plt>
进入系统调用。但继续执行,我们发现程序在接下来这里卡住了:
[0x01] Why? What’s movaps?
为什么这个指令执行不了了?
查阅资料 得知,movaps这个指令在执行时需要保证栈必须16字节对齐,在16进制的情况下即,栈顶寄存器rsp的地址必须以0x0结尾(例如0x1a2b30,0x1a2b40,0x1a2b50…)。若未对齐则程序会报错。
在我们正常编程时调用system()
,编译器逻辑会保证16字节对齐,但这里我们强行对程序进行篡改(不管是使用gdb还是利用栈溢出)使其执行至system()
时,栈顶rsp并不一定对齐,比如说这道题。
使用stack
指令查看栈,发现rsp果然没对齐(rsp: 0x7fffffffdfc8):
其实,在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 进行许可。