欢迎来到 黑吧安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

ptmalloc利用之largebin attack

来源:本站整理 作者:佚名 时间:2019-08-13 TAG: 我要投稿


 
很早之前写了largebin attack的利用方式之一的lctf2017的2ez4u的wp,但是过去了很久,都忘了。以前对于源码了解的也不够清楚,只知道个大概,并且0ctf2018的heapstorm2出现了largebin attack的第二种姿势,一直想抽时间把largebin分配与释放的过程再好好看看,把这两种方式再好好的总结下,以免后面还是忘掉。
largebin attack的方式大致有两种:
在申请largebin的过程中,伪造largebin的bk_nextsize,实现非预期内存申请。
在largebin插入的过程中,伪造largebin的bk_nextsize以及bk,实现任意地址写堆地址。
前者典型的例题是2ez4u,后者典型的例题是heapstorm2以及rctf2019的babyheap。接下来会结合源码与题目,尝试将原理与利用姿势总结清楚。
 
largebin管理机制
源码中,以不在smallbin范围中的chunk称之为largebin,smallbin的定义相关是:
#define in_smallbin_range(sz) 
  ((unsigned long) (sz) unsigned long) MIN_LARGE_SIZE)
#define NSMALLBINS         64
#define SMALLBIN_WIDTH    MALLOC_ALIGNMENT
#define SMALLBIN_CORRECTION (MALLOC_ALIGNMENT > 2 * SIZE_SZ)
#define MIN_LARGE_SIZE    ((NSMALLBINS - SMALLBIN_CORRECTION) * SMALLBIN_WIDTH)
因此在64位的系统里面大于MIN_LARGE_SIZE为64*0x10即0x400的chunk为largebin,而32位系统中大于MIN_LARGE_SIZE为64*0x8即0x200的chunk位largebin。
后面的分析过程中,主要还是基于64位的系统,所以源码分析就不再提32位了,有需要的可以借鉴64位的自行分析。
与smallbin不同的是,largebin中不再是一个index只对应一个大小的size,而是存储等差数列变化的chunk块。其相关定义如下:
#define largebin_index_64(sz)                                               
  (((((unsigned long) (sz)) >> 6) 48) ?  48 + (((unsigned long) (sz)) >> 6) :
   ((((unsigned long) (sz)) >> 9) 20) ?  91 + (((unsigned long) (sz)) >> 9) :
   ((((unsigned long) (sz)) >> 12) 10) ? 110 + (((unsigned long) (sz)) >> 12) :
   ((((unsigned long) (sz)) >> 15) 4) ? 119 + (((unsigned long) (sz)) >> 15) :
   ((((unsigned long) (sz)) >> 18) 2) ? 124 + (((unsigned long) (sz)) >> 18) :
   126)
可以看到大小为0x400对应的chunk其对应的index为(0x400>>6)+48即64,而index为64对应的范围是[0x400, 0x400+1>>6)即[0x400, 0x440),在这个级别index中,size的范围为0x40(1
size
index
[0x400 , 0x440)
64
[0x440 , 0x480)
65
[0x480 , 0x4C0)
66
[0x4C0 , 0x500)
67
[0x500 , 0x540)
68
等差 0x40

[0xC00 , 0xC40)
96
[0xC40 , 0xE00)
97
[0xE00 , 0x1000)
98
[0x1000 , 0x1200)
99
[0x1200 , 0x1400)
100
[0x1400 , 0x1600)
101
等差 0x200

[0x2800 , 0x2A00)
111
[0x2A00 , 0x3000)
112
[0x3000 , 0x4000)
113
[0x4000 , 0x5000)
114
等差 0x1000

[0x9000 , 0xA000)
119
[0xA000 , 0x10000)
120
[0x10000 , 0x18000)
121
[0x18000 , 0x20000)
122
[0x20000 , 0x28000)
123
[0x28000 , 0x40000)
124
[0x40000 , 0x80000)
125
[0x80000 , …. )
126
largebin管理的是一个范围区间的堆块,此时fd_nextsize与bk_nextsize就派上了用场。
大小对应相同index中的堆块,其在链表中的排序方式为:
堆块从大到小排序。
对于相同大小的堆块,最先释放的堆块会成为堆头,其fd_nextsize与bk_nextsize会被赋值,其余的堆块释放后都会插入到该堆头结点的下一个结点,通过fd与bk链接,形成了先释放的在链表后面的排序方式,且其fd_nextsize与bk_nextsize都为0。
不同大小的堆块通过堆头串联,即堆头中fd_nextsize指向比它小的堆块的堆头,bk_nextsize指向比它大的堆块的堆头,从而形成了第一点中的从大到小排序堆块的方式。同时最大的堆块的堆头的bk_nextsize指向最小的堆块的堆头,最小堆块的堆头的fd_nextsize指向最大堆块的堆头,以此形成循环双链表。
具体编程体验下laigebin的管理机制,首先是堆块从大到小的排序,以[0x400, 0x440)为例,源码如下:
#include
int main()
{
    char *gap;
    char *ptr0=malloc(0x400-0x10); //A
    gap=malloc(0x10);
    char *ptr1=malloc(0x410-0x10); //B
    gap=malloc(0x10);
    char *ptr2=malloc(0x420-0x10); //C
    gap=malloc(0x10);
    char *ptr3=malloc(0x430-0x10); //D
    gap=malloc(0x10);
    free(ptr2);
    free(ptr3);
    free(ptr0);
    free(ptr1);
    malloc(0x440); //trigger that sort largebin from unsorted bin to largebins
    return 0;

[1] [2] [3] [4] [5] [6] [7] [8] [9] [10]  下一页

【声明】:黑吧安全网(http://www.myhack58.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱admin@myhack58.com,我们会在最短的时间内进行处理。
  • 最新更新
    • 相关阅读
      • 本类热门
        • 最近下载