实验目的:
在掌握栈帧结构的基础上,学习栈溢出漏洞的基本原理。
完成功能:
在函数的栈帧中,局部变量是顺序排列的,栈帧中还保存前栈帧EBP及返回地址RET等信息。构造password.txt。
使得str在读取该文件后恰能够覆盖fun函数的返回地址,从而运行attack函数。
实验代码:
#include <stdio.h>
void attack(){
printf("Attacked!\n");
exit(0);
}
void fun(){
char password[6]="ABCDE";
char str[6];
FILE *fp;
if(!(fp=fopen("password.txt","r"))){
exit(0);
}
fscanf(fp,"%s",str);
str[5]='\0';
if(strcmp(str,password)==0)
printf("OK!\n");
else
printf("NO!\n");
}
int main()
{
fun();
return 0;
}
实验结果和分析:
- 设置程序断点
- 让程序运行到断点处停止,这时候查看main()函数栈的ebp指针的值
可以看到ebp指针的值是0x6dff08 - 这时候让我们跳进fun()函数中去,同时查看fun()函数栈中ebp指针的值
- 这时候打开内存,查看fun()的ebp指针指向的值
可以看到fun()函数栈中ebp指针指向的值是main()函数栈中ebp指针的值,由于栈的增长方向是从高地址向低地址增长的,ebp指针紧挨着的高地址位置是函数栈的返回地址。我们就可以知道fun()函数的返回地址是0x401410, 要使得fun()函数返回时成功地跳到attack()函数处去,就得把fun()函数的返回地址覆盖为attack()的函数地址,这样才能实现跳转。 - 让我们查看下attack()的函数地址
可以看到attack()函数的地址是0x401350 - 接着让我们查看下str数组的地址
从fun()函数的ebp地址到str数组地址中间相差了0x6dfef8 - 0x6dfee0共24个字节,存储返回值的地址到ebp地址中间又相差了4个字节。返回地址的长度是4个字节,所以从str数组开始到完全覆盖返回地址需要输入32个字节的数据。
前28个字节随便输入,后4个字节为attack的地址。 - 完成输入后,我们一直点击next line让程序往下执行
可以看到成功地从fun()返回后跳到了attack()函数处,继续执行程序。
成功了!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。