初次尝试,如有错误,请大佬指出。
编写了一个如下的程序,在函数verify_password
中,由于拷贝函数
strcpy(buffer,password);//over flowed here!
没有对长度进行限制,所以存在一个溢出点。
配置:IDA 7.0社区版
以及od 我爱破解7周年纪念版
。(需要软件的可以去官网下载:od,ida)
环境:windows 10,vc6.0
(环境原因不行的,我这里有一个编译好的,上传到csdn了,没有积分的私戳我,发邮件给你)
- 源代码
#include <stdio.h>
#include <string.h>
#define PASSWORD "1234567"
int verify_password (char *password)
{
int authenticated=1;
char buffer[8];// add local buffto be overflowed
// char buffer2[]="1234567812345678";// add local buffto be overflowed
authenticated=strcmp(password,PASSWORD);
strcpy(buffer,password);//over flowed here!
return authenticated;
}
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("incorrect password!\n\n");
}
else
{
printf("Congratulation! You have passed the verification!\n");
break;
}
}
}
-
打开ida对反编译的代码进行分析,进入到main函数。并找到
verify_password
函数的入口,进入 -
将
verify_password
函数的变量名字根据长度猜测,并修改。
4. 在我们大致了解反编译之后的代码的结构,我们打开od进行动态调试。先使用快捷键Ctrl+G
调出跳转框,注意,此时鼠标应该在汇编代码位置。而跳转的参数为verify_password
函数的入口地址。
5. 快捷键F9
运行。到断点位置之后,F7
单步调试。在cmd窗口输入abcdef
。EBP存放的是栈底的地址,ESP是栈顶指针,以下设置要在以下代码执行完成之后设置。不了解的同学看看这篇文章
push ebp//保存上一个栈底
mov ebp,esp//将上一个栈的栈顶作为新的栈底
sub esp,0x4c//设置新的栈顶位置
- 执行到
strcmp
函数的前后3个关键步骤。
7. 执行到strcpy
8. 然后可以看到cmd中出现
9. 那么我们就要开始想象怎么来利用前面提到的漏洞绕过密码
要知道在内存中 函数verify_password
的入栈顺序为
1. 形参password
的地址
2. verify_password
返回地址
3. authenticated
4. buffer[8]
也就是说当buffer的大小足够大的时候,可以在完成字符串比较之后,将authenticated
的值进行覆盖,那么返回的就是一个覆盖后的值。
我们不妨思考一下,buffer
的大小为8,那么输入的字符长度为12的时候就可以完全覆盖掉,对吧?但是注意,C语言会将输入的字符,后面加上0x00
作为截断,所以要将authenticated
覆盖为00,那么可以输入一个8位的任意字符,因为此时截断0x00
会恰好将authenticated
的最后的0x01
覆盖为0x00
,又由于我们初始化authenticated
的时候,前6bit已经变为0,所以authenticated
整个值为0。
可以看到密码不是1234567,但是仍然显示登陆成功。
当然如果想无论初值是什么都可以覆盖,那么就要构造payload了。