考虑这个 Linux 中的堆缓冲区溢出易受攻击程序的示例,直接取自“缓冲区溢出攻击”(第 248 页)一书:
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv)
{
char *A, *B;
A = malloc(128);
B = malloc(32);
strcpy(A, argv[1]);
free(A);
free(B);
return 0;
}
由于 unlink() 已被更改以防止最简单形式的利用 FD 和 BK 指针进行完整性检查,因此我使用的是一个非常旧的系统,我使用的是旧版本的 glibc(版本 2.3.2)。我还为此测试设置了 MALLOC_CHECK_=0。
这个玩具示例的目标是简单地查看是否可以将 4 个字节写入我指定的任意地址。我能想到的最简单的测试是尝试向 0x41414141 写入一些东西,这是一个非法地址,应该让程序崩溃以向我确认它确实在尝试写入这个地址(我应该能够观察到在 GDB 中)。
所以我尝试使用参数执行perl -e 'print "A"x128 . "\xf8\xff\xff\xff" . "\xf8\xff\xff\xff" . "\x41\x41\x41\x41" . "\x41\x41\x41\x41" '
所以我有:
Buffer A: 128 bytes of 0x41.
prev_size: 0xfffffff8
size: 0xfffffff8
FD: 0x41414141
BK: 0x41414141
我使用 0xfffffff8 而不是 0xfffffffc 因为有一个注意事项,在 glibc 2.3 中,第三个最低位 NON_MAIN_AREA 用于竞技场的管理目的,并且必须为 0。
这应该尝试将 0x41414141 写入 0x41414141(+ 12 更正确,但仍然是非法地址),对吗?但是,当我执行此操作时,程序只是正常终止。
我在这里想念什么?这似乎很简单,以至于开始工作应该不那么难。
我尝试了各种方法,例如使用 0xfffffffc 代替 prev_size 和 size,使用 FD 的合法地址(堆上的某个地址)。我尝试交换顺序 A 和 B 是 free()'d,我尝试进入 free() 以查看 GDB 中发生了什么,但我迷路了。请注意,此系统上不应该有任何其他安全功能,因为它非常旧并且没有 NX 位、ASLR 等(这对于仅将 4 个字节写入非法地址而言并不重要) .
关于如何完成这项工作的任何想法?
我可以补充一点,如果使用 MALLOC_CHECK_=3 我得到这个:
malloc: using debugging hooks
malloc: using debugging hooks
free(): invalid pointer 0x8049688!
Program received signal SIGABRT, Aborted.
0x4004a1b1 in kill () from /lib/libc.so.6