存储物理页属性的PFN数据库
Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html
Windows内存布局 / MmPfnDataBase页帧数据库
1. Windows操作系统在X86下的内存布局如下图所示


2. 进程工作集 (Hyperspace and process working set list)
如上图所示,在c0400000地址处存在一个进程工作集,其在EProcess+0x1f8 vm 表示,其是一个 _SUPPORT结构。

3. nt!MmNumberOfPhysicalPages 查看存在多少物理页
这是一个全局变量,表明操作系统当前可用的物理页个数,我们在10-10-12分页模式下一个页以4KB为单位,我们查看该变量:
dd nt!MmNumberOfPhysicalPages 0001ff6c
我们从任务管理器中查看其可用的内存

很容易发现满足关系 0001ff6c*4 = 523696,因此可以验证我们的说法:该变量代表当前进程中可用的物理页数。
4. 页帧数据库 PfnDataBase
1) mmpfndatabase 全局变量
该全局变量以数组形式存储对应的__MMPFN数据结构,整个可以看做 __MMPFN[x],x表示第x个物理页,这是数组一次排序。
其__MPFN数据结构如下(其中涉及大量的Union类型),其单个长度 0x14。(注意,其长度不确定,具体看详细版本的长度)

2) 物理页的八种状态(实际只有六个,其存在各自的链表)
物理页本来应该存在八种状态,但其中只有六个可用,其存储在 __MMPFN.u3
u3中存在一个 __MMPFNENTRY,里面描述了有关该页所处的状态(空闲状态,零化状态,未分配状态·····)。
其根据物理页的状态,制作不同的链表,将相同属性的物理页串联在一起,如下六个全局变量:
① MmZeroedPageListHead // 可以使用并清零的内存
② MmFreePageListHead // 被释放的内存,定期会检测是否有数据,如果有就清空并且挂到第一个链表中
③ MmStandbyPageListHead // 分页内存,备份到虚拟文件中,如果①②用完其才会用到这个,紧急使用
④ MmModifiedPageListHead // 修改过属性的页
⑤ MmModifiednoWritePageListHead // 修改但是没有写出的链表
⑥ MmBadPageListHead // 坏页的链表
具体的存储在 MmPageLocationList 这个数组中,我们在WRK中可以看到该数组的定义,我们可以看到,八个中确实只用到了六个。

typedef enum _MMLISTS {
ZeroedPageList,
FreePageList,
StandbyPageList, //this list and before make up available pages.
ModifiedPageList,
ModifiedNoWritePageList,
BadPageList,
ActiveAndValid,
TransitionPage
} MMLISTS;
3)__MMPFN的中存在 Flink 与 Blink 两个成员,但其并不是指针而是ULONG类型,前面说过内存物理页是依次排列的,那么这两个成员有什么用呢?
前面我们说过其存在六个链表,虽然物理页的前后是确定的,但是相同属性的物理页却是通过 Flink 与 Blink 连接起来的,其并不是连接而是在页帧数据库中的位置,这个很好理解。

而 MmPageLocationList数组中存储的各个属性物理页头部的地址,这样整个页帧数据库体系就很容易搭建起来了。
4)Windbg 遍历pfn 单个 __MMPFN数据结构
使用windbg的 !pfn x 命令可以查看其存在多少对应的PFN对应的物理页的属性:

5. 驱动遍历某一链表
结合我们上面所讲,其Pfn在内存中的布局如下,如果上面都看懂了,这部分应该很好理解,但其中MmPageLocationList与MmPfnDataBase并不是导出变量,我们通过IDA特征码定位即可。

#include <ntifs.h>
#include <ntimage.h>
#include <intrin.h>
#include "tools.h" typedef struct _MMPFN {
ULONG Flink; // 前一个节点索引
ULONG PteAddress; // 对应的pte地址
ULONG Blink; // 后一个节点索引
ULONG u3[3]; // 占位,总共0x14个字节
}MMPFN,*PMMPFN; typedef enum _MMLISTS {
ZeroedPageList,
FreePageList,
StandbyPageList, //this list and before make up available pages.
ModifiedPageList,
ModifiedNoWritePageList,
BadPageList,
ActiveAndValid,
TransitionPage
} MMLISTS; typedef struct _MMPFNLIST {
PFN_NUMBER Total;
MMLISTS ListName;
PFN_NUMBER Flink;
PFN_NUMBER Blink;
} MMPFNLIST, *PMMPFNLIST; PULONG MmPageLocationList; //
PULONG MmPfnDataBase; // 页帧数据库 VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
DbgPrint("卸载完成\n");
} NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegsiterPath)
{ pDriverObject->DriverUnload = DriverUnload; // 定位 MmPageLocationList
FindCode findcodes[1] = { 0 };
initFindCodeStruct(&findcodes[0],
"8B******8B48*FF088B56*894D*8B0E83**894D*0F*****8B*****8D0C498954**8B5D*8B4D*",
0, 0);
PUCHAR f = (PUCHAR)FindAddressByCode(findcodes, 1);
MmPageLocationList = *(PULONG) ((PUCHAR)f + 3); // 定位 MmPfnDataBase
FindCode findcodes2[1] = { 0 };
initFindCodeStruct(&findcodes2[0],
"8B*****8D044956578D34C28B7E*A1****C1**83**85C0895D*894D*0F*****83******0F*****8B46*",
0, 0);
f = (PUCHAR)FindAddressByCode(findcodes2, 1);
PULONG MmPfnDataBase = *(PULONG)(*(PULONG)((PUCHAR)f + 2)); // 查询空闲链表数据成员
MMLISTS PfnIndex = FreePageList;
PMMPFNLIST ZeroedPageList = MmPageLocationList[PfnIndex];
DbgPrint("零化链表的总数为:%x,前一个节点为:%x,后一个节点为:%x\r\n", ZeroedPageList->Total,ZeroedPageList->Flink,ZeroedPageList->Blink); // 开始遍历PfnDataBase页帧数据库
//DbgPrint("MmPfnDataBase地址为:%p\r\n", MmPfnDataBase);
ULONG index = ZeroedPageList->Flink; // 获取第一个节点索引
PMMPFN p;
for (ULONG i = 0; i < ZeroedPageList->Total; i++) {
p = (PMMPFN)((PUCHAR)MmPfnDataBase + sizeof(MMPFN) * index); // 获取结点
DbgPrint("Current PteAddress:%x\r\n", p->PteAddress);
index = p->Flink; // 更新下一个结点
}
return STATUS_SUCCESS;
}
存储物理页属性的PFN数据库的更多相关文章
- 深入理解Sqlserver文件存储之页和应用 (转)
我们每天都在使用数据库,我们部门使用最多的关系数据库有Sqlserver,Oracle,有没有想过这些数据库是怎么存放到操作系统的文件中的?有时候为了能够设计出最优的表结构,写出高性能的Sqlserv ...
- ibernate学习笔记5---实体类或属性名与数据库关键字冲突、hql命名参数、hql实现通用分页
一.实体类或属性名与数据库关键字冲突问题1.实体类名与数据库中的关键字冲突比如:实体表User与oracle中的系统表冲突解决方式1:在xml中添加table属性,指定表名,使其不与name默认相等 ...
- 4、Android-数据存储方案(使用LitePal操作数据库)
4.5.使用LitePal操作数据库 4.5.1.LitePal简介 LitePal是一款开源的Android数据库框架 采用了关系映射(ORM)的模式 将经常使用的一些数据库做了封装 是得不用编写S ...
- EF Core中怎么实现自动更新实体的属性值到数据库
我们在开发系统的时候,经常会遇到这种需求数据库表中的行被更新时需要自动更新某些列. 数据库 比如下面的Person表有一列UpdateTime,这列数据要求在行被更新后自动更新为系统的当前时间. Pe ...
- 使用mybatis如果类属性名和数据库中的属性名不一样取值就会为null
使用mybatis时如果类属性名和数据库中的属性名不一样取值就会为null 这是不能再去改变javabean中的属性,只能改变sql语句.语句如下所示: <select id="sel ...
- Mybatis中resultMap的作用-解决实体类属性名和数据库字段不一致
解决实体类属性名和数据库字段不一致
- 解决SpringDataJpa实体类中属性顺序与数据库中生成字段顺序不一致的问题
一.在application.yml配置中添加数据库根据实体类自动创建数据库表的配置(这里数据库采用MySQL数据库) jpa: database: MYSQL show-sql: true #Hib ...
- mybatis——解决属性名和数据库字段名不一致问题(注解方式)
当我们使用注解开发时有时会遇到数据库字段名与实体类属性名不一致的问题.xml方式开发可以通过结果集映射的方式解决,那注解方式开发要怎么解决呢? 注解解决方式: @Results()注解 Results ...
- mybatis——解决属性名和数据库字段名不一致问题
首先说一下,我的数据库名字叫mybatis,里边有一张user表,表中有三个字段,id.name.pwd:然后实体类中对应三个属性id.name.password(id和name跟数据库字段名一致,但 ...
随机推荐
- Session和Cookie的用法及区别
1. Session.Cookie是什么 1.1 概念理解 要了解session和cookie是什么,先要了解以下几个概念. 1.1.1 无状态的HTTP协议 协议:是指计算机通信网络中两台计算机之间 ...
- asp.net core + layui.js 搭建仓储系统
先放几张网站图片: 第一步先从layui 网站https://www.layui.com/doc/ 下载相关文件,复制到项目 wwwroot 目录下: 然后在 _Layout.cshtml 中引用 l ...
- Python的未来发展方向
Python是一种跨平台的计算机程序设计语言. 是一种面向对象的动态类型语言,最初被设计用于编写自动化脚本(shell),随着版本的不断更新和语言新功能的添加,越来越多被用于独立的.大型项目的开发. ...
- Spring MVC-从零开始-第一个控制器(不考虑命名规范)
1.目录结构 (log4j.properties.mybatis-config.xml可忽略) 2.配置web.xml文件 <?xml version="1.0" encod ...
- org.hibernate.AnnotationException: No identifier specified for entity 错误解决
主键对应的属性上加上@Id注解,对应javax.persistence.Id @Id private Long id;
- Flask基础(07)-->正则自定义转换器
正则自定义转换器 为什么要自定义正则转换器? 因为默认转换器太过于笨重,往往不能满足我们实际业务的需求,这时候我们就需要自定义正则转换器了. 那么我们怎么自定义正则转换器呢? from flask i ...
- SUSE Ceph 快速部署 - Storage6
学习 SUSE Storage 系列文章 (1)SUSE Storage6 实验环境搭建详细步骤 - Win10 + VMware WorkStation (2)SUSE Linux Enterpri ...
- Salesforce学习之路-developer篇(三)利用Visualforce Page实现页面的动态刷新案例学习
Visualforce是一个Web开发框架,允许开发人员构建可以在Lightning平台上本地托管的自定义用户界面.其框架包含:前端的界面设计,使用的类似于HTML的标记语言:以及后端的控制器,使用类 ...
- httpSession和Cookie
1.session在何时被创建一个常见的误解是以为session在有客户端访问时就被创建,然而事实是直到某server端程序调用 HttpServletRequest.getSession(true) ...
- Python3 Linux安装(Redhat)
Python3 Linux安装(Redhat): 下载Python-3.6.4.tgz: https://www.python.org/downloads/release/python-364/ Y ...