缓冲区溢出
缓冲区溢出是指当计算机向缓冲区内填充数据位数时超过了缓冲区本身的容量溢出的数据覆盖在合法数据上。
理想的情况是程序检查数据长度并不允许输入超过缓冲区长度的字符,但是绝大多数程序都会假设数据长度总是与所分配的储存空间相匹配,这就为缓冲区溢出埋下隐患。
缓冲区溢出有堆缓冲区和栈缓冲区溢出,二者有些不同,大部分情况下都是讨论栈溢出。
1.原理
1.1 函数调用栈情况
程序运行时,为了实现函数之间的相互隔离,需要在调用新函数时保存当前函数的状态,这些信息全在栈上,为此引入栈帧。每一个栈帧保存者一个未运行完的函数的信息,包括局部变量等等。栈帧的边界由ebp/rbp(栈底指针)和esp/rsp(栈顶指针)确定。
先看一看函数调用时的栈情况,以func1调用func2为例。假如func2有2个形参。
当func1调用 func2会执行如下汇编码
push arg2
push arg1
call func2
add esp, 8
一般一个函数(func2)的起始和终止汇编代码会有如下操作
push ebp
mov ebp, esp
sub esp, xxx
...
mov esp, ebp
pop ebp
retn
func1调用func2之前,栈中只有func1的局部变量。
- 执行call指令前,
func1将func2的2个参数压栈,此时ebp在func1局部变量之下,esp指向func2的第一个参数arg1。 - 之后执行
call指令,将程序下一条指令的eip(add esp,8)压栈,跳到func2。ebp不变,esp指向返回地址。 - 之后跳到
func2指向push ebp,func1的ebp被压栈。ebp依旧不变。 - 执行
mov ebp, esp。此时func2的ebp指向的是func1的ebp。 - 执行
sub esp, xxx,扩充栈空间,给局部变量清出空间。 - 执行
mov esp, ebp,销毁func2栈帧,再执行pop ebp。恢复func1的ebp。此时retn弹出func1的 eip(func2的返回地址)并回到func1继续执行。 - 回到
add esp, 8指令。清除func2的2个参数,此时栈中只剩func1局部变量。
func2执行完sub esp, xxx后整个栈空间布局如下,此时ebp指向的是func1的ebp。从func2返回地址到func1的局部变量都属于func1的栈帧。
| 栈 |
|---|
func2局部变量 |
func1的ebp |
func2返回地址(func1某条指令) |
func2 2个参数 |
func1局部变量 |
1.2 缓冲区溢出
void function(

最低0.47元/天 解锁文章
1681

被折叠的 条评论
为什么被折叠?



