天天看點

保護模式篇——任務段與任務門

保護模式篇之任務段與任務門,詳細介紹段任務段與任務門的基礎知識。

  此系列是本人一個字一個字碼出來的,包括示例和實驗截圖。由于系統核心的複雜性,故可能有錯誤或者不全面的地方,如有錯誤,歡迎批評指正,本教程将會長期更新。 如有好的建議,歡迎回報。碼字不易,如果本篇文章有幫助你的,如有閑錢,可以打賞支援我的創作。如想轉載,請把我的轉載資訊附在文章後面,并聲明我的個人資訊和本人部落格位址即可,但必須事先通知我。

你如果是從中間插過來看的,請仔細閱讀 羽夏看Win系統核心——簡述 ,友善學習本教程。

  看此教程之前,問幾個問題,基礎知識儲備好了嗎?上一節教程學會了嗎?上一節課的練習做了嗎?沒有的話就不要繼續了。

🔒 華麗的分割線 🔒

本次答案均為參考,可以與我的答案不一緻,但必須成功通過。答案注釋中有一些思考題,将會在本文結束後給出答案。

1️⃣ 構造無參的調用門,實作提權後讀取高2G的位址并分析堆棧情況。

🔒 點選檢視答案 🔒

  本人在<code>8003f090</code>作為段描述符存儲位址,值為<code>00CF9A00`0000FFFF</code>,在<code>8003f098</code>作為調用門的存儲位址,

值為<code>0040EC00`00901030</code>,注意一定填好正确的函數位址,否則會容易藍屏。

  在本題目中的示例代碼,運作,設定的斷點将會斷在WinDbg之中,說明調用門成功。如下圖所示:

保護模式篇——任務段與任務門

  堆棧分析如下圖所示:

保護模式篇——任務段與任務門

🔒 點選檢視代碼 🔒

2️⃣ 構造有參的調用門,實作提權後正确依次取出參數并分析堆棧情況。

值為<code>0040EC03`0090D740</code>,注意一定填好正确的函數位址和平好堆棧,否則會導緻藍屏。

保護模式篇——任務段與任務門
保護模式篇——任務段與任務門

3️⃣ 構造調用門,提權後,實作“FQ”,即不按原函數位址傳回。

保護模式篇——任務段與任務門

  程式顯示結果如下圖所示:

保護模式篇——任務段與任務門

4️⃣ 構造中斷門,實作提權後讀取高2G的位址并分析堆棧情況。

  本人在<code>8003f090</code>作為段描述符存儲位址,值為<code>00CF9A00`0000FFFF</code>,在<code>8003f4a0</code>作為中斷門的存儲位址,

值為<code>0040EE00`00901020</code>,注意一定填好正确的函數位址,否則會容易藍屏。

保護模式篇——任務段與任務門
保護模式篇——任務段與任務門

5️⃣ 構造陷阱門,實作提權後讀取高2G的位址并分析堆棧情況。

  本人在<code>8003f090</code>作為段描述符存儲位址,值為<code>00CF9A00`0000FFFF</code>,在<code>8003f4a0</code>作為陷阱門的存儲位址,

值為<code>0040EF00`00901020</code>,注意一定填好正确的函數位址,否則會容易藍屏。

  陷阱門的分析和代碼和陷阱門完全一樣,故不再贅述。

Windows 并沒有完全利用任務段和使用任務門實作CPU所謂的任務切換,Linux 也是如此。但為了保護模式的完整性,故繼續講解。

  我們回顧一下之前所學内容,在調用門、中斷門與陷阱門中,一旦出現權限切換,那麼就會有堆棧的切換。而且,由于<code>CS</code>的<code>CPL</code>發生改變,也導緻了<code>SS</code>也必須要切換。切換時,會有新的<code>ESP</code>和<code>SS</code>從哪裡來的呢?那就是任務狀态段提供的。任務狀态段簡稱任務段,英文縮寫為<code>TSS</code>,<code>Task-state segment</code>。

  <code>TSS</code>是一塊記憶體,大小為<code>104</code>位元組,記憶體結構如下圖所示:

保護模式篇——任務段與任務門

  <code>Intel</code>的設計<code>TSS</code>目的,用官方的話說就是實作所謂的任務切換。<code>CPU</code>的任務在作業系統的方面就是線程。任務一切換,執行需要的環境就變了,即所有寄存器裡面的值,需要儲存供下一次切換到該任務的時候再換回去重新執行。

  說到底,<code>TSS</code>的意義就在于可以同時換掉一堆寄存器。本質上和所謂的任務切換沒啥根本聯系。而作業系統嫌棄<code>Intel</code>的設計過于麻煩,自己實作了所謂的任務切換,即線程切換。具體将會在後面的教程進行講解。

  <code>TSS</code>是一個記憶體塊,并不在<code>CPU</code>中,那麼它是怎樣找到正确的<code>TSS</code>呢?那就是之前提到的<code>TR</code>段寄存器。<code>CPU</code>通過<code>TR</code>寄存器索引<code>TSS</code>是示意圖如下圖所示:

保護模式篇——任務段與任務門

  <code>TSS段描述符</code>的結構和普通的段描述符沒啥差別,就不詳細介紹了,如下圖所示:

保護模式篇——任務段與任務門

指令:<code>LTR</code>

說明:用<code>LTR</code>指令去裝載,僅僅是改變<code>TR</code>寄存器的值(96位),并沒有真正改變<code>TSS</code>。<code>LTR</code>指令隻能在系統層使用,加載後<code>TSS</code>段描述符會狀态位會發生改變。

指令:<code>STR</code>

說明:如果用<code>STR</code>去讀的話,隻讀了<code>TR</code>的16位,即選擇子。

在0環可以通過LTR指令去修改TR寄存器。

在3環可以通過CALL FAR或者JMP FAR指令來修改。用JMP去通路一個任務段的時候,如果是TSS段描述符,先修改TR寄存器,在用TR.Base指向的TSS中的值修改目前的寄存器。

  用<code>CALL</code>和<code>JMP</code>實作任務切換,它們之間有什麼不同呢?答案就不用說了。如果用<code>CALL</code>,它會把<code>Previous Task Link</code>填寫數值,并<code>EFLAGS</code>寄存器的<code>NT</code>位改為<code>1</code>。如果這個位被改為<code>1</code>,<code>iret</code>指令會被當做任務傳回,從TSS裡的取出<code>Previous Task Link</code>傳回;反之則為正常的中斷傳回,從堆棧讀值傳回。而<code>JMP</code>指令不會做上述事情。

保護模式篇——任務段與任務門

  任務門的結構如下圖所示:

保護模式篇——任務段與任務門

  任務門的結構我就不想再贅述了,來看看它的執行過程:

通過<code>INT N</code>的指令進行觸發任務門

查<code>IDT</code>表,找到任務門描述符

通過任務門描述符,查<code>GDT</code>表,找到<code>TSS</code>段描述符

使用<code>TSS</code>段中的值修改<code>TR</code>寄存器

<code>IRETD</code>傳回

1️⃣ pushad 和 pushfd 到底是必須的嗎?作用是什麼?

2️⃣ 在有參調用門調用取參的時候,為什麼用下面的代碼?

本節的答案将會在下一節進行講解,務必把本節練習做完後看下一個講解内容。不要偷懶,實驗是學習本教程的捷徑。

  俗話說得好,光說不練假把式,如下是本節相關的練習。如果練習沒做好,就不要看下一節教程了,越到後面,不做練習的話容易夾生了,開始還明白,後來就真的一點都不明白了。本節練習很少,請保質保量的完成。

1️⃣ 自己構造任務段通過<code>CALL</code>實作任務切換,要求使用0環的段,下面是一個代碼模闆,代碼裡面有坑,并且坑很深,看看自己能不能自行解決。

  保護模式篇——段和門小結

保護模式篇——任務段與任務門
保護模式篇——任務段與任務門

本作品采用 知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協定 進行許可

本文來自部落格園,作者:寂靜的羽夏 ,一個熱愛計算機技術的菜鳥

轉載請注明原文連結:https://www.cnblogs.com/wingsummer/p/15330063.html

保護模式篇——任務段與任務門