#include “stdafx.h”
#include <stdio.h>
#include <string.h>
#define PASSWORD “1234567”

int verify_password (char *password)
{
int authenticated;
char buffer[8];
authenticated=strcmp(password,PASSWORD);
strcpy(buffer,password);
return authenticated;
}

int 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\n”);
}
else
{
printf(“Congratulation! You have passed the verification!\n”);
break;
}
}
}

 

题目大概是问password需要在什么样的情况下,才能在密码不匹配的情况下,通过认证。

考点在于 strcmp函数、strcpy越界和字符串后面的null-terminate,也就是\0,

int StrCmp(
  PCSTR psz1,
  PCSTR psz2
);
如果psz1和psz2的ASCII编码相等,返回0,如果psz1<psz2,返回-1,如果psz1>psz2,返回1

需要通过认证,valid_flag需要为0,也就是authenticated 为0,正常情况下,你输入1234567,返回的就是0。

最简单的方法就是溢出,用\0去覆盖掉authenticated。

因为截断符只有1byte,要去覆盖authenticated,那么authenticated的值必须在0-255之间

函数verify_password中buffer长度为8,那么password必须也为8,这样password后面跟的\0才能在strcpy的时候溢出到authenticated,使得authenticated归零。

放张图,可能更加直观点:

ebp+0x8 是传入的password地址,图中的0x0012FB7C

ebp-0xc 是buffer[8]的地址,图中的0x0012FB18

ebp-0x4 是authenticated的地址,图中的0x0012FB20

当strcmp(指令地址为0x00401041)执行完毕后,authenticated值被存放在0012FB20,它的隔壁就是老王,不对是buffer[8](0x0012FB18-0x0012FB1C)

strcpy(指令地址为0x00401054)在执行的没考虑到长度问题,当password数据长度为8时候,如图中是FFFFFFFF(左边可以看到464646后面的00),就溢出了,拷贝的时候把00也拷贝过去,覆盖了0x0012FB20的低位数据

属于城门失火,殃及池鱼。。。

当然,因为是ASCII,所以你密码写四个汉字也行的,比如“随便写写”,刚好是8位。

 

说了那么多,把strcpy(buffer,password);注释掉就没那么多事情了,我只能说他是带有使命而来的。

 

 

 

 

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注