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等软件直接打开,因为堆管理函数检测到调试状态,就会使用调试态堆管理策略
不同点
-
调试堆不使用快表,只用空表分配
-
所有的堆块被加上了多余的16字节尾部来防止溢出(防止程序溢出而不是堆溢出),包括8个字节的0xAB和8个字节的0x00
-
块首的标志位不同
所以在源码中我们在创建堆之后加入一个人工断点 int 3,
当堆初始化完,断点就中断程序,这时再用调试器attach,就看到真实的堆了
首先我们选择编译成release版
首先将od设置成实时调试器
运行
点击取消,停在了int 3
去内存模块看看
看不到书本那里的HeapCreate创建的
我们看看前面的返回值
怎么隐藏那么深呢
识别堆表
程序在初始化,malloc使用的堆和进程堆已经经过若干次分配和释放操作,里面比较“凌乱”,用HeapCreate创建的就比较“整齐”
用一下heap_vis插件查看堆块,结果就是没结果
那我们直接到内存取查看吧,ctrl+g
从3A0000开始包含的信息依次是段表索引,虚表索引,空表使用标识和空表索引区
不懂啊,0x178偏移是空表索引区,其余跟堆溢出利用关系不大,先不学咯
去3A0688看看
当前块的大小,是块首的前两个字节,0x130,但是单位是8个字节,就是0x980字节(堆的大小包含块首在内)
快表据说在0x584,这里为NULL,因为我们这样创建的堆没扩展性,HeapCreate(0,0,0)就可以
堆块的分配
注意分配时8字节对齐的,不足的就给足8字节,还有块首还有8字节,所以申请2字节,最终分配16字节
我们单步到前6次分配
结果发现,原版的才能用
看一下第一次分配的时候
可以看到前四个都是分配16字节
继续
堆块的释放
前三次释放内存不连续,所以不会合并,先释放h1看看
下图是16字节才对,要加上块首8字节嘛
通过实验发现h3插在了h1的链表前面
我们可以去看看空表所以 0x178处
堆的合并
原来h3的堆首大小被改写,前向指针和后向指针指向freelist[8]
合并只是修改了块首的数据
块表的使用
再来一个程序,改一下创建堆时候,参数变成0,0,0就好,还有就是改改分配大小修改一下
那么快表就是在0x688了,去看看
8字节插入到lookaside[1],16就[2],24就[3]
那我们到8字节的那个地方看看
当我们再申请16字节,就从块表中取了,之前释放优先放到块表中,直到满了四个
所以我们再申请,就先从块表获取了
而且申请的返回值就是之前块表储存的地址,可以看前上上上张图
博主您好!请问有书籍相关源码资料吗,若能分享,非常感谢!
http://bbs.pediy.com/thread-201998.htm
你好请问你用的win2000sp2还是sp4?
这明显是xp啊