中断门

中断门与调用门类似,可以进行跨段和提权

  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();
}

  

原文地址:https://www.cnblogs.com/Hookcc/p/12704089.html