堆的初步认知

堆的分配是在程序运行时完成的,分配速度较为缓慢,但是堆的可用空间非常的大。常见的堆空间操作有如:new,malloc(申请);free,delete(释放),底层函数RtlAllocateHeap(ntdll.dll中),更详细的函数信息查看MSDN。堆分配的空间较为碎片化,需要对堆块的管理:按照堆块的大小分类组织在一起,在堆区的起始位置建立堆表用于索引堆块;而每一个堆块头部也记录着本块大小、空闲与否等(8字节),空闲块区还有前向指针(flink),后向指针(binlk),一共16字节。


每一次堆分配或者堆释放时,都将从空堆表末尾进行操作。堆的操作存在修改链表链接和块首信息,构造伪造的节点就可以实现一次内存读写的操作。


堆溢出的时候,就是溢出修改堆的首部指针,当块卸下的时候,将实现向我们在blink处写的地址target写入原flink处的修改值payload(与此同时在blink处写的数据也将写到flink偏移4字节的位置去)。一般target选取为函数返回,异常发生或函数调用等。也可以用于目标地址变量值的修改,或填入nop之类修改函数流程。特别的使用方法就是修改PEB中线程同步的函数入口地址,进程退出时,exitprocess调用线程中的rtlentercriticalsection等函数来处理线程间实现临界段锁的数据清理。

调试堆与常态管理有不同:调试堆不使用块表只用空表分配;所有堆块添加16字节尾部用于防止程序溢出(不是堆溢出);块首标志位不同。如果堆初始化结束后再attach程序可以看见真实状态的堆。

在多线程的程序里,每个线程都有其自己独立的栈,它们都共享一个堆。栈是面向线程的而堆是面向进程的。

linux下的堆与windows平台下差别不大:

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 一、温故而知新 1. 内存不够怎么办 内存简单分配策略的问题地址空间不隔离内存使用效率低程序运行的地址不确定 关于...
    SeanCST阅读 8,139评论 0 27
  • __block和__weak修饰符的区别其实是挺明显的:1.__block不管是ARC还是MRC模式下都可以使用,...
    LZM轮回阅读 3,599评论 0 6
  • 1.写一个NSString类的实现 +(id)initWithCString:(c*****t char *)nu...
    韩七夏阅读 3,876评论 2 37
  • 《重塑心灵》一书讲道:有效的双向沟通是指,我表达了自己的信息,而对方的回应是我所期待的,或者,对方不一定会接受我的...
    May74阅读 141评论 1 1
  • 请安静 请安静 请安静 然后呢 听 心声呢 哦 晚安
    彩ya阅读 129评论 0 1

友情链接更多精彩内容