为什么这段代码可以被利用?

时间:2012-04-09 21:11:18

标签: c security

为什么此代码不安全?

#include <stdio.h>
int main( int argc, char *argv[] )
    {
       printf(argv[1]);
       printf("\n");
       return 0;
    }

5 个答案:

答案 0 :(得分:5)

printf将处理其第一个参数,查找%d%s等内容。

根据这些值,它将从堆栈中获取更多数据并将其打印出来。

所以如果有人打电话给你的程序:

a.out "%d %d %d %d %d %d %d %d %d %d %d %d"

他们可以查看计算机的一部分callstack。

如果他们使用格式说明符更有创意,也许他们可以转储重要内容,例如信用卡号或密码。

答案 1 :(得分:4)

考虑printf控件的第一个参数(提示:printf不只是读取其输入参数)。

答案 2 :(得分:4)

了解什么是格式字符串漏洞:

http://en.wikipedia.org/wiki/Uncontrolled_format_string

答案 3 :(得分:1)

答案 4 :(得分:1)

由于海报要求提供%n所做的一个例子:

printf格式字符串更改内存的方式是使用%n选项;可以通过“明智地”使用格式宽度说明符来获得要写入的特定值。作为测试:

#include <stdio.h>

int main(int argc, char **argv)
{
    int *q = (int *)argv[0];
    printf("%1$300000d%5$n",
        123,         // %1 - 1st param (formatted as '300000d')
        0,           // %2 - 2nd param (unused)
        0,           // %3 - 3rd param (unused)
        0,           // %4 - 4th param (unused)
        argv[0]);    // %5 - 5th param (written to via 'n')

    printf("\nNow *q == %d\n", *q);

    return 0;
}

如果你运行它并查看输出的最后一行,它将打印Now *q == 300000(在Linux上测试)。

我正在使用% $&lt; pos&gt; printf()&lt; fmt&gt;)的printf()&lt; fmt&gt;)来为printf(argv[1])按顺序排列显示如何跳过参数来选择修改哪一个而不需要使用任何“无趣的”。

我会留给读者进行实验,以确定{{1}}对{{1}}这样的调用所谓的“论点”。答案取决于calling conventions(或相关的,系统的ABI),32 / 64bit Windows / Linux / MacOSX等不同。