內核知識第九講,32位下的分頁管理,36位下的分頁管理.以及64位下的分頁管理
一丶熟悉WinDbg的常見命令.
dd 虛擬地址 顯示內存.
!dd 加上!, ! dd 物理地址 專門用於顯示物理地址的.
!PTE 虛擬地址: 微軟給你計算出PDE,和PTE的虛擬地址的位置.(自動查表並且進行操作)
例如隨便求一個虛擬地址:
DD命令的使用:
當然, db則是一個字節一個字節顯示, dQ則是八個字節顯示.
!dd, 物理內存顯示:
!PTE 查詢頁目錄表和頁表.
微軟給的是虛擬地址,我們只需要再次進行DD 這個虛擬地址即可.
二丶尋址結構圖
昨天我們講解的是32為下4M+4K的做表方式. 一個頁目錄表.一個頁表 (PDE,PTE),虛擬地址當作下表進行尋址動作.
然后還有一個尋址結構圖
1. 首先第一步,虛擬地址是段加偏移的方式 例如: CS:00401000
2.而后,段CS,當作選擇子去GDT表中查表.找到線性地址. 因為GDT微軟不使用.所以GDT表中的段首地址是0,所以 0 + 我們的偏移,找到線性地址. 圖中(linAddr)
3.而后線性地址,拆分成索引.去查詢頁目錄表. 而后繼續查詢頁表.而后從頁表中取出物理地址,加上虛擬地址的偏移.則是一個完整的物理地址.
PS: 因為GDT沒有使用,所以如果不開啟分頁保護.這個線性地址就是物理地址.但是現在開了,所以要查詢物理地址,看下圖
0-15是段選擇子,0-31是虛擬地址. 段選擇子去GDT查表.加上我們的虛擬地址就是物理地址. 而是否開啟分頁保護,就是修改CR0的標志位.上一篇已經講過了.
這里查表,拆分成了索引.但是昨天我們只學習了4M+4K的查表方法.虛擬地址的前20位做索引. 查詢.
但是32位下還有別的做表方式.
三丶32位下的PDE,PTE表,以及通用查表方法(通用: 指的是大同小異)
看一下32位下的做表的圖:
32位系統下,PDE有1024項,每一項是4個字節,其中存儲了頁表的位置.
這個就是我們昨天就愛了各國的.
1.首先從CR3中取出頁目錄表(PDE)
2.虛擬地址作為下表查詢PDE.
3.根據查詢的PDE表項.找出PTE的位置.
4.根據索引.查詢PTE的位置.
5.根據PTE中的內容.加上我們的虛擬地址的后12位,就得出了這個線性地址在物理地址的位置.
實戰演練:
查詢GDT虛擬地址的物理地址.
1.獲取GDT的虛擬地址, 獲取CR3的值.
VA = 8003F00
CR3 = 39000
2.查分虛擬地址.當作下表.查詢頁目錄表的位置.
8003f000 保留低12位 = 8003f
查分為索引.
8003f = 10000000000000111111
對2進制分割. 分為前10位.后10位.從右往左分割. 前10位索引當作 PDE的下表. 后10位的索引當作PTE的下表.
1000000000 0000111111
PDE = 1000000000 ,轉為16進制 = 0x200
PTE = 0000111111 ,轉為16進制 = 0x3f
由此得出下表.
3.根據下表進行查表.
CR3是PDE的首地址. 所以我們直接用WinDbg進行查表即可.
公式:
物理地址 * 索引 *4, 為什么*4,因為PDE的一個表項是4個字節
由此得出頁表的位置(PTE)
4.查詢頁表(PTE)
我們從PDE表項中,取出前20位,然后加上12位,繼續進行查表.
為什么這樣做.上一篇已經介紹了表格式了.
5.根據PTE的內容.找出物理地址的位置.
根據上圖,我們已經找到物理地址了.
取出前20位,加上虛擬地址的后12位偏移.則是物理地址了.
找出了所在的物理地址了.
此時我們dd 虛擬地址.查看是否兩塊內存是一樣的.
至此.我們的查表已經完成.
但是.我們這樣查詢是錯誤的.為什么?
首先查詢方法是正確的.類似於上面.我們已經正確的查詢到了物理地址. 但為什么又說是錯誤的.
原因:
操作系統在做分頁管理的時候.不一定是4M+4k的這種表來做的. 有可能有更大的表.
所以我們要看標志位進行查表
四丶標志位介紹.
上圖介紹了標志位為什么.表項做多大的.
1. 如果PSE和PS位都為1.那么這個表就做成4MB的.
2.如果PS位為0.PSE位無效那么這個表就做成4kb的.
3.如果PAE為1,PS位為1,則表項做成2MB的.
我們要看標志位進行查表.
PAE位 (物理地址擴展): 存放在CR4寄存器的第五位.
PSE位 (頁尺寸擴展): 存放在CR4寄存器的第4位.
PS位: 存放在PDE(頁目錄表的第7位)
上面所說的.都是從左往右的位.
比如:
CR4寄存器的值 = 0x34500
拆分:
0011 0100 0110 0000 0000 第4位.第五位都是0.
索引我們要根據位來看看到底是什么表.
五丶32位表項.
從上面我們得知了第一種表現.是4KB的表項做法.每一個都是1024項的.
4kb表項
也就是我們上圖做的.查表的是否根據上圖去查表的.
4MB的頁
這個就很簡單了.發現了沒有.上面少了一個頁表. 我們從PDE中查表的時候.查出來直接就是物理地址了.
而且虛擬地址的偏移是22位了.所以最后我們加的是前10位.
而且下圖也有說.
還把各種標志位的作用都說了.
查表方法同上面一樣. 只不過最后加偏移的是否是 從PDE表中的所在物理地址的位置取出10位.然后加上我們的偏移即可.
例如我們從上面隨便找個PDE的表
假設 PDE中的0003b163是物理地址.我們只需要取出前10位.然后加上我們的偏移即可.
0000 0000 00 + offset = 物理地址.
六丶開啟PAE,36位表項.
在我們可以映射4G內存的是否. 內存發展速度大於CPU.此時已經8G內存了.如果訪問
此時CPU廠家.就加了4根地址總線.以支持8G的訪問.
而因為為了支持.所以表項變成了512個項了. 每一項8個字節了.
36位下4KB的分頁
根據上圖,我們可以看出.加了一個新表.
我們的虛擬地址索引的高2位要做為這個 新表的索引去查詢.
最后我們的12位偏移,要加上PTE中物理地址的24位才是我們的物理內存的位置.
而這種做表方法.只能說也是映射4G內存.只不過可以映射多個4G內存了.
查表方法和上面一樣.
首先字節改變了. 每一項8個字節,而后最后我們是12位加上24位.得出物理地址.
36位下2MB的分頁
也是同上.只不過少了一個PTE.查表動作少了一次而已.
.只不過計算的是否.要根據36位地址來計算.
看下圖.
2MB的
第一張圖,告訴了我們.我們進行查表的時候. 4KB的怎么加.
例如:
我們以前查表是 !dd 3f000000 ,正好32位.而看上圖.4KB的告訴了我們.
32位 - 35位當作基址查詢.(4位) 要加上. 比如 !dd 00003f000000 正好滿足36的地址進行查尋.
2MB的圖是一樣的.
七丶64位系統下的表項
64位CPU下的的表項.同32為系統的表項是一樣的. 只不過變的更大了.
4kb的表項
和32位下一樣.加了幾張表.各種位都變大了.
2MB的分頁
64位擴展的2MB分頁
64位下映射1GB的圖
CR3. 當我們3環調用0環回調的是否.CR3是ring3的.
八丶為什么學習這些表.以及學這些表的作用
為什么學習. 因為到了0環.就是對抗了. 就比誰對操作系統了解.
比如我們熟悉上面的這些表的設計. 而且根據GDT,找出線性地址.根據線性地址找出對應的物理地址.
那么我們完全可以進行手動操作物理內存. 實現ReadProcessMemory和WriteProcessMemeory.
當然不會怎么簡單.但是我們能操作內存了. 是不是就不用調用API了.我們自己實現了 內存讀寫功能.
舉例子:
假設游戲有保護.保護了API. 不讓你讀寫內存. 給你HOOK了.各種檢測. 但是我們不調用. 我們自己寫一個.它怎么檢測.