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源码

  1 //
  2 // Protection data for MiMakeProtectionMask
  3 //
  4 
  5 CCHAR MmUserProtectionToMask1[16] = {
  6                                  0,
  7                                  MM_NOACCESS,
  8                                  MM_READONLY,
  9                                  -1,
 10                                  MM_READWRITE,
 11                                  -1,
 12                                  -1,
 13                                  -1,
 14                                  MM_WRITECOPY,
 15                                  -1,
 16                                  -1,
 17                                  -1,
 18                                  -1,
 19                                  -1,
 20                                  -1,
 21                                  -1 };
 22 
 23 CCHAR MmUserProtectionToMask2[16] = {
 24                                  0,
 25                                  MM_EXECUTE,
 26                                  MM_EXECUTE_READ,
 27                                  -1,
 28                                  MM_EXECUTE_READWRITE,
 29                                  -1,
 30                                  -1,
 31                                  -1,
 32                                  MM_EXECUTE_WRITECOPY,
 33                                  -1,
 34                                  -1,
 35                                  -1,
 36                                  -1,
 37                                  -1,
 38                                  -1,
 39                                  -1 };
 40 
 41 
 42 MM_PROTECTION_MASK
 43 FASTCALL
 44 MiMakeProtectionMask (
 45     IN WIN32_PROTECTION_MASK Win32Protect
 46     )
 47 
 48 /*++
 49 
 50 Routine Description:
 51 
 52     This function takes a user supplied protection and converts it
 53     into a 5-bit protection code for the PTE.
 54 
 55 Arguments:
 56 
 57     Win32Protect - Supplies the protection.
 58 
 59 Return Value:
 60 
 61     Returns the protection code for use in the PTE.  Note that
 62     MM_INVALID_PROTECTION (-1) is returned for an invalid protection
 63     request.  Since valid PTE protections fit in 5 bits and are
 64     zero-extended, it's easy for callers to distinguish this.
 65 
 66 Environment:
 67 
 68     Kernel Mode.
 69 
 70 --*/
 71 
 72 {
 73     ULONG Field1;
 74     ULONG Field2;
 75     MM_PROTECTION_MASK ProtectCode;
 76 
 77     if (Win32Protect >= (PAGE_WRITECOMBINE * 2)) {
 78         return MM_INVALID_PROTECTION;
 79     }
 80 
 81     Field1 = Win32Protect & 0xF;
 82     Field2 = (Win32Protect >> 4) & 0xF;
 83 
 84     //
 85     // Make sure at least one field is set.
 86     //
 87 
 88     if (Field1 == 0) {
 89         if (Field2 == 0) {
 90 
 91             //
 92             // Both fields are zero, return failure.
 93             //
 94 
 95             return MM_INVALID_PROTECTION;
 96         }
 97         ProtectCode = MmUserProtectionToMask2[Field2];
 98     }
 99     else {
100         if (Field2 != 0) {
101             //
102             //  Both fields are non-zero, return failure.
103             //
104 
105             return MM_INVALID_PROTECTION;
106         }
107         ProtectCode = MmUserProtectionToMask1[Field1];
108     }
109 
110     if (ProtectCode == -1) {
111         return MM_INVALID_PROTECTION;
112     }
113 
114     if (Win32Protect & PAGE_GUARD) {
115 
116         if ((ProtectCode == MM_NOACCESS) ||
117             (Win32Protect & (PAGE_NOCACHE | PAGE_WRITECOMBINE))) {
118 
119             //
120             // Invalid protection -
121             // guard and either no access, no cache or write combine.
122             //
123 
124             return MM_INVALID_PROTECTION;
125         }
126 
127         MI_ADD_GUARD (ProtectCode);
128     }
129 
130     if (Win32Protect & PAGE_NOCACHE) {
131 
132         ASSERT ((Win32Protect & PAGE_GUARD) == 0);  // Already checked above
133 
134         if ((ProtectCode == MM_NOACCESS) ||
135             (Win32Protect & PAGE_WRITECOMBINE)) {
136 
137             //
138             // Invalid protection -
139             // nocache and either no access or write combine.
140             //
141 
142             return MM_INVALID_PROTECTION;
143         }
144 
145         MI_ADD_NOCACHE (ProtectCode);
146     }
147 
148     if (Win32Protect & PAGE_WRITECOMBINE) {
149 
150         ASSERT ((Win32Protect & (PAGE_GUARD|PAGE_NOACCESS)) == 0);  // Already checked above
151 
152         if (ProtectCode == MM_NOACCESS) {
153 
154             //
155             // Invalid protection, no access and write combine.
156             //
157 
158             return MM_INVALID_PROTECTION;
159         }
160 
161         MI_ADD_WRITECOMBINE (ProtectCode);
162     }
163 
164     return ProtectCode;
165 }

 

 

 

 

 

 

posted @ 2019-10-27 20:25  OneTrainee  阅读(2146)  评论(0编辑  收藏  举报