您的位置:首页 > 其它

【0Day】栈溢出漏洞基础——简单输入漏洞 & 修改返回函数

2014-11-29 11:07 323 查看
最近再次利用零零散散的时间,把第二章学完了。 感觉实验成功之后,还是非常开心的!嘿嘿。

书本上的理论可以很快的看完,但是真正实践的时候还是会出现一点问题的。一点点总结将在后面一起分享出来。

自己构造的漏洞代码,如果使用VS编译的话,debug版溢出了会报错,release版它自己把代码优化了,消除了溢出的漏洞。





看来好几年前的技术现在已经被防护的很彻底了呀。 所以说,学技术不能死学,要学习思想。

0x00 堆栈的基本原理

在调用一个call之后,堆栈的情况是这样的。



call中记录的是前栈帧的EBP。 这个时候:

比如这说个函数 int f(int a, int b){ int abc = 5 ; return abc; }

在汇编中,获取函数的局部变量和传入参数,都是利用EBP的相对地址的。

就相当于图中的 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的位置,同时还有返回地址的位置。

首先确定待跳转的地址。这里我们将在函数返回之后直接跳转到提示成功的地方。[b][0x00401467]




接着我们掌握堆栈结构,锁定具体哪一个位置填充我们的地址。



可以发现,每行四个字符,前面6行,24个字符,填充掉,后面四个字符表示返回地址。我们填上自己的地址。

构造的exploit文件时这样:



接着再执行。发现已经替换成我们的地址了。



显示执行成功了!



整理完之后还是感觉很有成就感的。

初步的漏洞理论学习。

下面是利用漏洞注入自己的代码,但是方法不是通用的。跟操作系统版本号,编译器等有关的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐