最近學習了一下Windows的內存管理方面的知識,包括了PTE的修改和PHYSICAL_MEMORY的內核對象。
從網上得到了一段殺傷力很強的代碼(似乎是Zwell以前寫的) ,就是通過設置物理內存對象的可讀寫,再加上映射PTE的方式從而在Ring3環境下讀取內核數據。這正是我想要,於是乎嚴重地學習了一下,前面已經有人總結過關鍵步驟了,如下:
1、用ZwOpenSection打開PHYSICAL_MEMORY對象,並設置可讀寫
2、進行虛擬地址到物理地址的轉換
3、用NtMapViewOfSection進行映射,(用MapViewOfFile也可以)
4、讀取或寫入數據(但不是每個地方都能寫的)
5、用NtUnmapViewOFSection取消映射(也可以使用UnMapViewOfFile),並關閉句柄(ZwClose)
經過這幾步之後就可以爲所欲爲了,下面貼一段將虛擬地址轉換成物理地址的代碼,(在此得感謝Zwell的代碼,使我的學習過程簡化了不少):
//----------------------------------------------------------------
// paramenter : PULONG
// PVOID
// return : PVOID
// convert linear address to physical address
//----------------------------------------------------------------
PVOID LinearToPhys(PULONG BaseAddress, PVOID addr)
{
ULONG VAddr = (ULONG)addr, PGDE, PTE, PAddr;
if ( VAddr >= 0x80000000 && VAddr < 0xa0000000 )//對於虛擬地址在0x80000000至0xa0000000這間的
{ //可以將虛擬的高3位置0,這樣就能得到物理地址
PAddr = VAddr - 0x80000000;
return (PVOID)PAddr;
}
PGDE = BaseAddress[ VAddr >> 22 ]; //在PDT中索引得到PDE
if ( (PGDE&1) != 0 )
{
ULONG tmp = PGDE & 0x00000080; //如果是4M的分頁則沒有PageTable,用PDE的高10位 加上
if ( tmp!=0 ) //虛擬地址的低22位就可以了,所說這樣是爲性能的考慮
{
PAddr = ( PGDE & 0xFFC00000 ) + ( VAddr & 0x003FFFFF );
}
else //如果是4K的分頁
{
PGDE = (ULONG) MapViewOfFile ( //映射到物理內存
g_hMPM,
FILE_MAP_ALL_ACCESS,
0,
PGDE & 0xfffff000,
0x1000
);
PTE = ( (PULONG)PGDE )[ (VAddr&0x003FF000) >> 12 ]; //用虛擬地址的中間10位來索引到PTE
if ( (PTE&1) != 0 ) //是否有效
{
PAddr = ( PTE & 0xFFFFF000 ) + ( VAddr & 0x00000FFF );//用PTE的高20位加上虛擬地址的低12
UnmapViewOfFile( (PVOID)PGDE ); //就可以了,這時取消映射
}
else return 0;
}
}
else return 0;
return (PVOID)PAddr;
}
這是主要的代碼了,另外還有一段代碼就是用來打開對象,並設置其可讀寫的,後來自已加了一點代碼(不超過15行)就可以指哪打哪了。
當時爲了試驗隨便改了一下,不想改的就是PTE,後來在啓動IceSwrod的時候直接重啓了,比較汗。
以前聽HOPY說,他用驅動試的修改PTE成功了,但用物理內存卻沒有成功,貌似我沒有遇到過這種情況,呵呵!