《0day安全》堆基础知识的学习

power by 《0day安全:软件漏洞分析技术》

其实里面基础的部分确实有很多我们操作系统课堂上学习的知识

基础的知识就不打出来了

堆的调试方法

写代码少不了

#include <windows.h>
int main(int argc, char const *argv[])
{
   // handle to local memory object(本地内存对象句柄)
   HLOCAL h1, h2, h3, h4, h5, h6;
   HANDLE hp;
   // The HeapCreate function creates a heap object that can be used by the calling process.
   // 创建一个堆对象,可被调用者使用
   hp = HeapCreate(0, 0x1000, 0x10000);
   __asm int 3
   // The HeapAlloc function allocates a block of memory from a heap. The allocated memory is not movable. 
   // HEAP_ZERO_MEMORY -----> Specifies that the allocated memory will be initialized to zero. Otherwise, the memory is not initialized to zero. 
   // 最后一个参数是申请的字节数 number of bytes to allocate
   h1 = HeapAlloc(hp, HEAP_ZERO_MEMORY, 3);
   h2 = HeapAlloc(hp, HEAP_ZERO_MEMORY, 5);
   h3 = HeapAlloc(hp, HEAP_ZERO_MEMORY, 6);
   h4 = HeapAlloc(hp, HEAP_ZERO_MEMORY, 8);
   h5 = HeapAlloc(hp, HEAP_ZERO_MEMORY, 19);
   h6 = HeapAlloc(hp, HEAP_ZERO_MEMORY, 24);
   // free block and prevent coaleses(我觉得这个英文有问题coalesce才对吧)
   // The HeapFree function frees a memory block allocated from a heap by the HeapAlloc or HeapReAlloc function. 
   HeapFree(hp, 0, h1); // free to freelist[2]
   HeapFree(hp, 0, h3); // free to freelist[2]
   HeapFree(hp, 0, h5); // free to freelist[4]
   HeapFree(hp, 0, h4); //coaleses h3,h4,h5,link the large block to freelist[8]
   return 0;
}

调试堆不能用od等软件直接打开,因为堆管理函数检测到调试状态,就会使用调试态堆管理策略

不同点

  1. 调试堆不使用快表,只用空表分配

  2. 所有的堆块被加上了多余的16字节尾部来防止溢出(防止程序溢出而不是堆溢出),包括8个字节的0xAB和8个字节的0x00

  3. 块首的标志位不同

所以在源码中我们在创建堆之后加入一个人工断点 int 3,

当堆初始化完,断点就中断程序,这时再用调试器attach,就看到真实的堆了

首先我们选择编译成release版

blob.png

首先将od设置成实时调试器

blob.png

运行

blob.png

点击取消,停在了int 3blob.png

去内存模块看看

blob.png

看不到书本那里的HeapCreate创建的

我们看看前面的返回值

blob.png

怎么隐藏那么深呢

blob.png

识别堆表

程序在初始化,malloc使用的堆和进程堆已经经过若干次分配和释放操作,里面比较“凌乱”,用HeapCreate创建的就比较“整齐”

用一下heap_vis插件查看堆块,结果就是没结果

blob.png

那我们直接到内存取查看吧,ctrl+g

blob.png

从3A0000开始包含的信息依次是段表索引,虚表索引,空表使用标识和空表索引区

不懂啊,0x178偏移是空表索引区,其余跟堆溢出利用关系不大,先不学咯

blob.png

去3A0688看看

blob.png

当前块的大小,是块首的前两个字节,0x130,但是单位是8个字节,就是0x980字节(堆的大小包含块首在内)

快表据说在0x584,这里为NULL,因为我们这样创建的堆没扩展性,HeapCreate(0,0,0)就可以

blob.png

堆块的分配

注意分配时8字节对齐的,不足的就给足8字节,还有块首还有8字节,所以申请2字节,最终分配16字节

我们单步到前6次分配

blob.png

结果发现,原版的才能用

blob.png看一下第一次分配的时候

blob.png

可以看到前四个都是分配16字节

继续

blob.png

堆块的释放

前三次释放内存不连续,所以不会合并,先释放h1看看

下图是16字节才对,要加上块首8字节嘛

blob.png

通过实验发现h3插在了h1的链表前面

blob.png

我们可以去看看空表所以 0x178处

blob.png

堆的合并

原来h3的堆首大小被改写,前向指针和后向指针指向freelist[8]

blob.png

合并只是修改了块首的数据

块表的使用

再来一个程序,改一下创建堆时候,参数变成0,0,0就好,还有就是改改分配大小修改一下

blob.png

blob.png

那么快表就是在0x688了,去看看

blob.png

8字节插入到lookaside[1],16就[2],24就[3]

blob.png

那我们到8字节的那个地方看看

blob.png

当我们再申请16字节,就从块表中取了,之前释放优先放到块表中,直到满了四个

所以我们再申请,就先从块表获取了

blob.png

而且申请的返回值就是之前块表储存的地址,可以看前上上上张图

blob.png

打赏
微信
支付宝
微信二维码图片

微信扫描二维码打赏

支付宝二维码图片

支付宝扫描二维码打赏

《0day安全》堆基础知识的学习》上有4条评论

  1. ncafei

    博主您好!请问有书籍相关源码资料吗,若能分享,非常感谢!

    回复

giantbranch 发表评论 取消回复