【发布时间】:2020-07-24 20:51:36
【问题描述】:
鉴于此代码:
#include <stdlib.h>
#include <stdio.h>
int main(){
char *password;
unsigned int *uid;
printf("enter password: ");
password = (char *)malloc(0x10);
uid = (unsigned int *)malloc(0x08);
*uid = 1;
fgets(password,0xa0,stdin);
printf("uid: %d\n",(unsigned long)*uid);
if (*uid == 0) {
puts("you are logged in as admin");
}
else {
puts("you are logged in as user");
}
return 0;
}
提示是尝试找到一种方法使其将 uid 输出为 0。我发现答案涉及输入长度正好为 31 个字符的任何字符串。我知道这与溢出到 uid 的字符串末尾的空字符有关,但我无法准确理解这是如何发生的。 malloc() 为密码分配 16 个字节,为 uid 分配 8 个字节,而 fgets() 尝试将最多 160 个字符放入密码中。 16 + 8 = 24 个字节,但 31 个字符的字符串将是 31 个字节,第 32 个字节是空字符。我到底错过了什么?
【问题讨论】:
-
你只为
malloc()分配了16个字节。如果您输入超过 15 个字符的fgets(),将导致未定义的行为。 -
您从未初始化
uid指向的内存,因此访问*uid也会导致未定义的行为。 -
问题不清楚。为什么你认为它会将 uid 输出为 0?密码中的终止 null 只是一个字节,但
int通常至少是 4 个字节。也不能保证malloc()会在内存中分配password和uid。 -
在导致未定义行为时试图获得特定结果是徒劳的。
-
您正在学习或练习利用程序中的缺陷吗?您正在尝试制作溢出缓冲区并导致特定输出的输入?如果是这样,那很大程度上取决于具体情况,包括编译器、特定源代码和编译选项。
uid对象相对于password对象的位置可能取决于malloc实现,但编译器也可能对其进行优化,因为它可以从源代码中看到*uid“应该是”1,所以它可以将printf("uid: %d\n",(unsigned long)*uid);更改为puts("uid: 1");。
标签: c malloc overflow fgets exploit