【问题标题】:How do I use formatstring to print out a string?如何使用 formatstring 打印出字符串?
【发布时间】:2012-09-29 22:59:59
【问题描述】:

我正在阅读有关格式字符串漏洞的教程,以了解如何更安全地编码。目前我写的程序如下:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
    char text[100];
    strcpy(text, argv[1]);

    printf(text);
}

我是这样运行的:

>>> ./foo $(ruby -e 'print "AAAA" + "%08x."*9 + "%x"')
AAAAffe466f4.00000001.f763b1c9.ffe458df.ffe458de.00000000.ffe459c4.ffe45964.00000000.41414141

我可以在末尾看到“41414141”,也就是字符串开头的 AAAA。但是,当我像这样使用“%s”时:

>>> ./foo $(ruby -e 'print "AAAA" + "%08x."*9 + "%s"')

我得到一个段错误。谁能指出我正确的方向?

【问题讨论】:

    标签: c security format-string


    【解决方案1】:

    问题是,此时,您在堆栈上达到原始 AAAA;但是,%s 说明符需要一个指向字符串的 指针,即您的 AAAA 的地址。您想要执行的操作没有格式字符串说明符,因为在正常执行过程中您不会将字符串直接粘贴为 printf() 的参数;一个想法是%c%c%c%c 至少将数据打印为字符而不是十六进制值,但这也不起作用,因为 C 中参数的最小大小是 int 甚至 @987654323 @ 说明符适用于 int 大小的参数内存区域。

    【讨论】:

    • 感谢您的帮助!现在,我正在尝试: ./foo $(ruby -e 'print "\x7f\x2a\x96\xff" + "%08x."*9 + "%s"') 但我仍然遇到段错误.这应该是一个指向字符串的有效指针,我想,我修改了程序以打印出变量的地址。是否与 64 位地址更长有关?
    • 我认为您现在的问题是 endianity - 尝试颠倒指针的字节顺序。
    • 啊,这不是字节序,而是堆栈随机化。非常感谢您的帮助!
    【解决方案2】:

    在动态字符串上使用printf 通常是未定义的行为,因为您不能保证字符串没有格式说明符。正确的说法是,

    printf("%s", text);
    

    或者只是

    puts(text);
    

    现在,也就是说,您的第一个示例归结为 printf("%x%x");。这当然是 UB,但两个 %x 说明符只会让您从堆栈中读取有限的数量(两个字),这将打印垃圾,但只有有限的数量。

    另一方面,当您说printf("%s") 时,该函数需要一个指针,该指针指向您无法控制的内存区域中的以空字符结尾的字节序列!本质上,该函数将从堆栈中读取一个字,假装它是一个指针,然后读取该值指向的内存——这几乎肯定会导致分段错误,因为您不允许通过以下方式访问大多数内存地址默认。即使地址指向您被允许访问的内存,也没有理由很快就会出现零字节,因此您很可能会跑出页面并进入非法内存。

    【讨论】:

      【解决方案3】:

      test 中你最后有%sprintf 在遇到 %s 时需要 char 指针,但您没有提供任何 --> 段错误。请改用putsprintf("%s", test);

      $ ruby -e 'print "AAAA" + "%08x."*9 + "%x"'
      AAAA%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%x
      
      $ ruby -e 'print "AAAA" + "%08x."*9 + "%s"'
      AAAA%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%s
      

      printf 的两个字符串都无效,因为您没有传递所需的参数。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-03-30
        • 2015-12-31
        • 2015-04-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-25
        相关资源
        最近更新 更多