1、内存分布情况
系统中每个进程都有自己的虚拟地址空间,对于一个32位进程的应用来说。这个地址的寻找空间等于2的32次方,也就是刚好4GB。32位指针地址空间是从0x00000000到0xFFFFFFFF之间任意一个值。对于一个64位程序来说,由64位指针可以表示从0x00000000’00000000到0xFFFFFFFF’FFFFFFFF之间任意一个值,因此地址空间大小为16EB。每个程序都有自己的专有空间,当这个程序每个线程运行时它只能访问到自己的地址空间。
每个进程都有自己的内存分区(进程虚拟地址空间的划分),下图是一个32位程序的分区情况:
由于地址空间分区依赖于系统底层实现,所以windows内核的不同分区略有不同
- 空指针赋值分区:
进程中空指针赋值分区段又称为闭区间,该分区是帮组给程序捕捉空指针使用。如malloc分配内存失败,就会返回NULL。如果一个程序对该分区做写入操作会触发违规操作。
- 用户模式分区:
Windows中所有的exe和动态链接库都是加载到这个区域,同时会把该进程的可以访问的资源都加载到这个区域。
对于应用程序来说,大部分数据都保存在这一分区。
32位下,默认为2GB大小。打开/3GB开关时,可扩大到3GB空间,但同时内核空间缩小为1GB。
- 64K禁入分区:
64K禁入区的作用很明显是隔离了用户和内核空间;防止用户程序跨越到内核空间中。与内核交互会涉及到SSDT表,后续破解驱动保护部分会讲到。
- 内核模式分区:
内核模式分区顾命思意,内核模式是对操作系统的代码驻地。与线程,内存管理,文件系统,网络支持以及驱动相关程序的代码都会载入这个区域。这一部分的代码是所有的进程都共有的。
2、程序内存分布情况
对于一个程序来说逻辑上我们可以把它分为三个区域段:动态分配段、代码段、静态数据段。
动态分配段一般就是“堆栈”,栈(stack)和堆(heap)是两种不同的动态数据区。栈是一种线性数据,堆一种链式数据。进程的线程每一个都有自己私有的“栈”,所以每个线程虽然代码一样,但是互相不干扰。一个堆栈可以通过“基地址”和“栈顶地址”来描述。
全局变量和静态变量分配在静态数据区,本地变量分配在动态数据区,即堆栈中。程序通过堆栈的基地址和偏移地址来访问本地变量。