0day 安全 之 windows 2000的堆块学习之 空表

堆溢出在0day安全这本书里面应该是  基础章的最后一段了 其实也算是比较难的一段

在 CTF的pwn中 堆就是一个难点  并且 在那些重大的CTF比赛 上来就直接 来个 经典的 菜单 堆块题

不过  这个在windows下 却是比较难利用的 

linux 是开源的 就相当于 代码审计     但是 windows 却是 闭源的,,,

然后 windows 2000的 堆块策略 基本了解了

看着这本书 然后 开始研究 

实验环境 就是 windows2000 sp4   VC6.0   OD

代码如下

/*****************************************************************************
      To be the apostrophe which changed "Impossible" into "I'm possible"!
		
POC code of chapter 6.2 in book "Vulnerability Exploit and Analysis Technique"
 
file name	: heap_debug.c
author		: failwest  
date		: 2007.04.04
description	: demo show of how heap works
Noticed		:	1 only run on windows 2000
				2 complied with VC 6.0
				3 build into release version
				4 only used for run time debugging
version		: 1.0
E-mail		: failwest@gmail.com
		
	Only for educational purposes    enjoy the fun from exploiting :)
******************************************************************************/

#include <windows.h>
main()
{
	HLOCAL h1,h2,h3,h4,h5,h6;
	HANDLE hp;
	hp = HeapCreate(0,0x1000,0x10000);
	__asm int 3

	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
	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); //coalese h3,h4,h5,link the large block to freelist[8]

	
	return 0;
}

这里直接 用的堆就是空表 并没有用到 快表 (为了更好的观察 空表)

而且还不能直接 用od 调试 要不然的话  会有所改变 主要改变的地方 体现在

然后我们我们直接 用od 来看

 

这里的eax 就是 我们申请到的地方  就是  HeapCreate 申请到的地方

ok  现在 还没有开始想我们申请到的地方申请堆块  可以看出这里面已经有了很多数据

这里我们看一下 0day 书上描述的内容

这里 的 0x520000  在我们这里是  0x0036000

然后 根据 书上描述的内容 我们来看一下 堆块里面的内容  首先 观察  空表索引区

这里面的值可以好好的 琢磨一下,(看的头晕眼花)

0x00360178处的值指向的是0x00360688,而接下来索引区其它的索引都是指向自己本身   这里对应了 上面的第三条  第四条

可以认为 这里的 0x00360688 就是那个 “尾块”

然后我们 到 0x00360688看看,可以看到这个位置的指针是指向0x00360178

然后空闲堆块的 结构

 

 

占用堆块的结构

也就是说我们的占用堆 会 把fd bk 给填充成数据

所以我们 直接越过 8字节 直接看 data 块 

然后我们 观察一下  0x00360680

发现了  0x360680 的值是 0x00080130

这里的 0x0130表示这个堆块大小为0x0130 计算单位是8字节 也就是 0x980 字节0xx0008表示Previous chunk size

然后我们继续往下走 

第一次申请堆块
h1 = HeapAlloc(hp,HEAP_ZERO_MEMORY,3);

看一下堆块的变化

 

可以看出变化还是很大的 

这里具体分析一下

内存0x00360028处的0x00000130变成了0x0000012E,减小了2个堆单位,一个堆单位是8字节,也就是说减小了16个字节,而这个数字的意思就是尾块还有多少可以分配的空间,因为分配的时候会带上块首,所以第一次申请了3个字节加上块首8个字节,最终一共申请的是11个字节,所以实际就分配了16个字节也就是两个堆单位

然后会发现  0x360178这里指向的地方也发生了变化  变成了  0x0360698  然后   看一下 0x00360680

前面8字节是块首,0x0002表示两个堆单位(可以理解 0x8是上一个相邻的堆单位   0x2是所在堆块的堆单位)

前面提到过,0x00360178处是freelist[0],指向的是尾块,所以现在0x00360178处的指针变成了0x00360698,也就是说现在尾块的起始位置是0x00360690
块首的前两个字节是代表堆块的大小,所以0x012E的确是现在未分配堆块的大小,和前面的数据是匹配的
以上就是第一次分配内存里的部分变化,也是比较直观可见的变化,接下来看看其余五次的申请,过程和第一次是一样的,只是数据会有所不同

第二次申请堆块
h2 = HeapAlloc(hp,HEAP_ZERO_MEMORY,5);

尾块可分配的大小变为0x0000012C个堆单位
0x00360020  00 02 00 00 00 20 00 00 2C 01 00 00 FF EF FD 7F

尾块数据区的起始位置变为0x003606A8
0x00360170  00 00 00 00 00 00 00 00 A8 06 36 00 A8 06 36 00

第三次申请堆块
h3 = HeapAlloc(hp,HEAP_ZERO_MEMORY,6);

尾块可分配的空间变为0x0000012A个堆单位
尾块数据区的起始位置变为0x003606B8


第四次申请堆块
h4 = HeapAlloc(hp,HEAP_ZERO_MEMORY,8);

尾块可分配的空间变为0x00000128个堆单位
尾块数据区的起始位置变为0x003606C8

第五次申请堆块
h5 = HeapAlloc(hp,HEAP_ZERO_MEMORY,19);

可分配尾块空间为0x00000124个堆单位
尾块数据区的起始位置为0x003606E8

第六次申请堆块
h6 = HeapAlloc(hp,HEAP_ZERO_MEMORY,24);

尾块可分配空间变为0x00000120个堆单位
尾块数据区的起始位置变为0x00360708

这里就没有什么好说的了  就是 不断地变化  freelist[0]  然后 把 堆的单位改一下

其实就是不断地 分割 尾块的过程,

然后 看一下 free的过程。

我们这里直接把 h1 h3  h5 全部free 掉  直接观察结果

 

Freelist 前四位我都标注好

可以看到  list[2] 和  list[4] 发生了变化    list[2] 指向了 fd指向了 h1 bk指向了 h3     list[4]直接指向了  h5

然后我们看一下 h1 和 h3的空间

发现两者data 化成了fd指针 fd  已经用上 

然后 继续往下看  free掉 h4

可以看到Freelist[4]原来串着的h5没了,0x00360198处的指针已经指向了自身

而Freelist[8]发生了变化,值为0x003606A8,那就过去看看

可以看到这里出现了一个大小为8个堆单位的堆块

而这里原本 是h3的空间,,

因为当h4被释放的时候,h3,h4,h5发生了合并,大小为8个堆单位,所以串在了Freelist[8]上

也可以看到 freelist[2] 上面就剩下 h1块

 

ok 终于还是艰难的把分析了一下

(怀念在 ubuntu 里面用 gdb调试堆的时光,,,这OD调试的眼花。。。。)

 

参考资料

0day安全:软件漏洞分析技术

https://www.52pojie.cn/thread-472862-1-1.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值