0x00 前言
讲内存管理单纯的理论比较空洞,所以本文从探究DbgVeiw的内存分布开始,来探究windows系统的内存管理,讨论malloc和VirtualAlloc的差别,和缺页异常。
参考文章
https://blog.youkuaiyun.com/weixin_42052102/article/details/83757538
https://blog.youkuaiyun.com/weixin_42052102/article/details/83722047
https://blog.youkuaiyun.com/weixin_42052102/article/details/83751896
0x01 线性地址的管理
首先在虚拟机中打开一个.exe的文件,这里选择了DbgView,之后到Windbg里查看对应的进程
看一下_KPROCESS结构体
在0x11c的位置的VadRoot处是一个搜索二叉树的入口点,每一个节点都记录被占用的线性地址空间,每一个节点的结构,都是_MMVAD结构体
接下来,先手动找一下这个搜索二叉树的节点
观察一下1)Parent:因为是根节点所以没有父节点了
2)LeftChild / RightChild:左子树/右子树,一个是往左边拓展的线,一个是往右边拓展
重复这一过程就可以找到所有的节点(选择二叉树而并非链表是因为搜索二叉树查找的效率比链表高很多)
3)StartingVpn && EndingVpn: 这两个值是以页(4kb)为单位的,所以各把这两个数后面添上3个0,就是当前节点的起始位置与结束位置,也此两者之间就是已经被占用的位置,所以想找到那些已被占用和未被占用的线性地址,遍历这个二叉树就可以了。
4)ControlArea:看一下结构体
其中的FilePointer如果其中的值是NULL则线性地址对应的是真正的物理页
而如果指向一个_FILE_OBJECT(如上图),那线性地址对应的是某文件影射的内存,我们继续跟下去
5)_MMVAD+0x14成员u,我们不妨参考一下 ReactOS 里的说明
union {
ULONG_PTR LongFlags
MMVAD_FLAGS VadFlags
} u
主要使用的是MMVAD_FLAGS这个结构,跟进这个结构(和实际windows还是有一定差别的,但是主要成员没问题,其中Protection的偏移为0x14)
typedef struct _MMVAD_FLAGS
{
ULONG_PTR CommitCharge:19
ULONG_PTR NoChange:1
ULONG_PTR VadType:3
ULONG_PTR MemCommit:1
ULONG_PTR Protection:5//规定文件属性
// 1 READONLY 2 EXECUTE 3 EXECUTE _READ 4 READWITER
// 5 WRITECOPY 6 EXECUTE _READWITER 7 EXECUTE_WRITECOPY
ULONG_PTR Spare:2
ULONG_PTR PrivateMemory:1//是实际物理页(1:private)还是文件映射(0:mapped)
} MMVAD_FLAGS,*PMMVAD_FLAGS;
遍历所有节点,在windbg里也存在这样的指令! vad 0x89473968(这个是根节点的线性地址)
一下列举4种不同的情况
1. 其中的Level就是二叉树中的层级,
2. start和end 后面再加3个0(因为单位为4kb)就是每个节点线性地址的起始与终点位置
3.Private是指线性地址对应真实