缓冲区溢出利用(1)
§1.1 题目描述
题目包括两个文件:
vul1.c:C语言源程序代码
Vul1.exe : 编译生成的可执行文件
题目要求:
- 执行 vul1.exe,在不修改程序的情况下,取得合法验证。
-
撰写详细的分析利用报告。
§1.2 使用的分析工具
在本次实验中,我们使用了以下工具进行分析:
1、Visual C++6.0
2、IDA7.0
§1.3 漏洞分析过程
首先,我们观察其C语言代码,可以发现,其中在判断函数返回前,进行了一次字符串复制操作,将password复制给buffer。如图(1).
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIyVGduV2YfNWawNyZuBnL0AzN1QzM0AjMzETMxAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
图 1
而在这里,我们可以发现变量authenticated的大小为1024字节,而buffer的大小为32字节,这就表明这里可能存在一个栈溢出漏洞。也就是说,我们可以通过构造一个输入,使其大小能超出栈中给buffer分配的大小,覆盖authenticated所在位置,从而改变函数verify_password的返回值。
下面我们使用IDA对exe文件进行反汇编。我们首先通过call verify_password命令确定验证函数在栈中位置。
然后观察其中buff变量和authenticate位置,可以发现authenticate在buff的后方。
我们查看其在栈中位置进行再次确定,发现buff在authenticated上0x20的位置。即只要password的超过32个字符,就可以对authenticated的值进行覆盖。
再往下看我们可以发现,该函数是将authenticated的值通过寄存器EAX进行返回。如下图所示.
接着在主函数中将eax的值赋与了ebp+valid_flag位置,并在这之后通过比较其与0是否相等来进行判断,如果等于零就会跳转到loc_40109B位置。否则继续执行下面的命令并回到verify_password开始位置。
然后我们再来对攻击数据进行构造,首先是使用32个字符填满buff分配到的栈空间,然后再对authenticated的值进行构造。
由于authenticated需要与零相等,所以其再占中数据应该为00 00 00 00。而在覆盖前,其值由password与正确口令“1921X12”进行比较得出。如果password大于正确口令,则authenticated为1,即在栈中顺序为10 00 00 00;如果小于,则为-1,在栈中顺序为ff ff ff ff。
再看会需要构造的口令,由于是再对话框输入,在输入的字符串后会默认存在一个空字符,其Ascll码即为00。但是,由于我们无法在对话框输入Ascll码为00的字符,所以,我们仅可以覆盖authenticated在栈中最小位置的数并使之为00.如此,构造的字符串必须大于password。
§1.4 漏洞利用过程
根据在1.3节得出的结论,我们构造字符串“22345678901234567890123456789012”进行攻击。效果如下。
将结果与输入正确密码后的结果进行对比,如下。可以发现两者相同。
这里给出vul1.c代码
#include <stdio.h>
#define PASSWORD "1921X12"
int verify_password (char *password)
{
int authenticated;
char buffer[32];
authenticated=strcmp(password,PASSWORD);
strcpy(buffer,password);
return authenticated;
}
void main()
{
int valid_flag=0;
char password[1024];
while(1)
{
printf("please input password: ");
scanf("%s",password);
valid_flag = verify_password(password);
if(valid_flag)
{
printf("\nIncorrect password!\n\n");
}
else
{
printf("\nCongratulation!\n");
printf("You have passed the verification!\n\n");
break;
}
}
}