能力值:
(RANK:30 )
|
-
-
2 楼
赞!感谢分享!
|
能力值:
( LV7,RANK:110 )
|
-
-
3 楼
感谢楼主
|
能力值:
( LV2,RANK:10 )
|
-
-
4 楼
在学习的时候发现,关于 SegmentOffset overwrite 这一块,想问下楼主是编译的Debug还是Release版本用Windbg附加的啊。 我最开始是用的Release版本,使用Windbg附加调试,但是结果跟文章里的图示一点也不一样,没有多出的0x24字节,没有上溢和下溢的0xfdfdfdfd标志。解密堆头后整个堆块的大小是3*8(3个堆粒度大小)
因为提到new申请的堆块会多0x24字节,在数据前后会多0xfdfdfdfd。 但是我在看《软件调试》的时候,上面说处于调试状态的CRT堆才会有这个结构。所以我又用Debug版本的附加调试,这次的结果和图示有点像了,但是未被初始化的类的变量在内存里是0xcdcdcdcd而不是0;综合推断一下:楼主所用的程序版本是Debug版本,所以调试的时候处于调试态,CRT堆的调试支持就是将堆的用户数据包裹起来,形成以下的一个结构: struct _CrtMemBlockHeader { _CrtMemBlockHeader* _block_header_next; //下一块堆空间首地址(实际上指向的是前一次申请的堆信息) _CrtMemBlockHeader* _block_header_prev; //上一块堆空间首地址(实际上指向的是后一次申请的堆信息) char const* _file_name; int _line_number; int _block_use; size_t _data_size; //堆空间数据大小 long _request_number; //堆申请次数 unsigned char _gap[no_mans_land_size]; //上溢标志 fdfdfdfd unsigned char _data[_data_size]; //用户操作的堆数据 //这个数据的前后4个字节被初始化为0xFD,用于检测堆数据访问过程中是否有越界访问 unsigned char _another_gap[no_mans_land_size]; //下溢标志 fdfdfdfd };
最后有一个疑问,处于调试状态下的堆块结构不是一般和我们分析的堆块结构不一样吗(不太了解windows 7的堆调试状态),所以《0day安全:软件漏洞分析技术》上面也一直用的Release版本的应用程序,而且文章里前面提到的激活LFH也要在不可调试的状态下才能激活
|
能力值:
( LV2,RANK:10 )
|
-
-
5 楼
《0day安全:软件漏洞分析技术》关于调试态堆管理策略和常态堆管理策略的差异: - 调试堆不使用快表,只用空表分配 - 所有堆块都被加上了多余的 16 字节尾部用来防止溢出(防止程序溢出而不是堆溢出攻击),这包括 8 个字节的 0xAB 和 8 个字节的 0x00。 - 块首的标志位不同。 调试态的堆和常态堆的区别就好像 debug 版本的 PE 和 release 版本的 PE 一样。 我刚刚又调了一下,发现即使是Debug编译下的程序运行之后再附加调试器也不会引起堆块发生变化 ,但是一开始就用调试器调试结构就会和书上说的一样(只测了windows2000,其他应该也一样) 所以楼主用Debug编译的程序也能正常溢出,堆块结构也正常,但是CRT堆是调试状态,所以多了0x24个字节
|
能力值:
( LV10,RANK:171 )
|
-
-
6 楼
是的,我用的debug版本的,当时没注意到crt在debug和release的区别 ,感谢指出。 调试状态下的堆块结构不同的原因是调试器启动时会设置PEB->NtGlobalFlag标志位,这些标志位提供了一些堆的调试支持,你可以用glags看下这些标志位。附加能够不影响堆结构的原因是附加不会影响这些标志位。(相关的知识软件调试有所描述) LFH的激活可以通过调用HeapSetInformation函数显式激活。 另外,文章说的实验是在windows7做的,因为LFH从win7开始支持(windows2000还没有LFH)。
|
|
|