10 10 12分页模式下
// readPageAttr.cpp : 定义控制台应用程序的入口点。
//调用门段描述符 0041ec00`000813c0
#include "stdafx.h"
DWORD PDE=0;
DWORD PTE=0;
DWORD dwPDT_Index=0;
DWORD dwPTT_Index=0;
DWORD dwPageIndex=0;
DWORD WritePTE;
BOOL bWrite=false;
char callAddr[20]={0};
void _declspec(naked) test()
{
_asm
{
push 0x30
pop fs
pushad
pushfd
//PDE=0xc0300000+PDI*4
mov eax,0xc0300000
//dwPDT_Index=PDI
mov ecx,dwPDT_Index
shl ecx,2
//eax=PED的指针
add eax,ecx
//读出pde的值
mov ebx,[eax]
//保存在全局变量PDE
mov PDE,ebx
//解析PTE 0xc0000000+PDI*4096+PTI*4
//在上面已经移了2位 再左移10位就是4096
shl ecx,10
//eax=PTI
mov eax,dwPTT_Index
shl eax,2
//ebx=PTE的指针
mov ebx,0xc0000000
add ebx,eax
add ebx,ecx
//如果标志位是true就挂PTE
//两次进入调用门,第一次是获取要挂载的PTE 第二次是把PTE写到0地址的PTE
mov edx,bWrite;
cmp edx,0
jz s
//eax保存PTE物理地址
mov eax,WritePTE
//把物理地址挂载到0地址的PTE处
mov [ebx],eax
jmp a
//读取PTE的值保存
s:mov ebx,[ebx]
mov PTE,ebx
a:popfd
popad
retf
}
}
void ParsePage(DWORD dwAddr)
{
//10 10 12分页模式
//获取PDT索引
dwPDT_Index=(dwAddr>>22);
//获取PTT的索引
dwPTT_Index=((dwAddr<<10)>>22);
dwPageIndex=(dwAddr&0xfff);
}
void CallGate()
{
char buffer[6]={0};
*(DWORD*)&buffer[0]=0;
*(WORD*)&buffer[4]=0x4b;
_asm
{
call fword ptr [buffer]
push 0x3b
pop fs
}
}
int _tmain(int argc, _TCHAR* argv[])
{
ParsePage((DWORD)callAddr);
CallGate();
WritePTE=PTE;
bWrite=TRUE;
ParsePage(0);
CallGate();
DWORD *p=(DWORD*)0;
*p=10;
printf("0x00000000=%d",*p);
getchar();
return 0;
}