中断门

本文讲述中断门,以及中断门实验。

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.调用门可以传参数。中断门不能传参数。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章