rogxo@home:~$

中断门陷阱门提权

2a6f748e12edacf1417515c3e462c415.png

#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>

#ifndef _WIN64
typedef struct _GeneralRegisters
{
    DWORD eax;
    DWORD ecx;
    DWORD edx;
    DWORD ebx;
    DWORD esp;
    DWORD ebp;
    DWORD esi;
    DWORD edi;

}GeneralRegisters, * pGeneralRegisters;
#else
typedef struct _GeneralRegisters
{
    QWORD eax;
    QWORD eax;
    QWORD eax;
    QWORD eax;
    QWORD eax;
    QWORD eax;
    QWORD eax;
    QWORD eax;

}GeneralRegisters, * pGeneralRegisters;
#endif

typedef struct _SegmentRegisters
{
    WORD cs;
    WORD ds;
    WORD es;
    WORD fs;
    WORD gs;
    WORD ss;
    WORD ldtr;
    WORD tr;

}SegmentRegisters, * pSegmentRegisters;


GeneralRegisters gr_r0 = { 0 };
GeneralRegisters gr_r3 = { 0 };

SegmentRegisters sr_r0 = { 0 };
SegmentRegisters sr_r3 = { 0 };

BYTE GDT[6] = { 0 };


void GetGRs(GeneralRegisters* gr)
{
    _asm
    {
        mov ecx, [gr]
        mov dword ptr[ecx + 0x0], eax
        mov dword ptr[ecx + 0x4], ecx
        mov dword ptr[ecx + 0x8], edx
        mov dword ptr[ecx + 0xC], ebx
        mov dword ptr[ecx + 0x10], esp
        mov dword ptr[ecx + 0x14], ebp
        mov dword ptr[ecx + 0x18], esi
        mov dword ptr[ecx + 0x1C], edi
    }
}

void GetSRs(SegmentRegisters* sr)
{
    _asm
    {
        mov ecx,[sr]
        mov word ptr [ecx+0x0], cs
        mov word ptr [ecx+0x2], ds
        mov word ptr [ecx+0x4], es
        mov word ptr [ecx+0x6], fs
        mov word ptr [ecx+0x8], gs
        mov word ptr [ecx+0xA], ss
    }
}

//读取选择子为0008的段描述符
BYTE Buf[0x8] = { 0 };
void __declspec(naked) ReadGDT()
{
    _asm
    {
        //int 3
        pushad
        pushfd

        sgdt GDT
        mov eax, dword ptr[GDT + 0x2]
        mov ebx, dword ptr[eax + 0x8]
        mov dword ptr[Buf], ebx
        mov ebx, dword ptr[eax + 0xC]
        mov dword ptr[Buf+0x4],ebx

        popfd
        popad
        ret
    }
}

void PrintGRs(GeneralRegisters* gr)
{
    printf("EAX=%x\n", gr->eax);
    printf("ECX=%x\n", gr->ecx);
    printf("EDX=%x\n", gr->edx);
    printf("EBX=%x\n", gr->ebx);
    printf("ESP=%x\n", gr->esp);
    printf("EBP=%x\n", gr->ebp);
    printf("ESI=%x\n", gr->esi);
    printf("EDI=%x\n", gr->edi);
}

void PrintSRs(SegmentRegisters* sr)
{
    printf("CS=%x\n", sr->cs);
    printf("DS=%x\n", sr->ds);
    printf("ES=%x\n", sr->es);
    printf("FS=%x\n", sr->fs);
    printf("GS=%x\n", sr->gs);
    printf("SS=%x\n", sr->ss);
}

//中断门调用
void __declspec(naked) INTGate()
{
    _asm
    {
        //int 3	
        //中断门中调用int3,会改变fs寄存器的值,iret/iretd后fs不会恢复,弹异常
        //解决方法:中断调用前push fs保存fs的值,调用结束后再pop fs手动恢复
        //此处引用https://www.cnblogs.com/onetrainee/p/12436327.html看法
        /*
         这个错误的原因并不是Intel的问题,我们之后嵌套调用门,int20 --> int21 并没有发现这个问题;
     并且查阅intel手册,里面重点强调NT、IF、VM等Eflags位,并没有提到FS寄存器;
     因此这里可以推断是Windows的处理机制存在的问题,怀疑是先前模式搞得鬼,我们在三环,但是使用
         零环的权限,而系统以为我们在内核调用int3;
     这问题先放一下,之后如果有时间再来研究这个问题。
        */
        pushad
        pushfd
    }
        GetSRs(&sr_r0);
        ReadGDT();
    _asm
    {
        popfd
        popad
        iretd
    }

}

//陷阱门调用
void __declspec(naked) TrapGate()
{
    _asm
    {
        int 3
        pushad
        pushfd
    }
        GetSRs(&sr_r0);
        GetGRs(&gr_r0);
        ReadGDT();
    _asm
    {
        popfd
        popad
        iretd
    }
}

//中断门和陷阱门唯一的区别就是通过中断门时eflags的IF位被清零以屏蔽可屏蔽中断,而陷阱门不会

int main(int argc, char* argv[])
{
    GetGRs(&gr_r3);
    GetSRs(&sr_r3);

    puts("Ring3 General Registers:");
    PrintGRs(&gr_r3);
    puts("Ring3 Segment Registers:");
    PrintSRs(&sr_r3);

    _asm
    {
        push fs
        int 0x20
        pop fs
    }

    puts("Ring0 General Registers:");
    PrintGRs(&gr_r0);
    puts("Ring0 Segment Registers:");
    PrintSRs(&sr_r0);

    putchar('\n');
    printf("%x`%x\n", *(DWORD*)Buf, *(DWORD*)&Buf[4]);

    getchar();

    return 0;
}

3345082b4db7225f65f3b857830ceb95.png