記一次面試(有關windows下分頁機制淺談)

引子:
 最近一直在研究惡意代碼方向與逆向軟件方向,面試聊了windows內核與保護模式相關知識,有很多沒有回答上來,以前確實研究過相關資料,但是沒有深入研究,加上長時間沒有複習,就很尬尷了。
 還是自己基本功還不紮實,畢竟好久沒寫過驅動編程與複習內核/保護模式相關的知識,所以靜下心來複習一下吧。

 每個可執行文件映像到內存中之後,都會有4GB大小的虛擬內存。說到這裏,面試的時候還問了一下4kb最大尋址,當時我就想說4GB,還是有點緊張,這麼基礎的問題竟然支支吾吾的最後說個0xffffffff,沒有完善的回答上來,簡直丟人啊!4kb-->32bit,沒老臉了。

4GB的虛擬內存結構:

虛擬內存地址範圍 描述
0x00000000~0x0000FFFF 64kb大小的空指針區域,當然就不可以訪問了
0x00001000~0x7FFFFFFF 加上上述的空指針區域,低2GB的用戶態空間
0x80000000~0xFFFFFFFF 高2GB的內核態空間

更多的詳細劃分請參考這篇博客:https://blog.csdn.net/wang010366/article/details/52730052


一個進程地址如何映射到物理地址的?
記一次面試(有關windows下分頁機制淺談)
                    圖片一:映射關係
 上述圖片只是片面的闡釋,一個虛擬內存地址通過頁錶轉換,映射到物理內存地址,多個進程其實都是通過這種機制映射到物理內存。
記一次面試(有關windows下分頁機制淺談)
                    圖片二:地址映射過程

 圖片二是虛擬地址映射,注意:缺少了分頁的層級,頁表中每一項都是一個分頁。映射的物理地址過程如何實現的?先介紹Cr0系列的控制寄存器,面試的時候忘的一乾二淨,那就在學一遍:

寄存器名稱 描述
CR0 包含處理器標誌控制位,如PE,PG,WP等
CR1 保留
CR2 專門用於保存缺頁異常時的線性地址
CR3 保存進程頁目錄地址
CR4 擴展功能(如判斷物理地址擴展模式等),Pentium系列(包括486的後期版本)處理器中才實現

記一次面試(有關windows下分頁機制淺談)

                    圖片三:控制寄存器

➀什麼是PE,PG,WP呢?
 1、PE:CR0寄存器的第0位,Protection Enable,啓用保護標誌。如果該位爲1,開啓了保護模式,反之關閉,當開啓保護模式的時候PE\PG都會置位。
 2、PG:CR0寄存器的第31位,Paging,分頁標誌位。如果爲1則開啓分頁機制,禁止分頁的話線性地址等同於物理地址,若開啓標誌位意味着需要開啓保護模式。
 3、WP:CR0寄存器的第16位,Write Proctect,寫保護標誌。WP==1的時候意味着只讀頁面不可執行寫操作,wp==0的時候意味着只讀頁面可執行寫操作。


➁CR3寄存器保存了每個進程的頁目錄地址,什麼叫做頁目錄呢?
 Windows下開啓保護模式與分頁機制後,當前CR0寄存器的屬性PE == 1 AND PG == 1,意味着進程中的虛擬地址將通過頁錶轉換映射相對應的物理地址上,如圖二所示,我們手工的獲取來學習:
首先介紹一下分頁機制其中一種記錄方式:

非物理地址擴展模式 物理地址擴展模式
  非PAE模式   PAE模式


 PAE模式:Physical address extension,物理擴展模式。能夠在32位操作系統訪問超過4GB尋址大小的模式,允許將最多64GB 的物理內存用作常規的4 KB 頁面,並擴展內核能使用的位數以將物理內存地址從32擴展到36。
 非PAE模式:在非物理擴展模式下,32位最大隻能4GB所以,即使你有8G的內存條,也是白費。
 那麼在非PAE模式下,操作系統分頁機制如何實現的?每個分頁4kb,一共4GB的內存,4194304KB大小也就是一共1048576個分頁,那麼如何高效的管理這些分頁呢?

 1024(PDT) × 1024(PTT) × 4096 = 4GB
 1024(PTT) × 1024(PTE) × 4 = 4MB
 1024(PDT) ×1024(PTE) = 1MB

如上述公式所示,就是通過這種方式來管理4GB的內存分頁,PDT,PTT,PTE又是什麼,如下所示

名稱 描述
頁目錄索引表(PDT) 一級索引
頁表索引表(PTT) 二級索引
頁表項(PTE) 頁表項 PDT(1024項PTE),PTT(1024項PTE)

記一次面試(有關windows下分頁機制淺談)
                   圖片四:地址解析

 需要配合圖二一起理解,操作系統會通過CR3寄存器獲取當前進程的頁表目錄地址,然後根據虛擬地址拆分爲10,10,12比例,找到頁目錄,找到頁表,然後找到分頁加上對應的偏移(物理內存),爲了方便理解,當然也是動手寫個小程序,在windbg下一探究竟。


➀編寫測試代碼,如下所示:

int main()
{
    printf("虛擬地址:0x%X\n", "hello world");
    cout << "hello world" << endl;
    system("pause");
}

 ➁編譯後拖入虛擬機,開啓雙擊調試(測試環境win7 32位),運行測試程序(不要關閉回車),windbg下輸入!process 0 0查看全部進程及各部分說明,如下所示:
記一次面試(有關windows下分頁機制淺談)
                 圖片五:雙擊調試
 ➂上述進程說明中我們看到DirBase地址,這個就是當前進程指向的頁目錄,我們看看到底對不對?需要明確的字段PROCESS 0x86ca5c18是EPROCESS的地址,輸入指令dt 0x86ca5c18 _EPROCESS來看一看,如下所示:
記一次面試(有關windows下分頁機制淺談)

                 圖片六:EPROCESS
 ➃一個進程的頁目錄怎樣找?在CreateProcess的第二個階段,會初始化進程的執行體層EPROCESS數據結構與微內核層KPROCESS數據結構,系統DLL映像目標用戶空間且初始化PEB操等等,來看_KPROCESS結構+0x18字段是什麼?如下所示:
記一次面試(有關windows下分頁機制淺談)

                 圖片七:DirectoryTableBase

 ➄通過上述_KPROCESS獲取了PDT的地址,與解析出來PDT數據一樣的。每當CPU切片執行進程時候,CR3就會被系統切換,CR3是不是讀取當前進程DirectoryTableBase字段作爲切換數值有待研究,看一看PDT也就是頁錶轉換的第一層結構,如下所示:
記一次面試(有關windows下分頁機制淺談)

                 圖片八:虛擬地址

 ➅解釋兩個dd,因爲這個以前也總是被同學問起,dd怎麼啥東西都找不到,在windbg命令下,d系列命令只能查看虛擬地址, 查看物理地址需要使用!d系列命令,PDT是物理地址,如下所示:
記一次面試(有關windows下分頁機制淺談)
記一次面試(有關windows下分頁機制淺談)
                 圖片九:物理地址
 ➆根據上述一些理論性知識,如圖九中所展示的每項便是頁表地址(物理地址),根據虛擬地址,測試是否能通過頁錶轉換找到映射的物理存儲數據,所以第二步中沒輸出字符串虛擬地址(圖是昨天的),重新來一下(已經關閉了隨機基址),如下所示:
記一次面試(有關windows下分頁機制淺談)
                 圖片十:輸出字符串在虛擬內存地址
➇根據圖片四把上述的虛擬地址進行分割,如下所示:
記一次面試(有關windows下分頁機制淺談)
                 圖片十一:虛擬地址轉換
 ➈對應的二進制換算16進制 (1 <--> 19 <--> B30),其中1代表是頁目錄表中的第一項,查看頁目錄表之前需要對地址頁目錄的PTE瞭解,如下所示:

記一次面試(有關windows下分頁機制淺談)
                 圖片十二:頁表地址解析

 ➉如上圖所示,低12位是屬性,高位是地址,所以0x3ebf3200真實的頁地址爲0x3ebf3000, 然後頁表索引是19,因爲數組元素是保存的指針,需要乘以4字節,如下所示:

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