• 使用调用门


    要注意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 ");
        }
        
        system("pause");
        return 1;
    }

     

  • 相关阅读:
    vector向量容器的一些基本操作
    OpenCV鼠标画图例程,鼠标绘制矩形
    网络安全学习笔记--《暗战强人:黑客攻防入门全程图解》
    遗传算法解决TSP问题实现以及与最小生成树的对比
    基于opencv的手写数字字符识别
    最小生成树
    opencv基本图像操作
    使用vs2010 opencv2.4.4编译release版本程序
    【machine translate】deep learning seq2seq
    【DL】物体识别与定位
  • 原文地址:https://www.cnblogs.com/foohack/p/3582298.html
Copyright © 2020-2023  润新知