【pwn学习】堆溢出(一)

学习这部分之前,如果对堆的基础还不甚了解可以参考一下下面的学习笔记

什么是堆溢出

堆溢出是指程序向某堆块(chunk)中写入的字节数超过了堆块本身可使用的字节数,因而导致了数据溢出,并覆盖到物理地址相邻的高地址的下一个堆块。这里之所以是可使用而不是用户申请的字节数,是因为堆管理器会对用户所申请的字节数进行调整,这也导致可利用的字节数大于等于用户申请的字节数。

ptmalloc 分配出来的大小是对齐的。这个长度一般是字长的 2 倍,比如 32 位系统是 8 个字节,64 位系统是 16 个字节。但是对于不大于 2 倍字长的请求,malloc 会直接返回 2 倍字长的块也就是最小 chunk,比如 64 位系统执行malloc(0)会返回用户区域为 16 字节的块。

因此,要利用堆溢出要满足两个前提

  • 程序向堆上写数据;
  • 写入的数据大小没有被控制;

与栈溢出的不同在于,堆上没有返回地址等让攻击者直接控制执行流程的数据,因此一般我们无法通过堆溢出来控制EIP。所以攻击人用来利用的方式一般如下

  1. 覆盖与其物理相邻的下一个chunk的内容。
    • prev_size;
    • Size.
    • Chunk content
  2. 利用堆中的机制(如 Unlink等)来实现任意地址写入(Write-Anything-Anywhere)或控制堆块中的内容等效果,从而来控制程序的执行流。

基本示例

// example-1.c
#include <stdio.h>

int main(void) 
{
  char *chunk;
  chunk=malloc(30);
  puts("Get input:");
  gets(chunk);
  return 0;
}

利用gdb调试,malloc执行后chunk的mem指针eax=0x804d1a0

Allocated_chunk

 chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         |             Size of previous chunk, if unallocated (P clear)  |
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         |             Size of chunk, in bytes                     |A|M|P|
   mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         |             User data starts here...                          .
         .                                                               .
         .             (malloc_usable_size() bytes)                      .
         .                                                               |
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         |             (size of chunk, but used for application data)    |
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
         |             Size of next chunk, in bytes                |A|0|1|
         +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

查看内存,根据allocated_chunk的结构,储存地址的上面4个字节是chunk的size。

pwndbg> x/30x 0x804d1a0-0x4
0x804d19c:      0x00000031      0x00000000      0x00000000      0x00000000
0x804d1ac:      0x00000000      0x00000000      0x00000000      0x00000000
0x804d1bc:      0x00000000      0x00000000      0x00000000      0x00000000
0x804d1cc:      0x00000411      0x20746547      0x75706e69      0x000a3a74
0x804d1dc:      0x00000000      0x00000000      0x00000000      0x00000000
0x804d1ec:      0x00000000      0x00000000      0x00000000      0x00000000

执行gets,输入100个‘a’后查看内存

pwndbg> x/30x 0x804d1a0-0x4
0x804d19c:      0x00000031      0x61616161      0x61616161      0x61616161
0x804d1ac:      0x61616161      0x61616161      0x61616161      0x61616161
0x804d1bc:      0x61616161      0x61616161      0x61616161      0x61616161
0x804d1cc:      0x61616161      0x61616161      0x61616161      0x61616161
0x804d1dc:      0x61616161      0x61616161      0x61616161      0x61616161
0x804d1ec:      0x61616161      0x61616161      0x61616161      0x61616161
0x804d1fc:      0x61616161      0x61616161      0x00000000      0x00000000
0x804d20c:      0x00000000      0x00000000

可以发现原chunk后面跟的内存被覆盖了。

堆分配函数

  • calloc

calloc 与malloc的功能类似,都是用来分配内存的。calloc 与 malloc 的区别是 calloc 在分配后会自动进行清空,这对于某些信息泄露漏洞的利用来说是致命的

calloc(0x20);
//等同于
ptr=malloc(0x20);
memset(ptr,0,0x20);
  • relloc

realloc 函数可以身兼 malloc 和 free 两个函数的功能。

  • 当 realloc(ptr,size) 的 size 不等于 ptr 的 size 时

    • 如果申请 size > 原来 size
      • 如果 chunk 与 top chunk 相邻,直接扩展这个 chunk 到新 size 大小
      • 如果 chunk 与 top chunk 不相邻,相当于 free(ptr),malloc(new_size)
    • 如果申请 size < 原来 size
      • 如果相差不足以容得下一个最小 chunk(64 位下 32 个字节,32 位下 16 个字节),则保持不变
      • 如果相差可以容得下一个最小 chunk,则切割原 chunk 为两部分,free 掉后一部分
  • 当 realloc(ptr,size) 的 size 等于 0 时,相当于 free(ptr)

  • 当 realloc(ptr,size) 的 size 等于 ptr 的 size,不进行任何操作

堆填充长度

填充长度 = 要覆盖的地址 - 开始写入的地址

利用基本示例,来尝试一下,以下示例均为32位程序

  • Malloc(0)

32位下最小的chunk大小为16个字节,而64位下最小的chunk大小为32个字节。

而chunk的大小包含了prev_size 4个字节和 size4个字节,因此此时分配的空间大小为8个字节。

那么此时可利用的空间就是8个字节了吗?

并不是。chunk的prev_size只有前一个chunk处于释放状态时才起作用,否则时可以用来给前一个chunk作为存储空间的。因此当malloc的参数是0时,实际的利用空间有12个字节。

pwndbg> x/20x 0x804d190
0x804d190:      0x00000000      0x00000000      0x00000000      0x00000011
0x804d1a0:      0x00000000      0x00000000      0x00000000      0x00021e59
0x804d1b0:      0x00000000      0x00000000      0x00000000      0x00000000
  • malloc(24)

chunk在分配空间的时候是以最小的chunk大小(16字节)增长的,24 = 16 + 8 因此,正好分配了24个字节的空间。但此时的利用空间还要包含前一个chunk的prev_size,因此实际利用空间为28个

pwndbg> x/20x 0x804d190
0x804d190:      0x00000000      0x00000000      0x00000000      0x00000021
0x804d1a0:      0x00000000      0x00000000      0x00000000      0x00000000
0x804d1b0:      0x00000000      0x00000000      0x00000000      0x00000411
0x804d1c0:      0x20746547      0x75706e69      0x000a3a74      0x00000000
  • Malloc(28)

此时的内存分配和上一的分析是一样的,由于可利用空间的大小满足用户的申请空间,因此不需要额外增加内存空间。

pwndbg> x/20x 0x804d190
0x804d190:      0x00000000      0x00000000      0x00000000      0x00000021
0x804d1a0:      0x00000000      0x00000000      0x00000000      0x00000000
0x804d1b0:      0x00000000      0x00000000      0x00000000      0x00000411
0x804d1c0:      0x20746547      0x75706e69      0x000a3a74      0x00000000

  • Malloc(29)

此时可利用空间增了一个最小chunk的大小

pwndbg> x/20x 0x804d190
0x804d190:      0x00000000      0x00000000      0x00000000      0x00000031
0x804d1a0:      0x00000000      0x00000000      0x00000000      0x00000000
0x804d1b0:      0x00000000      0x00000000      0x00000000      0x00000000
0x804d1c0:      0x00000000      0x00000000      0x00000000      0x00021e39
0x804d1d0:      0x00000000      0x00000000      0x00000000      0x00000000

堆攻击总结

接下来一段时间将按照heap-exploitation book介绍的顺序来学习堆溢出攻击。

攻击方式目标技巧
First FitThis is not an attack, it just demonstrates the nature of glibc’s allocator
Double FreeMaking malloc return an already allocated fastchunkDisrupt the fastbin by freeing a chunk twice
Forging chunksMaking malloc return a nearly arbitrary pointerDisrupting fastbin link structure
Unlink ExploitGetting (nearly)arbitrary write accessFreeing a corrupted chunk and exploiting unlink
Shrinking Free ChunksMaking malloc return a chunk overlapping with an already allocated chunkCorrupting a free chunk by decreasing its size
House of SpiritMaking malloc return a nearly arbitrary pointerForcing freeing of a crafted fake chunk
House of LoreMaking malloc return a nearly arbitrary pointerDisrupting smallbin link structure
House of ForceMaking malloc return a nearly arbitrary pointerOverflowing into top chunk’s header
House of EinherjarMaking malloc return a nearly arbitrary pointerOverflowing a single byte into the next chunk
  • 1
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Morphy_Amo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值