R3环申请内存时页面保护与_MMVAD_FLAGS.Protection位的对应关系
Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html
R3环申请内存时页面保护与_MMVAD_FLAGS.Protection位的对应关系
我们之前有过一篇关于 VAD 的介绍,其中 _MMVAD_FLAGS.Protection 中描述了页的属性。
我们知道在R3下申请内存时也会定义内存的属性,但通过搜索数值,发现这俩并不相同,这很让人产生疑惑。
下面就来解答这一疑惑。
一、R3与R0的定义
1)在R3环的定义
#define PAGE_NOACCESS 0x01
#define PAGE_READONLY 0x02
#define PAGE_READWRITE 0x04
#define PAGE_WRITECOPY 0x08
#define PAGE_EXECUTE 0x10
#define PAGE_EXECUTE_READ 0x20
#define PAGE_EXECUTE_READWRITE 0x40
#define PAGE_EXECUTE_WRITECOPY 0x80
2)在R0环的定义
#define MM_ZERO_ACCESS 0 // this value is not used.
#define MM_READONLY 1
#define MM_EXECUTE 2
#define MM_EXECUTE_READ 3
#define MM_READWRITE 4 // bit 2 is set if this is writable.
#define MM_WRITECOPY 5
#define MM_EXECUTE_READWRITE 6
#define MM_EXECUTE_WRITECOPY 7
二、内核函数 MiMakeProtectionMask
该内核函数负责将这些定义在R3环的值转换为R0环。
1)首先,将R3环的定义分为Field1(低字节)与Field2(高字节),比如 0x01,分为 Field1 = 1 / Field2 = 0。
2)之后,其分别会去表中查找(在下面源码开头的两个数组),表中携带的就是真正在R0中定义的值。
3)之后将R0的值赋在 _MMVAD_FLAGS.Protection位。
三、分析验证:
1)我们随便遍历一个进程的VAD树,选中一个结点,其为只读属性。
81af63e8 9 3f0 3f2 0 Mapped READONLY \WINDOWS\system32\ctype.nls
2)我们查看其Protection值
kd> dt _MMVAD_FLAGS 81af63e8+0x14
+0x000 Protection : 0y00001 (0x1)
3)我们通过查看R0中的定义可知0x1对应的MM_READONLY,符合要求。
4)MM_READONLY 又在 MmUserProtectionToMask1 表中的第三个位置(索引为2),故其在三环的定义应该为 0x02.
5)查看定义, #define PAGE_READONLY 0x02 ,则符合要求,验证成功。
四、Field表及MiMakeProtectionMask源码
//
// Protection data for MiMakeProtectionMask
// CCHAR MmUserProtectionToMask1[] = {
,
MM_NOACCESS,
MM_READONLY,
-,
MM_READWRITE,
-,
-,
-,
MM_WRITECOPY,
-,
-,
-,
-,
-,
-,
- }; CCHAR MmUserProtectionToMask2[] = {
,
MM_EXECUTE,
MM_EXECUTE_READ,
-,
MM_EXECUTE_READWRITE,
-,
-,
-,
MM_EXECUTE_WRITECOPY,
-,
-,
-,
-,
-,
-,
- }; MM_PROTECTION_MASK
FASTCALL
MiMakeProtectionMask (
IN WIN32_PROTECTION_MASK Win32Protect
) /*++ Routine Description: This function takes a user supplied protection and converts it
into a 5-bit protection code for the PTE. Arguments: Win32Protect - Supplies the protection. Return Value: Returns the protection code for use in the PTE. Note that
MM_INVALID_PROTECTION (-1) is returned for an invalid protection
request. Since valid PTE protections fit in 5 bits and are
zero-extended, it's easy for callers to distinguish this. Environment: Kernel Mode. --*/ {
ULONG Field1;
ULONG Field2;
MM_PROTECTION_MASK ProtectCode; if (Win32Protect >= (PAGE_WRITECOMBINE * )) {
return MM_INVALID_PROTECTION;
} Field1 = Win32Protect & 0xF;
Field2 = (Win32Protect >> ) & 0xF; //
// Make sure at least one field is set.
// if (Field1 == ) {
if (Field2 == ) { //
// Both fields are zero, return failure.
// return MM_INVALID_PROTECTION;
}
ProtectCode = MmUserProtectionToMask2[Field2];
}
else {
if (Field2 != ) {
//
// Both fields are non-zero, return failure.
// return MM_INVALID_PROTECTION;
}
ProtectCode = MmUserProtectionToMask1[Field1];
} if (ProtectCode == -) {
return MM_INVALID_PROTECTION;
} if (Win32Protect & PAGE_GUARD) { if ((ProtectCode == MM_NOACCESS) ||
(Win32Protect & (PAGE_NOCACHE | PAGE_WRITECOMBINE))) { //
// Invalid protection -
// guard and either no access, no cache or write combine.
// return MM_INVALID_PROTECTION;
} MI_ADD_GUARD (ProtectCode);
} if (Win32Protect & PAGE_NOCACHE) { ASSERT ((Win32Protect & PAGE_GUARD) == ); // Already checked above if ((ProtectCode == MM_NOACCESS) ||
(Win32Protect & PAGE_WRITECOMBINE)) { //
// Invalid protection -
// nocache and either no access or write combine.
// return MM_INVALID_PROTECTION;
} MI_ADD_NOCACHE (ProtectCode);
} if (Win32Protect & PAGE_WRITECOMBINE) { ASSERT ((Win32Protect & (PAGE_GUARD|PAGE_NOACCESS)) == ); // Already checked above if (ProtectCode == MM_NOACCESS) { //
// Invalid protection, no access and write combine.
// return MM_INVALID_PROTECTION;
} MI_ADD_WRITECOMBINE (ProtectCode);
} return ProtectCode;
}
最新文章
- 无法将类型为“Microsoft.Office.Interop.Word.ApplicationClass”的 COM 对象强制转换为接口类型“Microsoft.Office.Interop.Word._Application”。
- Abp Application级别的生命周期
- AIDL实例
- 有关Color和Drawable你所不知道的那些内容
- ASP.NET MVC- VIEW Overview Part 1
- 爱的歌我uhegierhiuerh5怕哦一
- 主机连不上虚拟机中的Redis的原因分析、以及虚拟机网络配置
- GET和POST两种基本请求方法的区别
- SGD、GD
- struts2自定义转换器
- postman测试请求参数中文乱码问题
- NOIP2002-2017普及组题解
- 关于mysql远程连接
- Jenkins实现SVN+Maven+Java项目的持续集成
- 轮询、中断、DMA和通道
- django的url的name参数的意义
- Jmeter入门--可执行元件
- 【日常训练】 Help Greg the Dwarf(CodeForces-99E)
- jQuery语法小结(超实用)
- Java类的设计----方法的重写、覆盖