首页 > 代码库 > 【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】栈溢出漏洞基础——简单输入漏洞 & 修改返回函数