试验目标:
在把握栈帧构造的根底上,学习栈溢出破绽的基本原理。
实现性能:
在函数的栈帧中,局部变量是顺序排列的,栈帧中还保留前栈帧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()函数处,持续执行程序。
胜利了!