中断门和调用门的不同点在于:调用门是从gdt表->gdt表,而中断门是从idt表->gdt表
idt表中的每一个中断门描述符的格式如下图:
这里使用的int [index] 跳转,其中index就是要在idt表中查询描述符的下标
其中的TYPE位置 (上边的第8~11位) 为e(h) = 1110(b)
决定了这个描述符的的类型是 中断门
首尾组合成的段中偏移值就是我们要跳转到的地方
使用中断门且不提权会先后压入 (eflags、cs、返回地址),提权的话会先后压入(ss、esp、eflags、cs、返回地址)因为提权后的堆栈是R0的,所以要保存下R3的堆栈esp
以及其权限ss
中断门使用iretd返回,这里注意iret是16位的,iretd才是32位的,特性和retf差不多,根据具体情况(提权or
非提权)出栈
实验代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
|
#include<stdio.h> #include<stdlib.h> #include<windows.h> int nt_value = 0; __declspec(naked) void test() { __asm { mov ebx,0x8003f00c; mov eax,[ebx]; mov nt_value,eax; iretd; } }
int main() { printf("%X\n",test); system("pause"); __asm { int 32; } printf("%X\n",nt_value); system("pause"); return 0; }
|
这是实验中提权后进入R0时候的堆栈布局
从上往下分别依次是 (返回地址、cs、eflags、esp、ss)
这里的eflag相对于r3的时候变化了 (r3.eflag = 0x202 , r0.eflag = 0x2) 因为调用中断门的时候会把eflag中的IF位置零,作用是屏蔽掉可屏蔽中断,即一个中断执行的时候其它中断无法执行
但是陷阱门不会把eflag中的IF位置零,这就是陷阱门和中断门的区别之一;另一个区别就是TYPE位为f(h)=1111(b)
此外两种门应该没有其他区别了
两种门的区别实验代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
|
#include<stdio.h> #include<stdlib.h> #include<windows.h> int nt_eflags = 0; int r3_eflags = 0; __declspec(naked) void test() { __asm { pushfd; pop eax; mov nt_eflags,eax; iretd; } }
int main() { printf("%X\n",test); system("pause"); __asm { pushfd; pop eax; mov r3_eflags,eax; int 32; } printf("\n\n中断门: \n"); printf("r3_eflags : %X\nr0_eflags: %X\n",r3_eflags,nt_eflags); system("pause"); return 0; }
|