Windows內核分析索引目錄:https://www.cnblogs.com/onetrainee/p/11675224.htmlhtml
技術學習來源:火哥(QQ:471194425)數組
R3環申請內存時頁面保護與_MMVAD_FLAGS.Protection位的對應關係app
咱們以前有過一篇關於 VAD 的介紹,其中 _MMVAD_FLAGS.Protection 中描述了頁的屬性。函數
咱們知道在R3下申請內存時也會定義內存的屬性,但經過搜索數值,發現這倆並不相同,這很讓人產生疑惑。學習
下面就來解答這一疑惑。ui
1、R3與R0的定義this
1)在R3環的定義
spa
#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 code
2)在R0環的定義htm
#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
2、內核函數 MiMakeProtectionMask
該內核函數負責將這些定義在R3環的值轉換爲R0環。
1)首先,將R3環的定義分爲Field1(低字節)與Field2(高字節),好比 0x01,分爲 Field1 = 1 / Field2 = 0。
2)以後,其分別會去表中查找(在下面源碼開頭的兩個數組),表中攜帶的就是真正在R0中定義的值。
3)以後將R0的值賦在 _MMVAD_FLAGS.Protection位。
3、分析驗證:
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 ,則符合要求,驗證成功。
4、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 }