参考《0day安全 软件漏洞分析》做的,个人学习记录
工具:
- x32dbg;
密码验证小程序源码:
#include<stdio.h>
#include<string.h>
#define PASSWORD "1234567"
int verify_password (char *password)
{
int authenticated=1;
char buffer[8]; //设置一个数组来人为制造栈溢出
authenticated = strcmp(password,PASSWORD);
strcpy(buffer,password); // 栈溢出将在这里发生
return authenticated;
}
int 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;
}
}
}
运行exe,如图
原理
根据变量声明的顺序,变量在栈中的存储情况应该如下所示
获得关键变量的地址
printf("%x\n",&authenticated); // 62fa6c
printf("%x\n",&buffer);//62fa64
发现符合上图所示的情况
在输入“qqqqqqqq”后,在x32dbg中调试可以观察到
strcmp作用是比较输入的password与常量PASSWORD,相同则返回0,不同则返回1,返回值保存在变量authenticated中
strcpy的作用是把password的值赋值给数组buffer,注意字符串末尾还有\0
1.在执行完strcmp后,由于“qqqqqqqq”和“1234567”不相等,authenticated被赋值为1 。
2.在执行完strcpy后,由于“qqqqqqqq”加上末尾“\0”需要18个字节。而数组buffer只声明了16个字节,多出的两个字节便覆盖了“01”,变成了“00”,如果我们把输入换成“”qqqqqqqqrst“,就会得到如下结果,q的ascⅡ码为0x71,r为0x72,s为0x73,t为0x74
3.由于authenticated的值被覆盖为0,无论密码是否正确,返回都是验证正确的结果