0x001 实验环境
xp3
2-9-9-12 分页环境
0x002 时间代码
// 20180327_01.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <stdio.h> #include <windows.h> DWORD zero, one, two; __declspec(naked) void MountPageOnNull() { __asm { push ebp mov ebp, esp sub esp, 0x100 push ebx push esi push edi } DWORD* pPTE; // 保存目标线性地址的 PTE 线性地址 DWORD* pNullPTE; // 0 地址的 PTE 线性地址 pNullPTE = (DWORD*)0xc0000000; // 挂上 0x50000000 所在位置 pPTE = (DWORD*)(0xc0000000 + ((0x50000000 >> 9) & 0x7ffff8)); *pNullPTE = *pPTE; zero = *(DWORD*)0; // 挂上 0x60000000 所在位置 pPTE = (DWORD*)(0xc0000000 + ((0x60000000 >> 9) & 0x7ffff8)); *pNullPTE = *pPTE; one = *(DWORD*)0; // 刷新 TLB __asm { mov eax, cr3 mov cr3, eax } // 再次读取 0 地址位置的数据 two = *(DWORD*)0; __asm { pop edi pop esi pop ebx mov esp, ebp pop ebp iretd } } // 外壳包裹函数 __declspec(naked) void MyMountPageOnNull() { __asm { int 0x20 ret } } int main(int argc, char* argv[]) { DWORD* x = (DWORD*)VirtualAlloc((LPVOID)0x50000000, 4, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); DWORD* y = (DWORD*)VirtualAlloc((LPVOID)0x60000000, 4, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); *x = 0x12345678; *y = 0x87654321; if (x != (DWORD*)0x50000000 || y != (DWORD*)0x60000000) { printf("Error alloc!\n"); return -1; } MyMountPageOnNull(); printf("1. 读 0 地址数据:\n"); printf("*NULL = 0x%08x\n\n", zero); printf("2. 给 0 地址重新挂上物理页\n\n"); printf("3. 重新读取 0 地址数据:\n"); printf("*NULL = 0x%08x\n\n", one); printf("4. 刷新 TLB \n\n"); printf("5. 再次读取 0 地址数据:\n"); printf("*NULL = 0x%08x\n", two); return 0; }
0x003 实验步骤
-
在 main 函数起始位置下断点,在 VC6.0 中观察到函数 MountPageOnNull的函数地址,在我的环境里是 0x00401030。
-
构造中断门描述符 0040ee00`00081030
-
中断到 WinDbg 中去,执行以下命令安装中断门
- 1
-
在 WinDbg 中执行命令
g
回到 xp 系统中。 -
继续执行 VC6.0 中的程序。
0x004 实验结果
0则评论给“TLB实验”