章节介绍
- 参考系统段描述符介绍,,段权限详解.
- 陷阱门执行流程同中断门相同,差别点在于位于门中对标记位的影响(EFLAG.IF).
- IDT(Interrupt Descriptor Table)中断描述符表,存储中断门,陷阱门,任务门描述符.每个描述符大小为8字节.
0.陷阱门描述符
陷阱门在IDT表(IDT介绍)中
高4字节 31-16(BIT) EIP高2字节
低4字节 15-00(BIT) EIP低2字节
高4字节 12-15(BIT) P == 1(有效段描述符) DPL == 00/11(段描述符权限 0/3 Windows未利用1 2环) S == 0(系统段描述符) 1110/1000(E/8)
高4字节 11-08(BIT) TYPE == 1111(32BIT INTERRUPT GATE)
低4字节 31-16(BIT) 加载代码段选择子(同级权限或提权)
陷阱门 XXXXEF00 - 0008XXXX
1.陷阱门执行
1.1 陷阱门执行流程
1.陷阱门利用INT X指令调用,此中X是查IDT表的索引号(不包含RPL,只是单纯的索引).
2.陷阱门描述符里面的Segment Selector作为段选择子再在GDT表里面查询,并且载入CS.
3.进入offset的地点执行时,堆栈里面的内容比调用门要多一项,压入的顺序为SS ESP EFLAGS CS EIP.
1.2 陷阱门堆栈
1.如果发生权限切换(陷阱门描述符利用的选择子指向的代码段DPL小于当前的CPL)那么就会发生堆栈的切换
- 从当前任务的TSS中获取SS和ESP,把老的SS和ESP值压入到新栈中去.
- 生存EFLAGS,CS,EIP的值到新栈中.
- 如果异常产生了一个错误代码,把这个错误代码也压入到堆栈里面(在压入EIP之后)(_KTRAP_FRAME->ErrCode).
2.如果没有权限切换(陷阱门描述符利用的选择子指向的代码段DPL与当前的CPL相同)
- 生存当前的EFLAGS,CS,EIP值到当前的堆栈中.
- 如果异常产生了一个错误代码,把这个错误代码也压入到堆栈里面(在压入EIP之后)(_KTRAP_FRAME->ErrCode).
1.3 陷阱门返回
陷阱返回IRET/IRETD指令返回
- 调用门通过CALL FAR 指令执行,但陷阱门通过INT INDEX指令.
- 调用门查询GDT表,但陷阱门查询IDT表.
- CALL CS:EIP中的CS是段选择子,由INDEX TI RPL 三部分组成,但INT X 中的X只是索引,陷阱门不检查RPL只检查CPL.
- 调用门可以有参数,陷阱门没有参数.
2.陷阱门示例
2.1 陷阱门
#include #include //寄存器结构typedef struct _Register { DWORD EAX; DWORD ECX; DWORD EBX; DWORD EDX; DWORD ESP; DWORD EBP; DWORD ESI; DWORD EDI; DWORD EFLAG; WORD CS; WORD SS;}mREGISTER,*PREGISTER;//堆栈结构typedef struct _Stack{ DWORD ESP0; DWORD ESP4; DWORD ESP8; DWORD ESPC; DWORD ESP10;}STACK,*PSTACK;mREGISTER R3Reg = {0};mREGISTER R0Reg = {0};STACK R0Stack = {0};DWORD dwEFLAG = 0;VOID OutPutRegisterInfo(PREGISTER pRegister, PSTACK pStack){ printf("\n"); printf("EAX [0x%08x] \n",pRegister->EAX); printf("ECX [0x%08x] \n",pRegister->ECX); printf("EBX [0x%08x] \n",pRegister->EBX); printf("EDX [0x%08x] \n",pRegister->EDX); printf("ESP [0x%08x] \n",pRegister->ESP); printf("EBP [0x%08x] \n",pRegister->EBP); printf("ESI [0x%08x] \n",pRegister->ESI); printf("EDI [0x%08x] \n",pRegister->EDI); printf("EFL [0x%08x] \n",pRegister->EFLAG); printf("CS [0x%04x] \n",pRegister->CS); printf("SS [0x%04x] \n",pRegister->SS); printf("\n"); if (pStack) { printf("ESP0 [0x%08x] \n",pStack->ESP0); printf("ESP4 [0x%08x] \n",pStack->ESP4); printf("ESP8 [0x%08x] \n",pStack->ESP8); printf("ESPC [0x%08x] \n",pStack->ESPC); printf("ESP10 [0x%08x] \n",pStack->ESP10); }}_declspec(naked)VOID CallGate1(){ __asm { //获取寄存器数据 mov [R0Reg.EAX], EAX mov [R0Reg.ECX], ECX mov [R0Reg.EBX], EBX mov [R0Reg.EDX], EDX mov [R0Reg.ESP], ESP mov [R0Reg.EBP], EBP mov [R0Reg.ESI], ESI mov [R0Reg.EDI], EDI pushfd pop [R0Reg.EFLAG] mov WORD ptr [R0Reg.CS], CS mov WORD ptr [R0Reg.SS], SS //获取堆栈数据 mov eax, [esp + 0x0] mov [R0Stack.ESP0], eax mov eax, [esp + 0x4] mov [R0Stack.ESP4], eax mov eax, [esp + 0x8] mov [R0Stack.ESP8], eax mov eax, [esp + 0xC] mov [R0Stack.ESPC], eax mov eax, [esp + 0x10] mov [R0Stack.ESP10], eax //TRAP GATE 默认堆栈 EIP CS EFL ESP SS iretd }}int main(){ //构建陷阱门描述符 //XXXXEF00`0008XXXX //P == 1 //DPL == 11 //S == 0 //TYPE == 1111 printf("%04xEF00`0008%04x \n",HIWORD(CallGate1),LOWORD(CallGate1)); system("Pause"); __asm { mov [R3Reg.EAX], EAX mov [R3Reg.ECX], ECX mov [R3Reg.EBX], EBX mov [R3Reg.EDX], EDX mov [R3Reg.ESP], ESP mov [R3Reg.EBP], EBP mov [R3Reg.ESI], ESI mov [R3Reg.EDI], EDI pushfd pop [R3Reg.EFLAG] mov WORD ptr [R3Reg.CS], CS mov WORD ptr [R3Reg.SS], SS } OutPutRegisterInfo(&R3Reg,NULL); __asm { int 0x20 } OutPutRegisterInfo(&R0Reg,&R0Stack); system("Pause"); return 0;}
陷阱门执行权限切换时堆栈结构为:
[ESP] = retaddr
[ESP + 4] = oldcs
[ESP + 8] = oldeflag
[ESP + 0xC] = oldesp
[ESP + 0x10] = oldss
进入中断门后IF标记位会被置0 陷阱门不会
来源:http://www.12558.net
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |