目录
1.当从键盘输入“1234567”、“12345678”、“11112222”时,程序执行完图中所标记的 strcpy 语句之后,堆栈会如何变化?此时程序的最终执行结果将会是什么?运行程序进行验证。
2.当满足什么条件时,就可以在不知道真实口令的情况下绕过口令验证功能?为什么?
缓冲区溢出作业
题目:
![](https://img-blog.csdnimg.cn/a6f80c9499334f3e8f60eadf96d4562c.png)
![](https://img-blog.csdnimg.cn/dce074a617914783bb3755023a179f57.png)
作业代码:(编译环境devc++,12位时绕开口令)
#include <stdio.h>
#include <stdlib.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 valid_flag=0;
char password[1024];
while(1){
printf("pleace input password:");
scanf("%s",&password);
valid_flag=verify_password(password);
if(valid_flag==0){
printf("congratulation.You have passed the verification.\n");
break;
}
else{
printf("incorrect password\n\n");
}
}
}
1.当从键盘输入“1234567”、“12345678”、“11112222”时,程序执行完图中所标记的 strcpy 语句之后,堆栈会如何变化?此时程序的最终执行结果将会是什么?运行程序进行验证。
(1)1234567
堆栈:
0x34333231 |
0x00373635 |
00000000 00000000 00000000 00000000 |
EBP |
返回 |
执行结果为:
(2)12345678
堆栈:
0x34333231 |
0x38373635 |
00000000 00000000 00000000 00000000 |
EBP |
返回地址 |
执行结果为:
Devc++
Code clock
(3)11112222
堆栈:
0x31313131 |
0x32323232 |
11111111 11111111 11111111 00000000 |
EBP |
返回地址 |
执行结果为:
devc++
Code clock
2.当满足什么条件时,就可以在不知道真实口令的情况下绕过口令验证功能?为什么?
利用缓冲区溢出攻击,可以在不知道真实口令的情况下绕过口令验证功能。
原理分析:
程序中存在一个潜在的漏洞,即使用了 strcpy 函数将用户输入的密码复制到一个缓冲区中,从而可能导致缓冲区溢出攻击,可以通过输入比缓冲区长的密码进行攻击。
而根据本题,当输入的密码长度超过 7个字符时password的长度大于7,使用 strcpy 函数将密码复制到 buffer 数组中时,会出现缓冲区溢出问题,导致内存中的其他数据被覆盖,从而可能篡改 authenticate 的值。
程序验证:
规律:
当输入位数为12(code block位数为8),前7位值大于1234567(PASSWORD)时,可以绕过口令验证。
(strcmp(str1,str2),若str1=str2,则返回零;若str1<str2,则返回负数;若str1>str2,则返回正数。)
经分析,当就是令strcmp返回0或者正数(即 authenticate 的值为0或正数)时,可以通过缓存溢出篡改authenticate 的值为0;strcmp返回负数(即 authenticate 的值为负数)时,无法实现。
过程分析:
在输入12位密码(code blocks为8位)时,会导致缓冲区溢出。从而将authenticate 的值篡改为0。当authenticate 的值篡改为0时,便表明口令有效,而且绕过验证。
遇到问题:
在输入前7位小于1234567时,strcmp会返回负数(即 authenticate 的值为负数),在我的初步理解里, authenticate 的值为负数与正数一样同样可以被篡改。但是在实际操作中,我发现当以上情况发生时,就无法绕开口令验证。
猜测:
负数的符号位储存为1,而0与正数符号位储存为0,这可能导致缓冲区溢出无法将负数篡改成0。
检验:
对源代码进行修改,加入打印 authenticate 的值的功能。
已知1与-1的四字节二进制值如下。
1:00000000 00000000 00000000 00000001
-1:11111111 11111111 11111111 11111111
经过修改发现1被修改为0,-1被修改为-256。0与-256如下。
0:00000000 00000000 00000000 00000000
-256:11111111 11111111 11111111 00000000
对比可以得出结论,缓冲溢出将最后一个字节覆盖为0,因此-1不能被修改为0。
结论:
当输入位长为12(code block为8)时,且前7位大于等于PASSWORD(1234567)时,可以绕开口令验证。
因为利用缓冲区溢出时,可以修改authenticate 最后一个字节的储存值为0。所以仅当authenticate前3字节存储值为0,才可以将其值修改为0。对于本题便是,authenticate值为-1或任意负数,则无法完成篡改。authenticate值为正数且小于512(包括1)时,则可以完成篡改。