我正在从我的书“黑客:剥削的艺术”中学习格式字符串攻击。 我有这个小程序,这是代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
char text[1024];
static int test_val = -72;
if(argc < 2) {
printf("Usage: %s <text to print>\n", argv[0]);
exit(0);
}
strcpy(text, argv[1]);
printf("The right way to print user-controlled input:\n");
printf("%s", text);
printf("\nThe wrong way to print user-controlled input:\n");
printf(text);
printf("\n");
// Debug output
printf("[*] test_val @ 0x%016x = %d 0x%08x\n", &test_val, test_val, test_val);
exit(0);
}
我想在我的程序中输入地址并打印出来。地址为0x00600b98
,因为输入"\x98\x0b\x60\x00"
这是我的bash代码:
./fmt_vuln $(python -c 'print "\x98\x0b\x60\x00"')%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.
但问题是,第一个地址(\ x00)变为空并且没有输入到我的地址,当打印内存时它变为25600b98
。所以我的问题是,为什么会出现这个问题以及如何输入00的地址?
这是输出:
The right way to print user-controlled input:
�
`%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.
The wrong way to print user-controlled input:
�
`f7ff5000.f7dd7970.f7b128c0.f7fd8700.0000002b.ffffe3b8.f7ddb72d.25600b98.
[*] test_val @ 0x0000000000600b98 = -72 0xffffffb8
答案 0 :(得分:0)
这是因为空字节(/ x00),至少在C中,用于终止字符串。因此,当你printf
时,它们被解释为字符串的结尾。
可以找到关于此的一个很好的解释,以及有关如何将空字节正确合并到代码中的信息here。
我希望这会有所帮助。
答案 1 :(得分:0)
argv[1]
指向内容为"\x98\x0b\x60\x00"
的字符数组。请注意,这是5个字节:4加上空字符。
以下代码仅复制到达到空字符,这导致只复制4个字节,因为argv[1][3]
是空字符。
strcpy(text, argv[1]);
建议添加可选的第二个参数,并使用指示长度的附加参数调用程序。
size_t size = 0;
if (argc > 2) {
long i = atol(argv[2]);
if (i >= 0 && i < SIZE_MAX) {
size = (size_t) i;
}
else {
size = strlen(argv[1]) + 1;
}
// strcpy(text, argv[1]);
memcpy(text, argv[1], size);
请注意,以下代码仍将仅打印到前3个字符
printf("%s", text);
printf(text); // UB if it contains '%'
BTW:建议在printf(text);
之前进行调试输出并修复其不匹配的格式
// printf("[*] test_val @ 0x%016x = %d 0x%08x\n", &test_val, test_val, test_val);
printf("[*] test_val @ 0x%016x = %d 0x%08x\n",
(unsigned) &test_val, test_val, (unsigned) test_val);
// or
printf("[*] test_val @ %p = %d 0x%08x\n",
(void*) &test_val, test_val, (unsigned) test_val);