(13)中断门
一、中斷門描述符
可以看到,中斷門的結構和調用門非常像,主要是TYPE域,0x6表示16位中斷門,0xE表示32位中斷門。和調用門不同,中斷門不能傳參。
中斷門存儲在IDT表中,IDT表除了存儲中斷門描述符,還有任務門和陷阱門描述符。
使用調用門的方法是 CALL FAR,而使用中斷門的方法是 INT N,其中,N表示中斷門描述符在IDT表中的下標。
和調用門一樣,中斷門也可以用來提權。不提權時,INT N 會壓棧CS,EFLAG EIP;提權時,會依次壓棧 SS ESP EFLAG CS EIP。需要用堆棧保存EFLAG是因為中斷門會將EFLAG的IF位置0.
二、自己實現中斷門
首先定義一個裸函數,在里面讀取一下IDT表的第一項,以證明自己的CPL是0.
// INTGate.cpp : Defines the entry point for the console application. //#include "stdafx.h" #include <Windows.h> #include <stdio.h>BYTE IDTItem0[8];// R0 函數,讀取了IDT表第一項 // 004113A0 void __declspec(naked) R0Function() {__asm{//int 3 // 調試用的pushadpushfdmov eax,0x8003f400mov ebx,[eax]mov ecx,[eax+0x4]mov dword ptr ds:[IDTItem0],ebxmov dword ptr ds:[IDTItem0+0x4],ecxpopfdpopadiretd // iret 會藍屏,因為 iret的硬編碼是66CF,32位下應該使用iretd,硬編碼是CF} }int _tmain(int argc, _TCHAR* argv[]) {__asm {INT 0x20}printf("%08x %08x\n", *(PDWORD)IDTItem0, *(PDWORD)((PBYTE)IDTItem0+0x4));getchar();return 0; }然后構造一個提權中斷門,DPL可以是0或3,都試試:
0041 13A00041EE00`000813A0 eq 8003f500 0041EE00`000813A000418E00`000813A0 eq 8003f500 00418E00`000813A0然后在IDT表里尋找一個P=0的無效項,把我們設計的第一個中斷門描述符填進去:
這里下標是0x20,所以中斷指令是 INT 0x20,執行結果如下:
這個是DPL=3的版本,然后我們再試試DPL=0:
發現被當成無效中斷了:
于是,得出結論,CPL=DPL時,才能成功觸發中斷。
三、在調用門中實現使用IRETD返回,在中斷門中實現用RETF返回.
在中斷門中用RETF返回,只需將[ESP+0x8]寫到EFLAG,然后讓ESP 和 SS向低地址移動4字節即可。
// INTGate.cpp : Defines the entry point for the console application. //#include "stdafx.h" #include <Windows.h> #include <stdio.h>BYTE IDTItem0[8];// R0 函數,讀取了IDT表第一項 // 004113A0 void __declspec(naked) R0Function() {__asm{//int 3 // 調試用的pushadpushfdmov eax,0x8003f400mov ebx,[eax]mov ecx,[eax+0x4]mov dword ptr ds:[IDTItem0],ebxmov dword ptr ds:[IDTItem0+0x4],ecx// 要求用 retf 返回add esp,0x2c // esp指向eflagspopfd // esp指向3環espmov eax,[esp] // 將原ESP和SS向低地址移動4字節mov [esp-0x4],eaxmov eax,[esp+0x4]mov [esp],eaxsub esp,0x30 // 還原esppopfdpopadretf} }int _tmain(int argc, _TCHAR* argv[]) {__asm {INT 0x20}printf("%08x %08x\n", *(PDWORD)IDTItem0, *(PDWORD)((PBYTE)IDTItem0+0x4));getchar();return 0; }在調用門中用IRETD返回,只需將ESP和SS向高地址移動4字節,將EFLAG寫到[ESP+0x8]即可。
// INTGate.cpp : Defines the entry point for the console application. //#include "stdafx.h" #include <windows.h> #include <stdio.h>DWORD dwHigh2GValue;// 該函數通過 CALL FAR 調用,使用調用門提權,擁有0環權限 // 00411480 void __declspec(naked) FunctionHas0CPL() {__asm{pushadpushfd// 讀取了GDT表第二項的低4字節mov eax,0x8003f008mov eax,[eax]mov dwHigh2GValue,eax// 要求用 iretd 返回 add esp,0x30 // esp指向ssmov eax,[esp] // 將原ESP和SS向高地址移動4字節mov [esp+0x4],eaxmov eax,[esp-0x4]mov [esp],eaxpushfdsub esp,0x2c // 還原esppopfdpopadiretd} }int main(int argc, char* argv[]) {char buff[6] = {0,0,0,0,0x48,0};__asm{call fword ptr [buff] // 長調用,使用調用門提權}printf("%08x\n",dwHigh2GValue);getchar();return 0; }總結
- 上一篇: (12)调用门阶段测试
- 下一篇: (14)陷阱门