Windows保护模式学习笔记(五)—— 任务段任务门
Windows保護模式學習筆記(五)—— 任務段&任務門
- 要點回顧
- 任務段
- TSS (Task-state segment )
- TR段寄存器
- TR段寄存器的讀寫
- TSS段描述符
- 實驗:加載自定義TSS
- 第一步:獲取必要參數
- 第二步:構造TSS段描述符
- 第三步:將TSS段描述符寫入GDT表
- 第四步:解除中斷,繼續執行代碼
- 任務門
- 任務門執行過程
- 實驗:通過任務門切換TSS
- 第一步:構造任務門描述符
- 第二步:將任務門描述符寫入IDT表
- 第三步:構造TSS段描述符
- 第四步:運行代碼
要點回顧
答案:TSS (Task-state segment ):任務狀態段
任務段
TSS (Task-state segment )
描述:
TSS是一塊內存
大小:104字節
TSS存儲了一堆寄存器的值
TSS結構圖:
TSS的作用:
TSS的本質:
CPU通過TR段寄存器尋找TSS
TR段寄存器
描述:
TR寄存器的值是當操作系統啟動時,從TSS段描述符中加載出來的,TSS段描述符在GDT表中
TR.Base = TSS起始地址
TR.Limit = TSS大小
TR段寄存器的讀寫
一、將TSS段描述符加載到TR寄存器
指令:LTR
說明:
二、讀TR寄存器
指令:STR
說明:如果用STR去讀的話,只讀了TR的16位,也就是段選擇子
TSS段描述符
描述:
TSS段描述符是系統段描述符中的一種
結構圖:
Type = 二進制1001:說明該TSS段描述符未被加載到TR段寄存器中
Type = 二進制1011:說明該TSS段描述符已被加載到TR段寄存器中
TSS、TSS段描述符、TR段寄存器關系示意圖:
實驗:加載自定義TSS
第一步:獲取必要參數
在VC6中運行如下代碼并在main函數頭部設置中斷:
#include <windows.h>DWORD dwOK; DWORD dwESP; DWORD dwCS;void __declspec(naked) func() {dwOK = 1;__asm{int 3mov eax,espmov dwESP,eaxmov ax,csmov word ptr [dwCS],ax//回去的代碼沒寫。。。} }int main(int argc, char* argv[]) {char bu[0x10]; //12ff70int iCr3;printf("input CR3:\n");scanf("%x", &iCr3);DWORD iTss[0x68] = {0x00000000, //link0x00000000, //esp0 //(DWORD)bu0x00000000, //ss00x00000000, //esp10x00000000, //ss10x00000000, //esp20x00000000, //ss2(DWORD)iCr3, //cr30x0040DE50, //eip0x00000000, //eflags0x00000000, //eax0x00000000, //ecx0x00000000, //edx0x00000000, //ebx(DWORD)bu, //esp0x00000000, //ebp0x00000000, //esi0x00000000, //edi0x00000023, //es0x00000008, //cs 0x0000001B0x00000010, //ss 0x000000230x00000023, //ds0x00000030, //fs0x00000000, //gs0x00000000, //dit0x20ac0000};char buff[6];*(DWORD*)&buff[0] = 0x12345678;*(WORD*)&buff[4] = 0xC0;__asm{call fword ptr[buff]}printf("ok=%d \t ESP=%x \t CS=%x \n", dwOK, dwESP, dwCS);return 0; }進入反匯編窗口查看 func 函數起始地址,我這里是0x401020
將地址填入iTss數組注釋為eip的地方,表示TSS切換后EIP的值
再通過 memory 窗口查看iTss數組所在地址,記下來備用
注意:代碼中如有地方發生修改,需要先停止程序,重新編譯
第二步:構造TSS段描述符
Offset in Segment 31:16 = 0x0000 // 暫定G = 0AVL = 0Limit = 二進制:0000P = 1DPL = 二進制:11Type = 二進制:1001Segment Limit = 0068H // Intel規定TSS段描述符G=0時Limit必須大于或等于67H Offset in Segment 15:00 = 0x0000 // 暫定由上述參數構造出的門描述符為:0000E900`00000068
在第一步中,我們已經知道iTss數組所在地址為0x12FDCC
因此,TSS段描述符最終確定為:0000E912`FDCC0068
第三步:將TSS段描述符寫入GDT表
我寫入的地址是8003f0c0,若寫入其他地址,則需要修改buff數組的后兩個字節
這時候先不要急著繼續運行代碼,先在WinDbg中輸入命令:!process 0 0
獲得當前進程的Cr3(我這里進程名叫TestDoor.exe,之前是用來做調用門的實驗,TSS沒有新建項目)
DirBase的值就是Cr3
第四步:解除中斷,繼續執行代碼
輸入上一步得到的Cr3,回車
WinDbg成功獲得了中斷信號
這時候看一下反匯編代碼
可以確定正在執行func函數的代碼
再看一下寄存器
eip、cs、ss都符合我們想要的結果
至此,TSS切換成功!
思考:TSS切換完成后,如何回到切換前的下一行繼續執行?
任務門
描述:
任務門存在于IDT表
任務門中包含TSS段選擇子
可以通過訪問任務門達到切換TSS的目的
結構圖:
任務門執行過程
實驗:通過任務門切換TSS
第一步:構造任務門描述符
任務門描述符結構圖灰色部分默認填充為0
P = 1DPL = 二進制:11TSS Segment Selector = 0x00C3 // TSS段描述符選擇子由上述參數及默認參數構造出的門描述符為:0000e500`00C30000
第二步:將任務門描述符寫入IDT表
第三步:構造TSS段描述符
TSS段描述符構造具體過程參照任務段實驗部分,這里不再詳解,只給出測試代碼
代碼如下:
#include <windows.h>DWORD dwOK; DWORD dwESP; DWORD dwCS;void __declspec(naked) func() {dwOK = 1;__asm{mov eax,espmov dwESP,eaxmov ax,csmov word ptr [dwCS],axiretd} }int main(int argc, char* argv[]) {char bu[0x10]; //12ff70int iCr3;printf("input CR3:\n");scanf("%x", &iCr3);DWORD iTss[0x68] = {0x00000000, //link0x00000000, //esp0 //(DWORD)bu0x00000000, //ss00x00000000, //esp10x00000000, //ss10x00000000, //esp20x00000000, //ss2(DWORD)iCr3, //cr30x00401020, //eip0x00000000, //eflags0x00000000, //eax0x00000000, //ecx0x00000000, //edx0x00000000, //ebx(DWORD)bu, //esp0x00000000, //ebp0x00000000, //esi0x00000000, //edi0x00000023, //es0x00000008, //cs 0x0000001B0x00000010, //ss 0x000000230x00000023, //ds0x00000030, //fs0x00000000, //gs0x00000000, //dit0x20ac0000};__asm{int 0x20}printf("ok=%d \t ESP=%x \t CS=%x \n", dwOK, dwESP, dwCS);getchar();return 0; }第四步:運行代碼
需要輸入Cr3,Cr3獲取流程參照任務段實驗部分,這里不再詳解
運行結果:
TSS切換成功!
至此,我們已經學會通過CALL/JMP以及任務門來切換TSS
思考:既然已經可以直接訪問任務段了,為什么還要有任務門?
總結
以上是生活随笔為你收集整理的Windows保护模式学习笔记(五)—— 任务段任务门的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows保护模式学习笔记(四)——
- 下一篇: Windows保护模式学习笔记(六)——