中断门与调用门类似,可以进行跨段和提权
1、INT INDEX; 中断门指令,INDEX作为查询IDT表时的索引
2、type域位置如果(已知为中断门)其最高位为1表示这是32位的中断门描述符(0xE),为0表示16位的中断门描述符(0x6),32保护模式下不存在为0情况
3、提权跨段和跨段的堆栈相比调用门多了一个EFLAG寄存器
只跨段堆栈:返回地址,EFLAGE,CS c3 b4 40 00 (ret address) 16 02 00 00 (eflage) 1b 00 00 00(cs)
提权堆栈:返回地址,CS,EFLAG,ESP,SS c3 b4 40 00 (ret address) 1b 00 00 00(cs) 16 02 00 00(eflage) 30 ff 12 00(esp) 23 00 00 00(ss)
4、通过中断门提权或跨段不能再通过RETF返回(因中断门与调用门堆栈结构不同),需使用IRET/IRETD
5、中断门因为不是通过段选择子去IDT表查询,所以没有RPL.权限检测时只检测CPL <= DPL
6、中断门高4字节的0:3位是弃用,也就表明中断门是无法使用参数
执行流程:
1、构造中断门,写入到IDT表
0040EE00`00081005 //提权的中断门
2、执行INT 4中断指令,根据4作为索引前往IDT表查询中断门段描述符(4*8+IDT表基址即查询的段描述符地址)
3、判断从IDT表内查出的段描述符p位,是否为1(可用),判断s位是否为0(系统段描述符),权限检测:判断CPL是否<=DPL
4、根据SegmentSelector作为段选择子前往GDT表查询代码段描述符
5、判断从GDT表内查出的代码段描述符p位,是否为1(可用),判断s位是否为1(数据代码段),type域最高位是否为1(代码段)权限检测:判断cpl<=dpl(跨段)还是cpl>=dpl(提权)
5、修改CS,SS,ESP,EFLAGE,EIP
6、PUSH SS,PUSH ESP,PUSH ELFAGE,PUSH CS,PUSH 返回地址
7、使用IRETD返回,IRETD依次出栈到相应寄存器
#include <windows.h> DWORD CSS1 = 0; DWORD CSS2 = 0; void __declspec(naked) cc() { __asm { mov word ptr ds:[CSS1],cs IRETD } } void __declspec(naked) FUN() { __asm { mov word ptr ds:[CSS2],cs INT 32 IRETD } } int main(int argc, char* argv[]) { printf("Fun Address:%X ",FUN); printf("Fun Address:%X ",cc); getchar(); __asm { INT 4 } printf("cs1:%X ",CSS1); printf("cs2:%X ",CSS2); getchar(); }
在调用门中实现使用IRETD返回 在中断门中实现用RETF返回. #include <windows.h> void __declspec(naked) tym() { //调用门使用IRETD返回 __asm { IRETD } } //中断使用RETF返回 void __declspec(naked) zdm() { __asm { sub esp,0x4 mov eax,dword ptr ds:[esp+0xC] //取ELFAGE mov dword ptr ds:[esp],eax popfd //修改ELFAGE寄存器 //重组堆栈,按照调用门堆栈的格式,这样就可以使用RETF返回 mov eax,dword ptr ds:[esp+0xC] //esp mov edx,dword ptr ds:[esp+0x10] //ss mov dword ptr ds:[esp+0x8],eax mov dword ptr ds:[esp+0xc],edx RETF } } int main(int argc, char* argv[]) { //在调用门中实现使用IRETD返回 在中断门中实现用RETF返回. printf("tym:%X ",tym); printf("zdm:%X ",zdm); getchar(); BYTE CodeBuff[6] = {0}; *(WORD*)&CodeBuff[4] = 0X93; __asm { pushfd //将标志位寄存器压入堆栈,作为调用门参数,而调用门参数刚刚好就从第3个位置分配,与中断门的EFLAGE寄存器位置相同 call fword ptr ds:[CodeBuff] add esp,0x4 } printf("调用门返回成功 "); getchar(); __asm { INT 32 } printf("中断门返回成功 "); getchar(); }