二进制漏洞——堆溢出学习(DWORD SHOOT)

基础概念

  • 空闲双向链表(空表)
    • 空闲堆块的块首中包含一对重要的指针,这对指针将空闲堆块组成双向链表。空表总共128条,按堆块大小区分。这里需要注意空表第一项(零号空表)是将所有大于等于1024字节 的堆块链接起来

  • 快速单向链表(快表)

    • 快速单向链表也是128条,组织结构与空表类似,是Windows用来加速堆块分配而采用的分配方式,这类单向链表其中的空闲块块首会被设置为占用态,不会发生堆块合并。且每条单向链表最多4个节点。

使用堆

  • 堆块分配

    • 堆块分配大致分为三类:快表分配、普通空表分配、零号空表分配。
  • 堆块释放

    • 将堆块状态改为空闲、链入相应的堆表。所有释放块都链入堆表的末尾,分配的时候也是先从末尾拿。
  • 堆块合并

    • 经过反复的申请与释放操作,产生了很多内存碎片,为了更有效的利用内存,堆管理系统进行堆块合并操作。当发现两块空闲堆块彼此相邻时,就会进行堆块合并操作。包括将两个块从空表中卸下、合并堆块、调整合并后块首信息、重新装入空表。

DWORD SHOOT概念

下图是正常情况下将堆块从空表中卸载的流程

假设有三个相邻双向链表节点分别名为A、B、C,卸载的流程就是将A的前节点指向C,且把C的后节点指向A。这样B节点就被卸载下来。

DWORD SHOOT的实现就是在这个过程中构造溢出实现任意地址写四个字节恶意数据,

即将B的后节点指向任意地址,将B的前节点改为四字节恶意数据。在拆卸堆块时实现向任意地址写入四字节的恶意数据