pwn栈溢出详解

问题原因

最近在给新生做辅导,发现他们容易混淆一个问题,或者说对于初学者而言,没有理论基础就直接上手实操容易弄混的一个问题:栈区和代码段分不清楚

由于pwn入门题一般是rop,所以大多数人都会有这样一个理解的误区:

把栈和程序执行流混为一谈了

不少初学者pwn手会把栈区当成程序执行流,但其实不是

要明白一点:

rip 指针所在的程序执行流才是程序执行的核心,栈只是用来辅助存储一些必要信息的工具

栈溢出原理分析

这里以Intel x64为例来讲一下

首先需要知道的基本知识:rsp 栈顶指针, rbp 栈底指针, rip 程序计数器(PC指针)

用下面的原理图来解释,提前声明:

栈区一格为8个字节,代码段一格为一句汇编指令

1,这是函数在执行main函数过程中的一段,此时的rip指向call func1,也就是说即将调用func1

2,执行call func1时,先执行的是push rip操作:

3,接着执行jmp func1操作:

4,此时rip已经指向func1的位置,然后开始执行func1里的代码:push rbp,将当前rbp的值入栈

5,mov rbp, rsp:是将rsp的值赋给rbp,也就是让rbp指向rsp指向的位置

6,sub rsp, 20h:将rsp向上移动0x20个字节,为函数要用到的数据开辟0x20大小的空间

7,函数一路执行,省略,直到leave指令

8,leavemov rsp, rbp,即将rbp的值赋给rsp,也就是让rsp指向rbp指向的位置

9,leavepop rbp,将栈顶元素出栈,并赋值给rbp

10,ret:即pop rip,将栈顶元素取出赋值给rip(程序计数器)

我们可以看到:这时函数的栈(rsprbp所夹的部分)又恢复到原来的样子,rip也恢复到程序调用func1之后的位置了,因此函数能通过调用栈正常执行。

而那个最初被存放在栈中的rip(图中的[rip_0]),就被成为 返回地址 ,也就是程序在完成这一次的函数调用后要继续执行的指令的地址

我们所说的栈溢出,通过对Data'写入时溢出,覆盖掉 返回地址 ,从而让程序接下来一步跳转到任意位置,完成对程序执行流的控制。比如:把 返回地址 覆盖成backdoor

由此,还可以延伸出ROP链攻击方法,在懂得栈溢出基本原理以后可以自行学习

posted @ 2025-05-11 15:12  ret2z  阅读(181)  评论(0)    收藏  举报