用15行C代码实践UAF导致堆基地址的泄漏

代码如下:

用15行C代码实践UAF导致堆基地址的泄漏
文章图片
image.png 【用15行C代码实践UAF导致堆基地址的泄漏】实验环境:ubuntu 16.04 64位(但是实验用的程序是32位的),gdb(linux上的命令行调试器)带插件peda环境
首先,先学习两个名词:
通过malloc函数创建的空间,我们称之为内存块,简称块(chunk), 块被free()后,成为空闲块
问题:什么是UAF。
答:Use After Free。指的是一个块被free()后,如果再malloc()一段块时,会判断malloc()的块的空间大小是否等于或小于前一个被free()的块,如果是则,将空闲块的空间分配给,此时malloc()的块。看下图:
用15行C代码实践UAF导致堆基地址的泄漏
文章图片
image.png 我们回到一开始的代码:一开始我malloc()了4个空间大小为0x80的块。我利用gdb,查看这四个块。在汇编中函数的返回值都会先保存在EAX这个寄存器上。如下图,刚执行完malloc(),记下它的返回值0x804b008,这是变量p1的值。但是块的真地址应该为0x804b000。
为什么?请继续往下看。

用15行C代码实践UAF导致堆基地址的泄漏
文章图片
1522401193(1).jpg 当四个块malloc()完后利用gdb 指令查看它们,如下图。一眼看过去全是0。但是希望有人注意到:图中一共又4个“89”。

用15行C代码实践UAF导致堆基地址的泄漏
文章图片
image.png
为了更方便的查看,我把源码修改一下。如下:

用15行C代码实践UAF导致堆基地址的泄漏
文章图片
image.png
编译调试查看如下图。
0x41='A',0x42='B',0x43='C',0x44='D'
用15行C代码实践UAF导致堆基地址的泄漏
文章图片
image.png
根据图,再解释一下。其实在malloc()一个空间大小0x80的块时,系统分配的块的大小实际上是0x88。这多出来的8个字节用申明当前块的大小。但是图中为什么显示是‘89’呢。这解释起来有点长,而且脱离了本文章的主旨,简单的说来就是当块被free()后,就变‘88’了
接下来就来看看p3,p1块被free()后,内存发生了什么。先来看看p3被free(),如下图,一看我们strcpy()进的9个‘C’被覆盖了8个剩下一个‘C’了:

用15行C代码实践UAF导致堆基地址的泄漏
文章图片
image.png
现在free(p1)。看下图。图1是p3块附近的数据,图2是p1块赴京的数据:
用15行C代码实践UAF导致堆基地址的泄漏
文章图片
image.png
图1
用15行C代码实践UAF导致堆基地址的泄漏
文章图片
image.png
图2
在图1看到了我们堆的基地址0x804b000。之所有会出现基地址是由于linux中系统对空闲块的管理产生的。linux对不同大小的的空闲块有着不同的管理方式。而这里我们仅以空间大小为0x80的块来做实验,对于0x80块,是linux系统用双链表的数据结构来进行对空闲块的管理,所以会看到0x804b000(原p1块的地址),0x804b110(原p3块的地址)。
接下来我们malloc()一个空间大小为0x80的块,看看它的内存数据。
用15行C代码实践UAF导致堆基地址的泄漏
文章图片
image.png
p1[0]:

用15行C代码实践UAF导致堆基地址的泄漏
文章图片
image.png
p[1]:
用15行C代码实践UAF导致堆基地址的泄漏
文章图片
image.png 看到的数据就知道现在的p1块就是一开始的p3块,这时后就产生了UAF。将数据prinrf()出来导致堆的基地址泄漏。

    推荐阅读