首页 > 代码库 > 【0Day】栈溢出漏洞基础——简单输入漏洞 & 修改返回函数
【0Day】栈溢出漏洞基础——简单输入漏洞 & 修改返回函数
最近再次利用零零散散的时间,把第二章学完了。 感觉实验成功之后,还是非常开心的!嘿嘿。
书本上的理论可以很快的看完,但是真正实践的时候还是会出现一点问题的。一点点总结将在后面一起分享出来。
自己构造的漏洞代码,如果使用VS编译的话,debug版溢出了会报错,release版它自己把代码优化了,消除了溢出的漏洞。
看来好几年前的技术现在已经被防护的很彻底了呀。 所以说,学技术不能死学,要学习思想。
0x00 堆栈的基本原理
在调用一个call之后,堆栈的情况是这样的。
call中记录的是前栈帧的EBP。 这个时候:
比如这说个函数 int f(int a, int b){ int abc = 5 ; return abc; }
在汇编中,获取函数的局部变量和传入参数,都是利用EBP的相对地址的。
[b] 就相当于图中的 param1, 地址为EBP+C
[a] 相当于param2, 地址为EBP+8
调用函数f之后的指令地址为[return addr], 地址为EBP+4
声明的本地变量从EBP开始减,
局部变量[abc]相当于 local pa1,地址为EBP-4,依次类推。
ESP的作用就是堆栈的栈顶指针,一般用于调用函数的时候,压入参数。
此次漏洞构造的目的,就是要利用Function 函数中拷贝函数的溢出特点,把局部变量local pa1,return addr 改变成自己想要的值得目的。
0x01 简单的输入漏洞
构造的具有漏洞的代码如下:
/* note: 1、找到存储aut,buffer的位置。 本例中:aut=[esp-C] buffer=[esp-14] 2、查看堆栈,到数据窗口中跟随。 3、根据具体情况构造对应的overflow代码 */ #include <string.h> #include <stdio.h> #define PASSWORD "123456" int authen(char *password) { int aut; char buffer[8];//add to be overflowed!! aut = strcmp(PASSWORD,password); strcpy(buffer, password);//overflow! return aut; } int main() { char password[1024]; while(1) { printf("please input the password: "); scanf("%s",password); if( authen(password) )//输入的数小于123456,值00000001,覆盖00000000;反之,值FFFFFFFF,覆盖为FFFFFF00,, { printf("no! you should try again!\n"); } else { printf("Yes! you did it! \n"); break; } } getchar(); getchar(); return 0; }
想要挖掘这个代码中的漏洞,就是要看两点。是否有可以溢出的缓冲区?是否有可以向缓冲区填充数据的条件?
本代码中就是 buffer 和strcpy两个函数。我们的目的就是要通过向buffer填充数据,改变相邻变量aut的值为0.为0 表示密码比对成功。
溢出之前的堆栈:
溢出之后的堆栈,aut位被溢出成0了,表示字符串比较成功,为相等:
本例中要求输入的密码小于真正的密码,得到的值为正数1. 反之如果大于真正的密码,将得到负数 -1. 补码为 FFFFFFFF。 普通输入将无法正确的溢出,需借助文件输入。
0x02 修改函数返回地址
构造的漏洞代码:
/* note: */ #include <string.h> #include <stdio.h> #define PASSWORD "123456" int authen(char *password) { int aut; char buffer[8];//add to be overflowed!! aut = strcmp(PASSWORD,password); strcpy(buffer, password);//overflow! return aut; } int main() { char password[1024]; FILE* fp; if(!(fp=fopen("password.txt","rw+")))//get the pass by read file return 0; fscanf(fp, "%s", password); if( authen(password) ) { printf("no! you should try again!\n"); } else { printf("Yes! you did it! \n"); } fclose(fp); getchar(); getchar(); return 0; }由于像地址这种特殊的字符"0x0041567",手打很难输入,因此,借助文件的输入。 这种构造完全是为了理解漏洞的原理来做的。
同样,也应该找到buffer的位置,同时还有返回地址的位置。
首先确定待跳转的地址。这里我们将在函数返回之后直接跳转到提示成功的地方。[0x00401467]
接着我们掌握堆栈结构,锁定具体哪一个位置填充我们的地址。
可以发现,每行四个字符,前面6行,24个字符,填充掉,后面四个字符表示返回地址。我们填上自己的地址。
构造的exploit文件时这样:
接着再执行。发现已经替换成我们的地址了。
显示执行成功了!
整理完之后还是感觉很有成就感的。
初步的漏洞理论学习。
下面是利用漏洞注入自己的代码,但是方法不是通用的。跟操作系统版本号,编译器等有关的。
【0Day】栈溢出漏洞基础——简单输入漏洞 & 修改返回函数