内容简介:本篇文章是该系列的第二篇,第一篇是glibc漏洞利用基础知识。在上一篇文章中我们提到过,堆管理将保留关于空闲块的元数据,以便这些空闲块可以被重新分配。为了补充我在上一篇文章中的说法,我在这篇文章中会提到针对不同大小的空闲块,会有不同类型的链表来管理,即如下这些链表:
本篇文章是该系列的第二篇,第一篇是glibc漏洞利用基础知识。
在上一篇文章中我们提到过,堆管理将保留关于空闲块的元数据,以便这些空闲块可以被重新分配。为了补充我在上一篇文章中的说法,我在这篇文章中会提到针对不同大小的空闲块,会有不同类型的链表来管理,即如下这些链表:
· Unsorted Bin -这个链表用来临时保存那些不属于Fast,Large或者Small bin分类的块。在这里引用某大牛论文中关于此的说法:当释放不在fastbin范围内的块时,这些块就被划到了未分类的bin中,而不会划分到small bins或者large bins中。
论文下载地址: https://loccs.sjtu.edu.cn/wiki/lib/exe/fetch.php?media=gossip:overview:ptmalloc_camera.pdf
· Small bins -正如其他链表一样,这只是另一个链表或者是一组链表,用来保存特定大小的空闲堆块。而这个大小的阈值可能因架构和glibc实现或者是build不同而有所变化。不过,最基本的一点是他们比Fast Bins大,比Large Bins小。我会在以后的文章中再来讲述关于这个的更多细节。
· Large Bins -比最大值还大的块,我现在搞得还不是很明白,所以也留在以后的文章中再讲。
· Fast Bins -本文的重点,保存的是所有小于特定最大块的空闲块。
这里之所以选择讲解Fastbin中的块,是因为它们是作为malloc_chunk基本格式的扩展,而malloc_chunk格式用于普通的未分类的或正常大小的堆块,并且它们也有一些很不错的技巧我们可以尝试一下。所以,本文不会讲解large chunks,只是目前不讲,不过以后等我有了足够的数据,我还是会分析一波。
好了,不叨叨了,开始讲fastbins吧。
Fast Bin格式
Fastbins其实也是内存中的一个堆块。
Fastbins是为小的内存对象保留的(小的结构和字符串)。fastbin的思想就是,这些块大小是能够从常规的计算开销中获得一些优势的,如果不使用的话,那么你使用的仅仅是符合所请求大小的小内存区域的简单链表。根据目前关于堆的研究,Fastbins是不同大小的fast bins的集合,(所以不只是简单的单一链表,对于每种大小的组,可能会有很多fastbins在操作),这里再引用一篇论文中的观点:
“Fastbin是一种针对性能和局部缓存进行了优化的特殊设计。它是一个单独链表,类似于Windows的look aside表格,其中相同大小的空闲块以LIFO方式链接。不同fastbins的块大小各不相同。在arena中有共有10个fastbins,但默认情况下使用前7个,在32位系统上为16到64个字节,在64位系统上为32到128个字节 “
论文地址:
https://loccs.sjtu.edu.cn/wiki/lib/exe/fetch.php?media=gossip:overview:ptmalloc_camera.pdf
还有一点我要提醒的是,如果fastbins被释放了,它们是不会合并的。在glibc- [版本] /malloc/malloc.c的文档中有更多关于fastbins的精彩内容。我建议大家可以去通读一遍 – 我这里就不进行复制了。
好了,关于fastbins的介绍部分就扯这么多了,现在我们来看看它们到底是什么东西以及它们的工作原理。
关于fastbins大小的阈值在 malloc/malloc.c 中进行了定义。就像glibc-2.23中一样,它的定义是这样的:MAX_FAST_SIZE = (SIZE_SZ * 80)/ 4,最大值为80个字节。因此,任何低于80字节的数据都会被分配到fastbins中。
下图是内存中fastbins的一个链表,可以很好的展示fastbins的格式:
在这个示例图片中,它也比较了一个非fastbins的块,只是一个普通的大块,大小为0xb0 (内存指针分配的第一个块,位置是0x602010) – 这是为了更加清楚的显示格式之间的区别。
在图片左侧,你可以看到“live”的fastbin块(从0x6020b0开始)。除了它们的大小之外,在这种状态下,不能把它们像fastbin一样分配出去。在图片右侧,你可以看到被释放的空闲fastbins块; 这里需要注意的一个关键事项是它们有一个后向指针(形成一个fastbin块的链表),指示下一个空闲fastbins块的位置。
还有一点你可能也会注意到,这个例子中:在内存中彼此相邻的fastbin'd块是空闲的; 但是大小字段都没有重叠,也没有块合并在一起。如前所述,他们不会合并。
OK,现在我们知道它们在内存中的格式,我们再来谈谈另一个重要机制,也就是fastbin first fit。
Fastbin First Fit
fastbins的重新分配规则略有不同。当他们进行重新分配时,他们位于后进先出的队列中。这意味着,如果我们一个接一个的将它们释放出来,那么第一个返回重新分配的块将会是系列中最后一个释放的。
在下面的内存分布图片中,图片左边显示了在调用malloc之前和所有fastbin块被释放之后的堆状态。右边是第二个malloc(或重新分配)被调用后的堆。所以我们基本上能够看到哪些fastbin块被返回和使用,以及它们的顺序(主要是因为我使用程序将一些信息写入堆块 – 每个分配写入0xAA,0xBB按照它们分配的顺序进入堆中):
你应该能够很容易地找出最先返回的块。另请注意显示在释放列表中的指针; 这些0x602yyy 在堆块中的值是malloc_chunk-> bk指针。
毫无疑问,你的下一个问题是我们如何让它返回一个我们想要的指针,或者我们如何影响空闲块,比方说,强制返回某个指定的空闲块?当我们“在使用中”时覆盖这些信息然后查看返回哪个fastbin时会发生什么?这里我们提供了下面这个测试方案:
1.释放一些块
2.重新指向fastbins 的malloc_chunk-> bk指针
3.看看哪些可用的块被写入0x4242 (这个0x4242 / 0x4141纯粹是因为我让这个程序对我有所帮助)
我们来看看这些块在内存中的视图:
解释一下。
首先,我用set {size_t} 0x602100 = 0x0000000000602000命令覆盖bk指针。这基本上告诉堆在返回第一个fast bin后(LIFO中的第一个fastbin在0x6020f0位置处),指针应该根据链表指向下一个空闲的fastbin,它位于0x0602000。
下一个截图显示了如何重定向分配; 它不是在最底层的上方分配下一个块,而是一直跳到顶部:
可以清楚地看到,我们只是重定向堆重新分配!链表权现在属于我们!!
你也可以将堆重定向到内存中可写可读部分中的其他位置的伪块。为此,需要做到如下几点:
1.释放所有的fastbins
2.就在第一次重新分配之前; 重新指向首先适合你的伪fastbin的fastbin
例如:set {size_t} 0x602100 = 0x601050 (这会将块的bk指针设置为0x6020f0 )
3.将fast bin的大小设置为可接受的值,这里我只是回收与被替换的fast bin相同的大小,如下所示:set {size_t} 0x601058 = 0x0000000000000051
下面的截图展示了这一点。
我们可以在0x6010yy地址区域中看到一个奇怪的堆块,而其余的块在0x6020yy范围内:
这并不是一个完整的安全漏洞,但它确实让我们更加接近一个漏洞。它还让我们学到了一个重要的小技巧,就是让堆去做一些奇怪的事情。
好了,本文就到这里,我将在下一篇文章中介绍更多关于堆元数据的内容。敬请关注!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 漏洞分析:对CVE-2018-8587(Microsoft Outlook)漏洞的深入分析
- MacOS/iOS CVE-2019-6231 漏洞深入分析
- 由Typecho 深入理解PHP反序列化漏洞
- 深入分析Windows系统DHCP漏洞(CVE-2019-0726)
- 对CVE-2018-8587(Microsoft Outlook)漏洞的深入分析
- Apache Tomcat从文件包含到RCE漏洞原理深入分析
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Web Anatomy
Robert Hoekman Jr.、Jared Spool / New Riders / 2009-12-11 / USD 39.99
At the start of every web design project, the ongoing struggles reappear. We want to design highly usable and self-evident applications, but we also want to devise innovative, compelling, and exciting......一起来看看 《Web Anatomy》 这本书的介绍吧!