保護模式篇之段和門小結
此系列是本人一個字一個字碼出來的,包括示例和實驗截圖。由于系統核心的複雜性,故可能有錯誤或者不全面的地方,如有錯誤,歡迎批評指正,本教程将會長期更新。 如有好的建議,歡迎回報。碼字不易,如果本篇文章有幫助你的,如有閑錢,可以打賞支援我的創作。如想轉載,請把我的轉載資訊附在文章後面,并聲明我的個人資訊和本人部落格位址即可,但必須事先通知我。
你如果是從中間插過來看的,請仔細閱讀 羽夏看Win系統核心——簡述 ,友善學習本教程。
看此教程之前,問幾個問題,基礎知識儲備好了嗎?上一節教程學會了嗎?上一節課的練習做了嗎?沒有的話就不要繼續了。
🔒 華麗的分割線 🔒
如果您看本系列進行學習保護模式的話,抱歉給您的長期等待帶來的不便。最近主要是忙于學業,作業比較多。其次就是回顧之前的總結有沒有疏漏,也花費了不少時間。總之,該寫的部落格,還是得寫的。
本次答案均為參考,可以與我的答案不一緻,但必須成功通過。第一題的答案可以比我的更詳細。
1️⃣ 自己構造任務段通過<code>CALL</code>實作任務切換,要求使用0環的段。
🔒 點選檢視答案 🔒
本人在<code>8003f090</code>作為任務段存儲位址,值為<code>0000E912`FD740068</code>,注意一定構造正确的TSS并填寫正确的TSS位址,否則會容易藍屏。
首先填寫的位址就是任務切換所需要的<code>EIP</code>,注意填對了,如下圖所示:

然後顯示出<code>TSS</code>的位址,這個至關重要,填好在<code>GDT表</code>中,如下圖所示:
其次填<code>CR3</code>,通過<code>!process 0 0</code>獲得并寫入,如下圖所示:
然後運作跑起來,任務切換成功,如下圖所示:
🔒 點選檢視代碼 🔒
到現在我們學習了什麼是段,什麼是門,什麼是段的機制,到現在您應該有一些比較清晰的了解和掌握。然而讀取記憶體不僅得過的了段這一關,還得過的了頁這一關。什麼是頁,什麼是頁的機制。将會到下一篇進行講解。
為什麼要寫這一篇小節呢?一是總結自己之前學過的東西,回頭一看其實也不太難,不過說實在的剛開始學起來挺頭秃的。二是提醒大家要學習完一個階段,每天回頭看看我寫的教程。因為這教程是我學習過程中寫的,可能有不太完善的地方,一旦有漏洞就會及時修改。保護模式僅僅靠我寫的東西是學不完的,還有很多細節的東西我還未涉及,但我學到的部分會盡快的補充。三是提醒大家要及時完成練習,因為後面還是會用到的。
學完段的内容,難道沒有個小節作業呢?這個是額外的練習,可以不做,但還是建議做一做,下面的題目将是對之前未講到的細節的補充。
1️⃣ 用代碼獲得<code>GDT</code>表的基位址和大小。
2️⃣ 構造一個3環的代碼段描述符,我想把它用請求權限為3的選擇子加載到<code>CS</code>當中。比如<code>0x1B</code>指向的段描述符,我用<code>0x18</code>請求CS的值會變成<code>0x1B</code>嗎?
3️⃣ 使用調用門我們都知道需要用<code>retf</code>将堆棧中的壓入的值重新彈到寄存器,進而傳回,從此有一個大膽的想法,我們自己構造壓入的值,使用0環的,用<code>retf</code>能提權嗎?
可以說想法很美好,現實很殘酷。先看看實作結果如下圖:
為什麼不能,我們看一下白皮書,可以看到如下句子:
A far return that requires a privilege-level change is only allowed when returning to a less privileged level (that is,the DPL of the return code segment is numerically greater than the CPL).
遠傳回系列指令隻能降級傳回是以通過這個方式提權别想了。
4️⃣ 一天通過中斷門提權,使用下面的代碼,發現運作後藍屏了,是為什麼呢?
這道題是專門給給搞不清楚<code>iret</code>和<code>iretd</code>的同志下的坑。
如下是《Intel白皮書》的原話,它在 PDF 中的第1059頁:
IRET and IRETD are mnemonics for the same opcode. The IRETD mnemonic (interrupt return double) is intended for use when returning from an interrupt when using the 32-bit operand size; however, most assemblers use the IRET mnemonic interchangeably for both operand sizes.
簡單是說<code>IRET</code>和<code>IRETD</code>是一樣的寫死<code>IRETD</code>是用來32位傳回用的。但是大多數彙程式設計式使用兩種操作數大小的 IRET 助記符可以互換,OD 就很好的落實到了這點:
但是不幸的是,它們是不一樣的指令,<code>Intel</code>隻說是<code>Opcode</code>是一樣的,沒說字首不一樣呀。在繼續之前我們先看白皮書的一句話:
The instruction prefix 66H can be used to select an operand size other than the default.
簡單點說,<code>0x66</code>這一個字首指令,不明白的可以看一下 羽夏筆記——寫死(32位) ,裡面比較詳細的介紹了寫死是基礎,也略微提及到了這一個字首。我們來看看正确的解釋是啥:
看到沒有,<code>iretd</code>指令比<code>iret</code>指令多一個<code>0x66</code>這個指令,這個指令正式反轉預設尋址方式的字首。在32位系統預設尋址32位,如果有這個指令,就用16位尋址。這會明白為什麼我會下這個坑吧?是以答案就是把<code>iret</code>改為<code>iretd</code>。
5️⃣ 驗證當3環提權到0環,不管怎麼破壞能夠不藍屏回去後,重新再次進入後也不會藍屏。
代碼我已詳細寫了注釋了,我用的調用門是<code>0040EC00`0090D480</code>,被填寫到<code>0x8003f098</code>,而調用門使用的段描述符的值為:<code>00CF9A00`0000FFFF</code>,被填寫到<code>0x8003f090</code>。
至于為什麼不藍屏,看看每次進0環的時候的<code>esp</code>,你就為什麼不藍屏,也感受到<code>TSS</code>的魅力了。
6️⃣ 将某一代碼片運作到1環。
🔒 點選檢視提示 🔒
7️⃣ 逆向<code>int3</code>/<code>int 8</code>中斷(注:隻把第一層看明白邏輯即可,就算看不懂也沒有太大的關系,剩下的部分都會在後面的教程逐漸講解深入)。
在看詳細答案之前,我們先搞懂3号中斷和8号中斷是什麼,看下面的圖:
3号中斷正好是我們已知的斷點,而8号中斷是雙重錯誤。說到雙重錯誤,那麼什麼是雙重錯誤呢?在程式執行過程中,可能會出現一個異常。當異常産生時,即錯誤産生時,CPU會走指定中斷進行異常處理。但在異常處理過程中,也可能會發生錯誤。如果再次發生錯誤,CPU将會走8号中斷,即所謂的雙重錯誤。對于Windows系統來說,基本就是以藍屏的形式出現。
既然我要分析代碼,必然要找到函數位址。根據中斷門的結構不難找到它的函數位址。我們先用<code>Windbg</code>來找到函數。先以<code>int 8</code>為例。
根據IDT表和索引找到中斷門<code>804e8e00`00080d02</code>後,得到位址<code>804e0d02</code>。然後輸入<code>uf 804e0d02</code>即可顯示。
雖然 Windbg 能夠很快的找到函數,但它不太友善。都知道大名鼎鼎的 IDA ,如何通過它找到我需要分析的函數呢?
首先我們先找到自己的核心檔案,找到<code>C:\WINDOWS\system32</code>這個路徑,找到的核心檔案如下圖所示:
為什麼是兩個核心程式呢?這是由于分頁的原因。WinXP有兩種分頁模式:10-10-12分頁和2-9-9-12分頁。10-10-12分頁使用的核心程式是<code>ntoskrnl.exe</code>,2-9-9-12分頁是<code>ntkrnlpa.exe</code>。我們把它們拖到實體機進行分析。
打開 IDA ,然後把<code>ntoskrnl.exe</code>拖進去,如下圖所示:
點選确定,然後IDA詢問檢測到調試資訊,是否從微軟伺服器下載下傳符号,點選否。因為WinXP的符号微軟早不搞了。如下圖所示:
然後我們自己加載符号,根據下圖所示操作,打開加載符号檔案:
按照圖示操作進行加載符号,注意找到自己的符号安裝位置再參考下圖:
不清楚自己目前的核心檔案是啥咋麼辦?可以用 PCHunter 進行檢查:
根據WinDbg給出的函數,根據其特征找到指定函數,具體分析過程就不再贅述了。
保護模式篇——分頁基礎
本作品采用 知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協定 進行許可
本文來自部落格園,作者:寂靜的羽夏 ,一個熱愛計算機技術的菜鳥
轉載請注明原文連結:https://www.cnblogs.com/wingsummer/p/15353642.html