2-9-9-12分页(下)
附:找到pdt:pde最后一个看看是否有物理页
1:)给0线性地址挂上物理页
打开windbg查看cr4
查看0的物理地址,发现没有挂物理页
利用写出代码,打印b的地址,并且把b的物理页也打印出来
将0号地址修改为跟b的相同的物理页上
打印相应地址的值
2:)逆向MnIsAddressValid
源代码
1 80514928 8bff mov edi,edi 2 8051492a 55 push ebp 3 8051492b 8bec mov ebp,esp 4 8051492d 51 push ecx 5 8051492e 51 push ecx 6 8051492f 8b4d08 mov ecx,dword ptr [ebp+8] 7 80514932 56 push esi 8 80514933 8bc1 mov eax,ecx 9 80514935 c1e812 shr eax,12h //将线性地址右移18位 10 80514938 bef83f0000 mov esi,3FF8h //0011 1111 1111 1000 11 8051493d 23c6 and eax,esi // 12 8051493f 2d0000a03f sub eax,3FA00000h //+ c0600000 13 80514944 8b10 mov edx,dword ptr [eax] //低4字节给edx 14 80514946 8b4004 mov eax,dword ptr [eax+4]//高4字节给eax 15 80514949 8945fc mov dword ptr [ebp-4],eax // 16 8051494c 8bc2 mov eax,edx 17 8051494e 57 push edi 18 8051494f 83e001 and eax,1 //获取最低位 19 80514952 33ff xor edi,edi 20 80514954 0bc7 or eax,edi 21 80514956 7461 je nt!MmIsAddressValid+0x91 (805149b9)//判断P位是否为1,验证地址是否有效 22 80514958 bf80000000 mov edi,80h //1000 0000 23 8051495d 23d7 and edx,edi //把ps位给edx 24 8051495f 6a00 push 0 25 80514961 8955f8 mov dword ptr [ebp-8],edx 26 80514964 58 pop eax 27 80514965 7404 je nt!MmIsAddressValid+0x43 (8051496b) //判断低地址的ps位是否为1,为1则是大页否则是小页,小页便跳转到0x8051496b,否则跳转到805149bd 28 80514967 85c0 test eax,eax //判断是否为0 29 80514969 7452 je nt!MmIsAddressValid+0x95 (805149bd) 30 8051496b c1e909 shr ecx,9 31 8051496e 81e1f8ff7f00 and ecx,7FFFF8h //0111 1111 1111 1111 1111 1000 32 80514974 8b81040000c0 mov eax,dword ptr [ecx-3FFFFFFCh] 33 8051497a 81e900000040 sub ecx,40000000h //pte 34 80514980 8b11 mov edx,dword ptr [ecx] 35 80514982 8945fc mov dword ptr [ebp-4],eax 36 80514985 53 push ebx 37 80514986 8bc2 mov eax,edx 38 80514988 33db xor ebx,ebx 39 8051498a 83e001 and eax,1 40 8051498d 0bc3 or eax,ebx 41 8051498f 5b pop ebx 42 80514990 7427 je nt!MmIsAddressValid+0x91 (805149b9) 43 80514992 23d7 and edx,edi 44 80514994 6a00 push 0 45 80514996 8955f8 mov dword ptr [ebp-8],edx 46 80514999 58 pop eax 47 8051499a 7421 je nt!MmIsAddressValid+0x95 (805149bd) 48 8051499c 85c0 test eax,eax 49 8051499e 751d jne nt!MmIsAddressValid+0x95 (805149bd) 50 805149a0 23ce and ecx,esi 51 805149a2 8b89000060c0 mov ecx,dword ptr [ecx-3FA00000h] 52 805149a8 b881000000 mov eax,81h 53 805149ad 23c8 and ecx,eax 54 805149af 33d2 xor edx,edx 55 805149b1 3bc8 cmp ecx,eax 56 805149b3 7508 jne nt!MmIsAddressValid+0x95 (805149bd) 57 805149b5 85d2 test edx,edx 58 805149b7 7504 jne nt!MmIsAddressValid+0x95 (805149bd) 59 805149b9 32c0 xor al,al 60 805149bb eb02 jmp nt!MmIsAddressValid+0x97 (805149bf) 61 805149bd b001 mov al,1 62 805149bf 5f pop edi 63 805149c0 5e pop esi 64 805149c1 c9 leave 65 805149c2 c20400 ret 4
找到pte存储pde的pdt
6 8051492f 8b4d08 mov ecx,dword ptr [ebp+8] 7 80514932 56 push esi 8 80514933 8bc1 mov eax,ecx 9 80514935 c1e812 shr eax,12h //将线性地址右移18位 10 80514938 bef83f0000 mov esi,3FF8h //0011 1111 1111 1000 11 8051493d 23c6 and eax,esi // 12 8051493f 2d0000a03f sub eax,3FA00000h //+ c0600000 13 80514944 8b10 mov edx,dword ptr [eax] //低4字节给edx 14 80514946 8b4004 mov eax,dword ptr [eax+4]//高4字节给eax 15 80514949 8945fc mov dword ptr [ebp-4],eax //
验证pde的p位和ps位是否为0,如果p位为0直接返回
17 8051494e 57 push edi 18 8051494f 83e001 and eax,1 //获取最低位 19 80514952 33ff xor edi,edi 20 80514954 0bc7 or eax,edi 21 80514956 7461 je nt!MmIsAddressValid+0x91 (805149b9)//判断P位是否为1,验证地址是否有效 22 80514958 bf80000000 mov edi,80h //1000 0000 23 8051495d 23d7 and edx,edi //把ps位给edx 24 8051495f 6a00 push 0 25 80514961 8955f8 mov dword ptr [ebp-8],edx 26 80514964 58 pop eax 27 80514965 7404 je nt!MmIsAddressValid+0x43 (8051496b) //判断低地址的ps位是否为1,为1则是大页否则是小页,小页便跳转到0x8051496b,否则跳转到805149bd 28 80514967 85c0 test eax,eax //判断是否为0 29 80514969 7452 je nt!MmIsAddressValid+0x95 (805149bd)
找到存储物理地址的pte,并验证p位和ps位
8051496b c1e909 shr ecx,9 8051496e 81e1f8ff7f00 and ecx,7FFFF8h 80514974 8b81040000c0 mov eax,dword ptr [ecx-3FFFFFFCh] 8051497a 81e900000040 sub ecx,40000000h 80514980 8b11 mov edx,dword ptr [ecx] 80514982 8945fc mov dword ptr [ebp-4],eax 80514985 53 push ebx 80514986 8bc2 mov eax,edx 80514988 33db xor ebx,ebx 8051498a 83e001 and eax,1 8051498d 0bc3 or eax,ebx 8051498f 5b pop ebx 80514990 7427 je nt!MmIsAddressValid+0x91 (805149b9) 80514992 23d7 and edx,edi 80514994 6a00 push 0 80514996 8955f8 mov dword ptr [ebp-8],edx 80514999 58 pop eax 8051499a 7421 je nt!MmIsAddressValid+0x95 (805149bd) 8051499c 85c0 test eax,eax 8051499e 751d jne nt!MmIsAddressValid+0x95 (805149bd)
找到对应物理页,并验证属性
805149a0 23ce and ecx,esi 805149a2 8b89000060c0 mov ecx,dword ptr [ecx-3FA00000h] 805149a8 b881000000 mov eax,81h 805149ad 23c8 and ecx,eax 805149af 33d2 xor edx,edx 805149b1 3bc8 cmp ecx,eax 805149b3 7508 jne nt!MmIsAddressValid+0x95 (805149bd) 805149b5 85d2 test edx,edx 805149b7 7504 jne nt!MmIsAddressValid+0x95 (805149bd) 805149b9 32c0 xor al,al 805149bb eb02 jmp nt!MmIsAddressValid+0x97 (805149bf) 805149bd b001 mov al,1 805149bf 5f pop edi 805149c0 5e pop esi 805149c1 c9 leave 805149c2 c20400 ret 4
3、编写代码实现修改页属性,实现应用层读写高2G内存地址
这里先感谢一个师傅的博客,实验写的很详细
思路分析:
- 不管是页目录表还是页表基址都是属于高2G的内存,那我们肯定是需要通过门的提权来实现对高两G的写
- 由于修改了高2G的页属性,所以我们通过另一个应用程序来访问被修改的页属性,如果成功,代表修改成功,否则修改失败
修改PDE和PTE公式
1 2-9-9-12
2 PDPTI-PDI-PTI-OFFSET
3
4 公式:
5 pPDE = 0xc0600000 + (PDPTI*4KB) + (PDI*8)
6 pPTE = 0xc0000000 + (PDPTI*2MB) + (PDI*4KB) + (PTI*8)
7
8 更高效的公式(MmIsAddressValid是这么干的)
9 pPDE = 0xc0600000 + ((addr >> 18) & 0x3ff8)
10 pPTE = 0xc0000000 + ((addr >> 9) & 0x7ffff8)
测试代码(这里非常感谢那位师傅)
1 // Phy_Memory.cpp : Defines the entry point for the console application. 2 // 3 4 #include "stdafx.h" 5 #include<stdlib.h> 6 #include<windows.h> 7 8 char buf[6]={0,0,0,0,0x48,0}; 9 10 DWORD *GetPDE(DWORD addr) 11 { 12 //return (DWORD *)(0xc0600000 + ((addr >> 18) & 0x3ff8)); 13 DWORD PDPTI = addr >> 30; 14 DWORD PDI = (addr >> 21) & 0x000001FF; 15 DWORD PTI = (addr >> 12) & 0x000001FF; 16 return (DWORD *)(0xC0600000 + PDPTI * 0x1000 + PDI * 8); 17 } 18 19 DWORD *GetPTE(DWORD addr) 20 { 21 //return (DWORD *)(0xc0000000 + ((addr >> 9) & 0x7ffff8)); 22 DWORD PDPTI = addr >> 30; 23 DWORD PDI = (addr >> 21) & 0x000001FF; 24 DWORD PTI = (addr >> 12) & 0x000001FF; 25 return (DWORD *)(0xC0000000 + PDPTI * 0x200000 + PDI * 0x1000 + PTI * 8); 26 } 27 28 __declspec(naked) void func() 29 { 30 __asm 31 { 32 pushad 33 pushfd 34 } 35 36 *GetPDE(0x8003f048) |=0x00000004; 37 *GetPTE(0x8003f048) |=0x00000004; 38 39 *GetPTE(0x8003f048) &= 0xFFFFFEFF; 40 41 __asm 42 { 43 popad 44 popfd 45 iretd 46 } 47 } 48 49 50 51 int main(int argc, char* argv[]) 52 { 53 54 printf("在IDT表构建中断门,请在windbg中执行下面的指令:\n"); 55 printf("eq 8003f500 %04xee00`0008%04x",(DWORD)func>>16,(DWORD)func&0x0000ffff); 56 57 getchar(); 58 59 __asm int 0x20; 60 printf("0x8003f048 U/S,G位修改成功.\n"); 61 printf("*(PDWORD)0x8003f048 = %08x\n", *(PDWORD)0x8003f048); 62 *(PDWORD)0x8003f048 = 0x12345678; 63 printf("*(PDWORD)0x8003f048 = %08x\n", *(PDWORD)0x8003f048); 64 getchar(); 65 66 return 0; 67 }
执行后
知识总结
- 2-9-9-12分页中,pte是0xc0000000,pde是0xc0600000
- 两种在线性地址的计算方式
-
公式: pPDE = 0xc0600000 + (PDPTI*4KB) + (PDI*8) pPTE = 0xc0000000 + (PDPTI*2MB) + (PDI*4KB) + (PTI*8) 更高效的公式(MmIsAddressValid是这么干的) pPDE = 0xc0600000 + ((addr >> 18) & 0x3ff8) pPTE = 0xc0000000 + ((addr >> 9) & 0x7ffff8)
不足处
- 看了上面那位师傅博客后,感觉自己的博客写的很烂
- 其次是自己对这些基础的了解远不如别人了解,需要每天都记忆一遍,来加深记忆
- 动手能力没有别的师傅那么厉害,在这里在谢谢一下,博客写的真的很好,需要向他学习