逆向

缓冲区漏洞千千种,这次遇到实验才来讲一讲我想明白的题目。

利用栈溢出漏洞破解口令 

源码:

#include<stdio.h>
#include<string.h>
#define PASSWORD "1234567"
int verify_password(char* password)
{
int authenticated=0xEEEEEEEE;
char buffer[8];
printf("My stack looks like:
%p
%p
%p
%p
%p
%p
%p
%p
%p

");
authenticated=strcmp(password,PASSWORD);
printf("My stack looks like:
%p
%p
%p
%p
%p
%p
%p
%p
%p

");
//printf("flag的值为:%d
",authenticated);
strcpy(buffer,password);
printf("%s
",buffer);
printf("My stack looks like:
%p
%p
%p
%p
%p
%p
%p
%p
%p

");
//printf("覆盖以后flag的值为:%d
",authenticated);
return authenticated;
}

int main()
{
int valid_flag=0x0;
char password[8];
printf("please input password:");
scanf("%s",password);
//printf("传的值为:%d
",verify_password(password));
valid_flag=verify_password(password);
//printf("传完之后flag的值为:%d
",valid_flag);
if (valid_flag)
    {
        printf("incorrect password!

");
   }
else
    {
        printf("Congratulation! You have passed the verification!
");
   }
}

1.首先,观察一下程序,能判断造成栈溢出的代码是

strcpy(buffer,password);

把执行到调用verify_password函数的堆栈来画一下

2.来分析一下代码的作用

(注:strcpy比较的是ASCII值,数字输入时虽然是“数字”,但是它是字符串)

我们能够使用strcpy覆盖并修改return给main函数的值,让main函数误以为我们输入了正确的密码。

看下面代码知判断密码正确的flag值为0,否则为不正确(包括大于0和小于0),因此我们就要return给valid_flag一个0。

3.首先运行

输入12个2,因为buffer最多存8个字节,会溢出4字节到紧接着的堆栈,字符串结尾还有00('')也要存储

flag值被结束符00覆盖了,因此被误认为输入正确

4.特殊情况

如果输入12个1为什么会认为输入错误呢?

首先strcpy是逐位比较,遇到不同位相减返回值的,输入12个1,遇到第二位2时,1-2=-1,因此返回-1(16进制存的是补码为FFFFFFFF)

因为return的值即flag位的数为负数,存储时补码占4字节,虽然字符串有结束符00,但是还远远不能覆盖,返回的值不为0,因此被判断为输入错误

实际上只要输入的字符为12位,且第一个不同位的ASCII值比预设密码的那位ASCII值大就能绕过密码的判断了。

原文地址:https://www.cnblogs.com/echoDetected/p/13787355.html