最近學習了一下PHYSICAL_MEMORY對象,總結之

最近學習了一下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成功了,但用物理內存卻沒有成功,貌似我沒有遇到過這種情況,呵呵!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章