001B:77FCCA25 754B JNZ 77FCCA72 //含则跳,这里不能跳
001B:77FCCA27 57 PUSH EDI
001B:77FCCA28 53 PUSH EBX
001B:77FCCA29 E80CCBFBFF CALL 77F8953A
001B:77FCCA2E 8B4F0C MOV ECX,[EDI 0C] //将buf2的0x0c偏移给ECX
001B:77FCCA31 8B4708 MOV EAX,[EDI 08] //将buf2的0x08偏移给EAX
001B:77FCCA34 3BC1 CMP EAX,ECX
001B:77FCCA36 8901 MOV [ECX],EAX //这里发生异常
001B:77FCCA38 894804 MOV [EAX 04],ECX
方式三和方式二都是利用RtlFreeHeap函数,他们的分岔口在于关键点二的
001B:77FCC8B8 0F858BF2FFFF JNZ 77FCBB49
方式二在这里要跳,方式三不能跳,从而进入下面的CALL(关键点三)
发生异常时ECX=0x22222222,EAX=0x11111111,这是我们能控制的。
可见方式三的前提有三个
1)构造堆(buf2)的长度不能为0
2)构造堆的上一个堆(buf1)和构造堆的长度相加不能大于0xfe00(div8之后)
3)构造堆的flag不能包含HEAP_ENTRY_BUSY
除了以上三种利用方式更有一种,和方式三差不多,但是是在free(buf2)时发生异常,应该是由于在合并下一个堆时长度计算错误造成的,具体就不分析了,类似于linux下的堆溢出,但是windows下不能将堆长度设为负数,造成一定的麻烦,sign
溢出之后的事情就不再说了。写这些主要为了分析总结一些东西,希望对初学者有帮助,不当之处请指正。
//更正一下,以上程式在.net平台下编译有效,VC 6.0编译是不能溢出的。可能是两种编译器对malloc的实现方式不同。vc的编译器实现malloc的时候并没有真正调用RtlFreeHeap或RtlAllocHeap函数,造成溢出失败。改成HeapAlloc就能够了
文章整理:西部数码--专业提供域名注册、虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!




