MDL详解
以下的虚拟内存可以理解成逻辑内存,因为我觉得只有这样才能讲通下面所有的东西。以下的“未分页”指没有为页进行编码。
以下为MDL结构体(我很郁闷,我在MSDN上没有找到这个结构体)
typedef struct _MDL {
struct _MDL *Next; //下一个MDL
CSHORT Size; //大小
CSHORT MdlFlags; //标志,保护属性等
struct _EPROCESS *Process;//
PVOID MappedSystemVa;
PVOID StartVa;
ULONG ByteCount;
ULONG ByteOffset;
} MDL, *PMDL;
如何使用MDL:
一个连续的虚拟内存地址范围可能是由多个分布(spread
over)在不相邻的物理页所组成的。系统使用MDL(内存描述符表)结构体来表明虚拟内存缓冲区的物理页面布局。我们应该避免直接访问MDL。我们可以
使用MS-Windows提供的宏,他们提供了对这个结构体基本
的访问。
·MmGetMdlVirtualAddress 获取缓冲区的虚拟内存地址
·MmGetMdlByteCount 获取缓冲区的大小(字节数)
·MmGetMdlByteOffset 获取缓冲区开端的物理页的大小(字节数)
·MmGetMdlPfnArray 获取记录物理页码的一个数组指针。
我们可以用IoAllocateMdl函数来分配一个MDL。如果要取消分配,可是使用IoFreeMdl函数。或者,可以使用MmInitializeMdl来把一个之前定义的缓冲区定制成一个MDL。但是以上两种方式都不能初始化物理页码数组。
对于在未分页池中分配的缓冲区,可以用MmBuidlMdlForNonpagedPool函数来初始化页码数组。对于可分页的内存,虚拟内存和物理内存
之间的联系是暂时的,所以MDL的页码数组只在特定的环境和时间段有效,因为很可能其他的程序对它们进行重新分配,为了使其他的程序无法对他们进行修改和
重新分配(在我们释放之前),我们就需要把这段内存锁定,防止其他程序修改,我们可以用MmProbeAndLockPages来实现,这个函数同时还为
当前的布局初始化了页码数组。当我们用MmUnlockPages来释放被锁定的内存时,页码数组也会随之无效。
假如MDL指定的是映射一块内核级别的虚拟地址空间,那么我们要用MmGetSystemAddressForMdlSafe
,这样我们就能防止映射目标是来自用户模式的空间,而来自用户模式空间的物理页只能在用户模式上下文环境中使用,并且随时可能被清空。用函数进行申明后,
就可以防止以上情况发生了。
以下这个函数是用于新创建一个MDL的:参数详解可翻阅MSDN
PMDL IoAllocateMdl(
IN PVOID VirtualAddress,
IN ULONG Length,
IN BOOLEAN SecondaryBuffer,
IN BOOLEAN ChargeQuota,
IN OUT PIRP Irp OPTIONAL
);
最后一个参数是指IRP(输入输出请求包),也就是将新建的这个MDL缓冲区和指定的IRP关联,为什么要关联?举个例子,比如网络驱动中就应该为每一个
发送到本机的IP数据报建立一个临时缓冲区,而最终用户——应用程序要读取这个缓冲区的数据,必须使用IRP请求驱动程序来完成,所以要提取某个IP数据
报,只要发送相关IRP给驱动程序,驱动程序遍历其创建的MDL链找到相应的MDL,然后进行数据提取和发送,请求处理完之后,驱动程序会自动清除这个
MDL。一个IRP可以关联多个MDL,就像上面举的例子一样,一个IRP关联到多个IP数据报(也就是多个MDL)。当应用成语的某个IRP要求一个新
的请求(可能是一个新的IP地址的IP数据报)时,驱动程序发现没有MDL与之联,这个时候该IP发送来一个IP数据报,这时驱动程序便建立一个MDL与
之关联,如果这是第一个新建的与这个IRP关联的MDL,那么驱动程把该MDL的地址赋值给MdlAddress。如果不是第一个,那么将把新建的MDL
放到上一个MDL的下一个单位,形成MDL 链。这就是MDL结构体中的第一个成员的含义所在。
总结:MDL就是描述一块虚拟内存的结构体,里面有个成员记录了多个页码,这些页码即处于各个不同物理地址的物理块的页号。
所以要对一块受系统保护的区域进行写操作的话,可以这样来修改它的保护属性:
1.创建一个MDL,显然里面的物理页号数组没有初始化 IoAllocateMdl
2.初始化页码数组,使之成为实际有效的MDL MmBuildMdlForNonPagedPool
3.进行锁定,并且重新赋值新的保护属性为可读 MmProbeAndLockPages
4.获得我们所映射后的实际内存区域的虚拟地址 MmMapLockedPagesSpecifyCache
网上的很多代码是用于2000和其之前的OS的,很多函数都改了,方式也不一样了,以下代码用于在SSDT表所在的内核区映射一个MDL,并且修改其只读属性为可写的,然后固定这块内存,防止它被其他应用程序修改。
g_pmdlSystemCall =IoAllocateMdl
(KeServiceDescriptorTable.ServiceTableBase,KeServiceDescriptorTable.NumberOfServices*4,FALSE,FALSE,NULL);
if(!g_pmdlSystemCall)
return STATUS_UNSUCCESSFUL;
MmBuildMdlForNonPagedPool(g_pmdlSystemCall);//初始化MDL页码数组
//g_pmdlSystemCall->MdlFlags = g_pmdlSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;// 改变MDL的flags为可读状态
MmProbeAndLockPages(g_pmdlSystemCall,KernelMode,IoWriteAccess);//在内存中锁定,并且指
明对它的改写权力
MappedSSDT=MmMapLockedPagesSpecifyCache( //映射被锁定内存,所谓映射,就是创建原来内存区的一个联合体,你
//修改了这个MDL,就是修改了它所描述的内存区
g_pmdlSystemCall,
KernelMode,
MeNonCached,//是否允许用作CPU缓冲区
FALSE,//当第二个参数为UserMode的时候才有效
NULL,//如果发生错误,直接返回NULL
); //MappedSSDT即映射后的SSDT地址
【注意】最后一个函数其实是大材小用了,只不过2000之后能得到映射缓冲区地址的函数中这个函数是最先进的被支持者,2000用的是MmMapLockedPages;
MDL详解的更多相关文章
- (转)MySQL备份原理详解
MySQL备份原理详解 原文:http://www.cnblogs.com/cchust/p/5452557.html 备份是数据安全的最后一道防线,对于任何数据丢失的场景,备份虽然不一定能恢复百分之 ...
- Python Fabric模块详解
Python Fabric模块详解 什么是Fabric? 简单介绍一下: Fabric是一个Python的库和命令行工具,用来提高基于SSH的应用部署和系统管理效率. 再具体点介绍一下,Fabri ...
- Linq之旅:Linq入门详解(Linq to Objects)
示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...
- 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)
一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...
- EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解
前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...
- Java 字符串格式化详解
Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...
- Android Notification 详解(一)——基本操作
Android Notification 详解(一)--基本操作 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Notification 文中如有纰 ...
- Android Notification 详解——基本操作
Android Notification 详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 前几天项目中有用到 Android 通知相关的内容,索性把 Android Notificatio ...
- Git初探--笔记整理和Git命令详解
几个重要的概念 首先先明确几个概念: WorkPlace : 工作区 Index: 暂存区 Repository: 本地仓库/版本库 Remote: 远程仓库 当在Remote(如Github)上面c ...
随机推荐
- Leecode刷题之旅-C语言/python-112 路径总和
/* * @lc app=leetcode.cn id=112 lang=c * * [112] 路径总和 * * https://leetcode-cn.com/problems/path-sum/ ...
- Vue2.5入门-3
安装和使用 全局安装vue npm install --global vue-cli 创建基于webpack模板的新项目 vue init webpack my-project 安装依赖 cd my- ...
- Opencv3.0-python: 编译报错color.cpp:7456: error: (-215) scn == 3 || scn == 4 的解决方案
结合Opencv3.0读取视频时,出现报错:C:\projects\opencv-python\opencv\modules\imgproc\src\color.cpp:11111: error: ( ...
- 基于MATLAB的多项式数据拟合方法研究-毕业论文
摘要:本论文先介绍了多项式数据拟合的相关背景,以及对整个课题做了一个完整的认识.接下来对拟合模型,多项式数学原理进行了详细的讲解,通过对文献的阅读以及自己的知识积累对原理有了一个系统的认识.介绍多项式 ...
- Linux入门进阶第二天——软件安装管理(上)
一.大纲介绍 这里介绍的仅仅是两大家族之一的RPM,关于Debian家族的DPKG,请参考:http://justcoding.iteye.com/blog/1937171 二.简介 软件包分类: 源 ...
- 20155216 2016-2017-2 《Java程序设计》第九周学习总结
20155216 2016-2017-2 <Java程序设计>第九周学习总结 教材学习内容总结 JDBC架构 JDBC API的使用 JDBC连接数据库 1.导入JDBC包: 添加impo ...
- 20145226夏艺华 《Java程序设计》实验报告五
实验五 Java网络编程及安全 实验内容 运行下载的TCP代码,结对进行 利用加解密代码包,编译运行代码,结对进行 集成代码,加密后通过TCP发送 结对伙伴:20145203 马超 实验步骤 (一)中 ...
- 【转载】混编ObjectiveC++
原文:混编ObjectiveC++ 最近有点炒冷饭的嫌疑,不过确实以前没有Git Or Blog的习惯,所以很多工作上的技术分享就存留在了电脑的文档里,现在还是想重新整理一下,再分享出来. 混编C++ ...
- 1、maven打包 install package deploy区别
maven package:打包到本项目,一般是在项目target目录下.如果a项目依赖于b项目,打包b项目时,只会打包到b项目下target下,编译a项目时就会报错. maven install:打 ...
- python环境通过selenium实现自动化web登陆及终端邀请
自动化主要的就是识别对象,可以在网上搜到各种各样的方法,自行百度.下面仅附上一个简单的例子. 环境搭建参考如下链接: https://www.cnblogs.com/hepeilinnow/p/101 ...