使用调用门

要注意gdt的第一项是0,不能使用。
然后看gdt中那一项的p位没有置位,再添加一个调用门描述符。描述符的offset指向需要被ring3程序调用的ring0函数地址。DPL为3。当然selector权限也需要是3。描述符中的selector应是0x8,说明是ring0下code段。驱动通过DeviceIoControl传递给ring3程序调用门的selector,当然也可以通过文件注册表之类的。不过这里我有点不解,使用了调用门之后,system("pause");就不起作用了。。有知道的请说一声。由于调用门是段间转移,所以用ret返回是错误的,会蓝屏。得用retf。至于怎么使编译器产生retf,我也不大清楚,所以就直接__declspec(naked)内嵌汇编了。有知道的拜托也说声,谢谢啦。还有,真的,写代码真得小心,我因为&和|的笔误调试了好久。
 
ring0:
#include <ntddk.h>

/*#pragma pack(1)
typedef struct _CALLGATE
{
    USHORT OffsetLow;
    USHORT selector;
    UCHAR ParamCount :4;
    UCHAR SomeBits :4;
    UCHAR tyep :4;
    UCHAR AppSystem :1;
    UCHAR dpl :2;
    UCHAR present :1;
    USHORT OffsetHigh;
}CALLGATE, *PCALLGATE;
#pragma pack()*/

#pragma pack(1)
typedef struct _CALLGATE
{
    USHORT OffsetLow;
    USHORT selector;
    UCHAR DCount;
    UCHAR GType;
    USHORT OffsetHigh;
}CALLGATE, *PCALLGATE;

typedef struct _GDT_ENTRY
{
    USHORT limit;
    ULONG base;
}GDT_ENTRY, *PGDT_ENTRY;
#pragma pack()

#define IOCTL_SELECTOR CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_READ_DATA|FILE_WRITE_DATA)

CALLGATE OrigCallGate = {0};
PCALLGATE pOrigCallGate = NULL;
USHORT selector = 0;

NTSTATUS DispatchGeneral(PDEVICE_OBJECT pDeviceObject,PIRP pIrp);
NTSTATUS DispatchDeviceControl(PDEVICE_OBJECT pDeviceObject,PIRP pIrp);
VOID DriverUnload(PDRIVER_OBJECT pDriverObject);
VOID AddCallGate(VOID);
MyFunc(VOID);
VOID Ring0Func(VOID);

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING pRegistryPath)
{
    UNICODE_STRING usDriverName = {0};
    UNICODE_STRING usDosDeviceName = {0};
    WCHAR wDriverName[] = L"\\Device\\CallGate";
    WCHAR wDosDeviceName[] = L"\\DosDevices\\CallGate";
    PDEVICE_OBJECT pDeviceObject = NULL;
    ULONG i = 0;
    NTSTATUS NtStatus = STATUS_SUCCESS;

    KdPrint(("DriverEntry"));

    RtlInitUnicodeString(&usDriverName,wDriverName);
    RtlInitUnicodeString(&usDosDeviceName,wDosDeviceName);

    NtStatus = IoCreateDevice(pDriverObject,0,&usDriverName,FILE_DEVICE_UNKNOWN,0,FALSE,&pDeviceObject);

    if(NT_SUCCESS(NtStatus))
    {
        for(i = 0;i < IRP_MJ_MAXIMUM_FUNCTION;i++)
        {
            pDriverObject->MajorFunction[i] = DispatchGeneral;
        }

        pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl;

        pDriverObject->DriverUnload = DriverUnload;

        NtStatus = IoCreateSymbolicLink(&usDosDeviceName,&usDriverName);

        if(!NT_SUCCESS(NtStatus))
        {
            IoDeleteDevice(pDeviceObject);
            return NtStatus;
        }
    }

    AddCallGate();

    return NtStatus;
}

NTSTATUS DispatchGeneral(PDEVICE_OBJECT pDeviceObject,PIRP pIrp)
{
    pIrp->IoStatus.Status = STATUS_SUCCESS;
    pIrp->IoStatus.Information = 0;

    IoCompleteRequest(pIrp,IO_NO_INCREMENT);

    return STATUS_SUCCESS;
}

NTSTATUS DispatchDeviceControl(PDEVICE_OBJECT pDeviceObject,PIRP pIrp)
{
    PIO_STACK_LOCATION irpsp = NULL;
    PUSHORT pOutputBuffer = NULL;
    NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;

    irpsp = IoGetCurrentIrpStackLocation(pIrp);

    switch(irpsp->Parameters.DeviceIoControl.IoControlCode)
    {
        case IOCTL_SELECTOR:
        {
            pOutputBuffer = pIrp->AssociatedIrp.SystemBuffer;
            if(pOutputBuffer)
            {
                if(irpsp->Parameters.DeviceIoControl.OutputBufferLength >= 2)
                {
                    pOutputBuffer[0] = selector;
                    pIrp->IoStatus.Status = STATUS_SUCCESS;
                    pIrp->IoStatus.Information = 2;

                    NtStatus = STATUS_SUCCESS;
                }
                else
                {
                    pIrp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
                    pIrp->IoStatus.Information = 0;

                    NtStatus = STATUS_BUFFER_TOO_SMALL;
                }
            }
            else
            {
                pIrp->IoStatus.Status = STATUS_INVALID_PARAMETER;
                pIrp->IoStatus.Information = 0;

                NtStatus = STATUS_INVALID_PARAMETER;
            }
            break;
        }
    }

    IoCompleteRequest(pIrp,IO_NO_INCREMENT);

    return NtStatus;
}

VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
    UNICODE_STRING usDosDeviceName = {0};
    WCHAR wDosDeviceName[] = L"\\DosDevices\\CallGate";

    KdPrint(("Driver Unload"));

    pOrigCallGate->OffsetLow = OrigCallGate.OffsetLow;
    pOrigCallGate->selector = OrigCallGate.selector;
    pOrigCallGate->DCount = OrigCallGate.DCount;
    pOrigCallGate->GType = OrigCallGate.GType;
    pOrigCallGate->OffsetHigh = OrigCallGate.OffsetHigh;

    RtlInitUnicodeString(&usDosDeviceName,wDosDeviceName);

    IoDeleteSymbolicLink(&usDosDeviceName);
    IoDeleteDevice(pDriverObject->DeviceObject);
}

VOID AddCallGate(VOID)
{
    //PVOID pGdtBase = NULL;
    GDT_ENTRY gdtr = {0};
    PCALLGATE pCallGate = NULL;
    ULONG i = 0;

    /*__asm
    {
        push eax
        sgdt [esp-2]
        pop eax
        mov pGdtBase, eax
    }*/

    KdPrint(("Add Call Gate"));

    __asm sgdt gdtr

    for(i = 1;i < gdtr.limit;i++)
    {
        pCallGate = (PCALLGATE)(gdtr.base + i*8);

        if(!(pCallGate->GType & 0x80))
        {
            KdPrint(("%d",i));

            pOrigCallGate = pCallGate;
            OrigCallGate.OffsetLow = pCallGate->OffsetLow;
            OrigCallGate.selector = pCallGate->selector;
            OrigCallGate.DCount = pCallGate->DCount;
            OrigCallGate.GType = pCallGate->GType;
            OrigCallGate.OffsetHigh = pCallGate->OffsetHigh;

            pCallGate->OffsetLow = (USHORT)MyFunc;
            pCallGate->selector = 0x8;
            pCallGate->DCount = 0;
            pCallGate->GType = 0xEC;
            pCallGate->OffsetHigh = (USHORT)((ULONG)MyFunc>>16);

            selector = (USHORT)((i * 8) | 3);
            break;
        }
    }
}

__declspec(naked) MyFunc(VOID)
{
    __asm
    {
        pushad
        pushfd
        call Ring0Func
        popfd
        popad
        retf
    }
}

VOID Ring0Func(VOID)
{
    DbgPrint("call gate");
}
 
ring3:
#include <windows.h>
#include <winioctl.h>
#include <stdio.h>

#define IOCTL_SELECTOR CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_READ_DATA|FILE_WRITE_DATA)

int main()
{
    HANDLE hFile;
    WORD farcall[3];
    DWORD dwReturn;

    farcall[0] = 0x0;
    farcall[1] = 0x0;
    farcall[2] = 0x0;

    hFile = CreateFile("\\\\.\\CallGate",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
    
    if(hFile != INVALID_HANDLE_VALUE)
    {
        DeviceIoControl(hFile,IOCTL_SELECTOR,NULL,0,&farcall[2],2,&dwReturn,NULL);

        if(farcall[2])
        {
            __asm call fword ptr [farcall]
        }
        else
        {
            printf("unable to get selector");
        }
    }
    else
    {
        printf("unable to open device\n");
    }
    
    system("pause");
    return 1;
}

 

posted @ 2014-03-05 13:48  foo__hack  阅读(560)  评论(0编辑  收藏  举报