首页
社区
课程
招聘
[原创]【很有时间系列】讲讲怎么枚举MmMapViewInSystemSpace分配的内存
发表于: 2018-9-14 17:24 9633

[原创]【很有时间系列】讲讲怎么枚举MmMapViewInSystemSpace分配的内存

2018-9-14 17:24
9633

之前曝光了一个利用MmMapViewInSystemSpace往驱动空间所在区域分配内存的外挂

传送门:https://bbs.pediy.com/thread-230129.htm
传送门:https://bbs.pediy.com/thread-230129.htm

闲的蛋疼就研究了一下怎么枚举这种方法分配出来的内存

首先明确一下虚拟内存的分配流程:
vista以上:
MmMapViewInSystemSpace ->MiMapViewInSystemSpace->MiInsertInSystemSpace->MiReserveSystemPtes(&MiSystemPteInfo, PteCount)(不同系统可能不同,但是总之是预留PTE)
xp:
MmMapViewInSystemSpace ->MiMapViewInSystemSpace->MiInsertInSystemSpace-> 从SystemSpaceBitMap找一块满足sizein64k大小的空的bitmap出来,对应到预先分配好的SystemSpaceViewStart里,直接作为分配出的地址

物理内存的分配流程:
刚才分配的PTE present位为0,访问时触发pagefault再分配物理内存←原理和NtMapViewOfSection差不多,都是只管分配VA,访问时#pf才给分配物理内存
↑这种情况下分配物理内存时不会往MmPfnDatabase中写入pfn对应的pte信息(毕竟一个section可以被多个PTE映射不是么?),导致MmGetVirtualForPhysical无法从物理地址反查虚拟地址

我们可以找个有符号的win7看一下
发现和wrk差不多,直接看wrk算了

关键代码

    Entry = (ULONG_PTR) MI_64K_ALIGN(Base) + SizeIn64k;

    Hash = (ULONG) ((Entry >> 16) % Session->SystemSpaceHashKey);

    while (Session->SystemSpaceViewTable[Hash].Entry != 0) {
        Hash += 1;
        if (Hash >= Session->SystemSpaceHashSize) {
            Hash = 0;
        }
    }

    Session->SystemSpaceHashEntries += 1;

    Session->SystemSpaceViewTable[Hash].Entry = Entry;
    Session->SystemSpaceViewTable[Hash].ControlArea = ControlArea;

    Entry = (ULONG_PTR) MI_64K_ALIGN(Base) + SizeIn64k;

    Hash = (ULONG) ((Entry >> 16) % Session->SystemSpaceHashKey);

    while (Session->SystemSpaceViewTable[Hash].Entry != 0) {
        Hash += 1;
        if (Hash >= Session->SystemSpaceHashSize) {
            Hash = 0;
        }
    }

    Session->SystemSpaceHashEntries += 1;

    Session->SystemSpaceViewTable[Hash].Entry = Entry;
    Session->SystemSpaceViewTable[Hash].ControlArea = ControlArea;


那么只要遍历MmSession的SystemSpaceViewTable就能找到所有的va

entry的算法是这样的
entry=64k对齐(虚拟地址)  +  多少个64k
也就是说entry的高48位是虚拟地址,低16位是大小(指有几个64k)



从分配前的检查也可以看出,不能分配超过(65535=64k-1)个64k,否则超过低16位能保存的大小了

算出来的entry会简单计算一个hash放到 SystemSpaceViewTable 里

那么我们遍历这个表就能拿到所有的SystemSpaceView VA和大小了,遍历前记得加锁SystemSpaceViewLockPointer

PMMSESSION_WIN7 Session = (PMMSESSION_WIN7)MmSession;
for (ULONG i = 0; i < Session->SystemSpaceHashSize; i ++) {
	if (Session->SystemSpaceViewTable[i].Entry != 0) {
			PVOID BaseAddress = (PVOID)(((Session->SystemSpaceViewTable[i].Entry >> 16) << 16) | 0xFFFF000000000000ull);//Higher 48 bit of Entry is BaseAddress aligned to 64k
			SIZE_T ViewSize = (Session->SystemSpaceViewTable[i].Entry & 0xFFFFull) * 0x10000;//lowest 16 bit of Entry is SizeIn64k
			//Now you get BaseAddress and ViewSize, ViewSize is count in bytes.
		}
	}
}

PMMSESSION_WIN7 Session = (PMMSESSION_WIN7)MmSession;
for (ULONG i = 0; i < Session->SystemSpaceHashSize; i ++) {
	if (Session->SystemSpaceViewTable[i].Entry != 0) {
			PVOID BaseAddress = (PVOID)(((Session->SystemSpaceViewTable[i].Entry >> 16) << 16) | 0xFFFF000000000000ull);//Higher 48 bit of Entry is BaseAddress aligned to 64k
			SIZE_T ViewSize = (Session->SystemSpaceViewTable[i].Entry & 0xFFFFull) * 0x10000;//lowest 16 bit of Entry is SizeIn64k
			//Now you get BaseAddress and ViewSize, ViewSize is count in bytes.
		}
	}
}

32位系统的区别仅在于高16位是虚拟地址,低16位是大小,其他和64位没有任何区别 
因此以上代码甚至只需要把PMMESSION结构换成32位版本就行了

至于PMMSESSION结构,自己找个有符号的win7自提啦

MMSESSION  MmSession变量在MmMapViewInSystemSpace入口一个lea rdx就有

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2018-9-18 14:41 被hzqst编辑 ,原因:
收藏
免费 1
支持
分享
打赏 + 1.00雪花
打赏次数 1 雪花 + 1.00
 
赞赏  junkboy   +1.00 2018/09/15
最新回复 (14)
雪    币: 914
活跃值: (2448)
能力值: ( LV5,RANK:68 )
在线值:
发帖
回帖
粉丝
2
今天的很有时间系列由hzqst主持
2018-9-14 17:25
0
雪    币: 41
活跃值: (360)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
1
最后于 2019-9-9 09:55 被DeepFantasy编辑 ,原因: 1
2018-9-14 17:34
0
雪    币: 1564
活跃值: (3572)
能力值: ( LV13,RANK:420 )
在线值:
发帖
回帖
粉丝
4
mark
2018-9-14 17:48
0
雪    币: 192
活跃值: (94)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
mark
2018-9-14 22:21
0
雪    币: 6664
活跃值: (957)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
学习了
2018-9-15 06:11
0
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
7
还是直接暴力枚举PTES简单和谐粗暴
2018-9-15 09:11
0
雪    币: 3736
活跃值: (3867)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8
顶大表哥。
2018-9-15 13:57
0
雪    币: 1604
活跃值: (640)
能力值: ( LV13,RANK:460 )
在线值:
发帖
回帖
粉丝
9
写的不错,整理一下:首先讨论不同版本上加入 system VA entry 的算法,再分别给出枚举方式:对于哈希表用迭代;对于树则从根节点递归调用自身到叶节点;MiInsertInSystemSpace() 负责插入 system VA ; MiReserveSystemPtes() 负责构建出描述该 system VA  的 PTE,各司其职;这种访问 RAM 时才实际分配的懒惰算法有助于节约 PFN 数据库的空间。两个关键的全局数据结构:SystemSpaceViewTable 与 ViewRoot 。看来在微软总部雷德蒙德开发os挺有趣的


最后于 2018-9-18 13:44 被shayi编辑 ,原因:
2018-9-17 23:39
0
雪    币: 1604
活跃值: (640)
能力值: ( LV13,RANK:460 )
在线值:
发帖
回帖
粉丝
10
2018-9-18 14:19
0
雪    币: 231
活跃值: (2631)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
11
2018-9-18 18:10
0
雪    币: 1604
活跃值: (640)
能力值: ( LV13,RANK:460 )
在线值:
发帖
回帖
粉丝
12
我觉得他的 EnumSystemSpaceViewWin10() 最后少了条 return 返回到调用者。
如果没有 return ,搜索一棵树时会是这样(忽略内核栈的大小限制):


有 return 则大不相同,能够回到上个 “岔口” 继续走另一条路,从而枚举完整棵树:

2018-9-18 20:09
0
雪    币: 1604
活跃值: (640)
能力值: ( LV13,RANK:460 )
在线值:
发帖
回帖
粉丝
13
由下图可知,插入红黑树是公平算法(左右节点各有几率),而遍历红黑树是右节点深度优先算法:


2018-9-18 23:36
0
雪    币: 12848
活跃值: (9142)
能力值: ( LV9,RANK:280 )
在线值:
发帖
回帖
粉丝
14
shayi 我觉得他的 EnumSystemSpaceViewWin10() 最后少了条 return 返回到调用者。如果没有 return ,搜索一棵树时会是这样(忽略内核栈的大小限制):有 return 则大 ...
这跟return有啥关系?


我这是标准的递归遍历啊
最后于 2018-9-19 07:41 被hzqst编辑 ,原因:
2018-9-19 07:41
0
雪    币: 1604
活跃值: (640)
能力值: ( LV13,RANK:460 )
在线值:
发帖
回帖
粉丝
15
hzqst shayi 我觉得他的 EnumSystemSpaceViewWin10() 最后少了条 return 返回到调用者。如果没有 return ,搜索一棵树时会 ...
那应该是我看错了,抱歉
2018-9-19 14:09
0
游客
登录 | 注册 方可回帖
返回
//