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啊