实验2.2修改临近变量:
#include "stdafx.h"
#include "stdio.h"
#include "string.h"
#define PASSWORD "1234567"
int verify_password(char *password)
{
int authenticated;
char buffer[8]; //这里声明的变量在后续的strcpy操作可能会发生溢出
authenticated = strcmp(password,PASSWORD);
strcpy(buffer,password); //导致溢出的函数
return authenticated;
}
void main(int argc, char* argv[])
{
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");
}
else
{
printf("Congratulation! You have passed the verification!\n");
break;
}
}
}
经过分析,我们进入verify_password(char * password)时栈的情况:
很显然,authenticated由strcmp函数的结果,(1,0,-1)不知道的可以查查该函数,复制后就不在对该变量进行改变
当我们执行了函数strcpy(buffer,password)时是有可能淹没authenticated变量的。
本实验的目的也是为了构造传入verify_password的参数password从而实现传入buffer导致溢出淹没用于判断验证密码正确与否的authenticated,改写该变量,实现即便输错密码也会反会成功验证的信息
既然我们知道了引发安全问题的是verify_password函数,下面是verify_password的汇编:
这里需要注意的是输入字符串时,系统识别字符串结束使用的%00表截断,我们这里测试输入的password是:123456我们看下内存怎么放的
注意到最后的00没有,这里就是表字符串到此结束。
对于局部变脸buffer[8]的栈情况FFFFFFFF表示-1,因为我们的password123456>1234567(正确密码),strcpy调用后返回-1
因此,我们可以放入8个字符,假设是12345678>1234567(正确密码)则加上%00则buffer存放是就会是
main中的if判断,则是authenticated为0是跳转验证通过的信息
可以看到,我们输入的密码并不是正确的密码(1234567),可我们还是得到了正确通过验证的信息,至此我们的实验目的达到了
总结思路就是:
找到跳转出正确信息的位置,找判断条件,回溯变量,改写,达到即便输错也可以pass验证
如本实验:
分析源代码main函数发现如果valid_flag是0则可以看到提示密码正确的信息,回溯,
找回valid_flag的赋值过程–>verify_password–>authenticated–>strcmp()
显然strcmp根据我们的输入来赋值,但是局部变量authenticated正好位于buffer[8]下方,我们可以通过溢出来覆盖这个值