本文講述中斷門,以及中斷門實驗。
IDT表裏面就三種內容:任務門描述符、中斷門描述符、陷阱門描述符。
中斷門描述符
是不是還是和段描述符很像(哈哈哈)
P=1有效,S=0系統段描述符,TYPE位是關鍵,0x6表示16位中斷門,0xE表示32位中斷門。中斷門不可以傳參數。
int x 指令,x是索引,x*8 + IDT的基地址,就是具體的中斷門描述符
int x指令進入中斷後,如果沒有權限切換(不切換堆棧)會push三個寄存器值(eflags cs eip),如果有提權,會想堆棧push5個寄存器值(ss esp eflags cs eip),所以不能用retf返回,而是使用iret或者iretd返回
offset in segment:新的EIP入口地址值(中斷門主要改這個值)
segment selector:段選擇子(往哪個段跳,就寫對應的段選擇子,這個段選擇子可以是0環的)
通過上面offset in segment和segment selector兩個部分:INT x指令進入中斷門,裏面的CS和EIP就都有了,大功告成。
中斷門也可以用來提權。不提權時,INT N 會壓棧CS,EFLAG EIP;提權時,會依次壓棧 SS ESP EFLAG CS EIP。需要用堆棧保存EFLAG是因爲中斷門會將EFLAG的IF位置0.
LIDT和SIDT特權指令,只能在0環使用。保護模式第一保護的是內存,另外保護的就是特殊寄存器,特殊寄存器由特權指令在0環執行。
實驗步驟
(1)查IDT表,自己構造中斷門描述符,在中斷門描述符中填上offset in segment和segment selector
函數的偏移地址00401020
中斷門描述符:0040ee00`00081020
kd> r idtr
idtr=8003f400
kd> dq 8003f400 L30
8003f400 80538e00`0008f3bc 80538e00`0008f534
8003f410 00008500`0058113e 8053ee00`0008f904
8003f420 8053ee00`0008fa84 80538e00`0008fbe0
8003f430 80538e00`0008fd54 80548e00`000803bc
8003f440 00008500`00501198 80548e00`000807e0
8003f450 80548e00`00080900 80548e00`00080a40
8003f460 80548e00`00080c9c 80548e00`00080f80
8003f470 80548e00`00081694 80548e00`0008190c
8003f480 80548e00`00081a2c 80548e00`00081b64
8003f490 80548500`00a0190c 80548e00`00081ccc
8003f4a0 80548e00`0008190c 80548e00`0008190c
8003f4b0 80548e00`0008190c 80548e00`0008190c
8003f4c0 80548e00`0008190c 80548e00`0008190c
8003f4d0 80548e00`0008190c 80548e00`0008190c
8003f4e0 80548e00`0008190c 80548e00`0008190c
8003f4f0 80548e00`0008190c 806d8e00`00083fd0
8003f500 00000000`00080000 00000000`00080000
8003f510 00000000`00080000 00000000`00080000
8003f520 00000000`00080000 00000000`00080000
8003f530 00000000`00080000 00000000`00080000
8003f540 00000000`00080000 00000000`00080000
8003f550 8053ee00`0008ebfe 8053ee00`0008ed00
8003f560 8053ee00`0008eea0 8053ee00`0008f7e0
8003f570 8053ee00`0008e691 80548e00`0008190c
kd> eq 8003f500 0040ee00`00081020
kd> dq 8003f400 L30
8003f400 80538e00`0008f3bc 80538e00`0008f534
8003f410 00008500`0058113e 8053ee00`0008f904
8003f420 8053ee00`0008fa84 80538e00`0008fbe0
8003f430 80538e00`0008fd54 80548e00`000803bc
8003f440 00008500`00501198 80548e00`000807e0
8003f450 80548e00`00080900 80548e00`00080a40
8003f460 80548e00`00080c9c 80548e00`00080f80
8003f470 80548e00`00081694 80548e00`0008190c
8003f480 80548e00`00081a2c 80548e00`00081b64
8003f490 80548500`00a0190c 80548e00`00081ccc
8003f4a0 80548e00`0008190c 80548e00`0008190c
8003f4b0 80548e00`0008190c 80548e00`0008190c
8003f4c0 80548e00`0008190c 80548e00`0008190c
8003f4d0 80548e00`0008190c 80548e00`0008190c
8003f4e0 80548e00`0008190c 80548e00`0008190c
8003f4f0 80548e00`0008190c 806d8e00`00083fd0
8003f500 0040ee00`00081020 00000000`00080000
8003f510 00000000`00080000 00000000`00080000
8003f520 00000000`00080000 00000000`00080000
8003f530 00000000`00080000 00000000`00080000
8003f540 00000000`00080000 00000000`00080000
8003f550 8053ee00`0008ebfe 8053ee00`0008ed00
8003f560 8053ee00`0008eea0 8053ee00`0008f7e0
8003f570 8053ee00`0008e691 80548e00`0008190c
進入中斷門後,查看寄存器:
kd> r
eax=cccccccc ebx=7ffdb000 ecx=00000000 edx=00430dd0 esi=0012f7bc edi=0012ff80
eip=00401020 esp=ee410dcc ebp=0012ff80 iopl=0 nv up di pl nz ac pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000016
kd> dq ee410dcc L40 //查看堆棧
ee410dcc 0000001b`0040106a 0012ff30`00000216
ee410ddc 00000000`00000023 00000000`00000000
ee410dec 0000027f`00000000 00000000`7c930000
ee410dfc 00000000`00000000 00001f80`00000000
ee410e0c 27262524`23222120 00380188`00380178
ee410e1c 37363534`00000001 00380000`3b3a3938
ee410e2c 003801f0`003823a0 00380178`0012f8f0
ee410e3c 7c930940`0012f8f0 000000e9`00380608
ee410e4c 003823a8`00000080 00000000`00382e30
ee410e5c 0000000f`003801c0 7f7e7d7c`00380178
ee410e6c 20202020`003823a8 20202020`20202020
ee410e7c 20202020`00380178 003823a8`00383780
ee410e8c 00000011`20202020 00000000`20202020
ee410e9c 00383788`20202020 00000101`00382b70
ee410eac 00380168`003823a0 00000000`00000000
ee410ebc 00000088`003823a0 20202020`00383780
ee410ecc 00000000`00000000 00000808`00383780
ee410edc 00000000`00383788 00000808`00380178
ee410eec 00380000`000001e0 77bfc3c9`0012f6d4
ee410efc 7c92e920`0012f924 ffffffff`7c9301e0
ee410f0c 77bfc1db`7c9301db 77be1294`77c20224
ee410f1c 00010800`77be129c 0012f900`00000001
ee410f2c 0012fb08`00000800 77be4af8`77c05c94
ee410f3c 77c20224`ffffffff 77c09d7a`0012f938
ee410f4c 0012f9f0`77be129c 77be1278`77c09dcf
ee410f5c 00000094`77be1280 77bef062`00000a28
ee410f6c 00000005`00000094 00000a28`00000001
ee410f7c 76726553`00000002 6b636150`20656369
ee410f8c 0012f998`00003320 00000000`7c94437b
ee410f9c 7ffdc000`00000000 7ffdc000`00400000
ee410fac 0020001e`00000000 0012f9b0`7c9443a4
ee410fbc 00000001`00000014 00000000`00000000
(2)代碼
#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>
BYTE IDTItem0[8];
// 裸函數地址:00401020
void __declspec(naked) R0Function()
{
__asm
{
//int 3 // 調試用的
pushad
pushfd
mov eax,0x8003f400 //訪問高2G內存
mov ebx,[eax]
mov ecx,[eax+0x4]
mov dword ptr ds:[IDTItem0],ebx
mov dword ptr ds:[IDTItem0+0x4],ecx
popfd
popad
iretd // iret 會藍屏,因爲 iret的硬編碼是66CF,32位下應該使用iretd,硬編碼是CF
}
}
int main(int argc, char* argv[])
{
__asm
{
int 0x20
}
printf("%08x %08x\n", *(PDWORD)IDTItem0, *(PDWORD)((PBYTE)IDTItem0+0x4));
getchar();
return 0;
}
調用門和中斷門的區別
1.調用門通過CALL FAR指令執行,RETF返回。中斷門用INT指令執行,IRET或IRETD返回。
2.調用門查GDT表。中斷門查IDT和GDT表
3.CALL CS:EIP中CS是段選擇子,由三部分組成。INT x指令中的x只是索引,中斷門不檢查RPL,只檢查CPL。
4.調用門可以傳參數。中斷門不能傳參數。