zoukankan      html  css  js  c++  java
  • 对<<寒江独钓Windows内核安全编程>>中第3章<<串口过滤>>的改进

      <<寒江独钓>>中第3章的串口过滤只实现了对写操作的过滤, 没有实现对读操作的过滤, 这里, 我改进了一下, 去掉了原来对所有串口的过滤, 改成了只对指定的串口过滤; 增加了同时对读操作的过滤,其实主要就是调用IoSetCompletionRoutine设置完成回调函数.

      源代码:
      

    #include <ntddk.h>
    #include <ntstrsafe.h>
    
    /**********************************************************
    文件名称:comdrv.c
    文件路径:./comdrv/comdrv.c
    创建时间:2013-1-29,14:18:08
    文件作者:女孩不哭
    文件说明:该程序是对<<寒江独钓>>中comcap串口过滤驱动程序的改进版,
    改进:
        [+] 增加了对串口的读取操作的过滤(原来只有写操作)
        [-] 去掉了原来对所有串口(32个)的过滤,现在只对指定端口
        [*] 优化了部分程序
    **********************************************************/
    
    //读操作请求计数
    ULONG gReadRequestionCounter = 0;
    
    //我的设备 设备扩展定义
    typedef struct{
        PDEVICE_OBJECT pFltObj;
        PDEVICE_OBJECT pTopDev;
    }COMDRV_DEVEXT,*PCOMDRV_DEVEXT;
    
    //函数的前向声明
    NTSTATUS comdrvOpenCom(ULONG comid, PDEVICE_OBJECT* ppOldObj);
    NTSTATUS comdrvAttachDevice(PDRIVER_OBJECT pDriver, PDEVICE_OBJECT pOldObj);
    
    void comdrvDriverUnload(PDRIVER_OBJECT pDriverObject);
    NTSTATUS DriverEntry(IN PDRIVER_OBJECT  pDriverObject, IN PUNICODE_STRING  pRegistryPath);
    
    void PrintHexString(char* prefix, UCHAR* buffer, ULONG length);
    
    NTSTATUS comdrvDispatch(PDEVICE_OBJECT pDevice, PIRP pIrp);
    NTSTATUS comdrvWrite(PDEVICE_OBJECT pDevice, PIRP pIrp);
    NTSTATUS comdrvRead(PDEVICE_OBJECT pDevice, PIRP pIrp);
    NTSTATUS comdrvReadCompletion(PDEVICE_OBJECT  DeviceObject, PIRP  Irp, PVOID  Context);
    
    
    //打开指定ID号的串口设备对象
    NTSTATUS comdrvOpenCom(ULONG comid, PDEVICE_OBJECT* ppOldObj)
    {
        NTSTATUS status;
        UNICODE_STRING name;
        WCHAR str[32] = {0};
        PFILE_OBJECT fileobj = NULL;
        PDEVICE_OBJECT devobj = NULL;
        RtlStringCchPrintfW(str, 32, L"\\Device\\Serial%d", comid);
        RtlInitUnicodeString(&name, str);
        status = IoGetDeviceObjectPointer(&name, FILE_ALL_ACCESS, &fileobj, &devobj);
        if(status == STATUS_SUCCESS)
            ObDereferenceObject(fileobj);
        *ppOldObj = devobj;
        return status;
    }
    
    //用指定的过虑设备绑定目标设备
    NTSTATUS comdrvAttachDevice(PDRIVER_OBJECT pDriver, PDEVICE_OBJECT pOldObj)
    {
        NTSTATUS status;
        PDEVICE_OBJECT pTopDev = NULL;
        PDEVICE_OBJECT pFltObj;
        PDEVICE_OBJECT next;
        PCOMDRV_DEVEXT pDevExt;
        //创建过虑设备
        status = IoCreateDevice(pDriver, sizeof(COMDRV_DEVEXT), NULL, pOldObj->DeviceType, 0, TRUE, &pFltObj);
        if(status != STATUS_SUCCESS)
            return status;
        //拷贝重要标志位
        if(pOldObj->Flags & DO_BUFFERED_IO) pFltObj->Flags |= DO_BUFFERED_IO;
        if(pOldObj->Flags & DO_DIRECT_IO) pFltObj->Flags |= DO_DIRECT_IO;
        if(pOldObj->Characteristics & FILE_DEVICE_SECURE_OPEN)
            pFltObj->Flags |= DO_POWER_PAGABLE;
        //绑定到另一设备上
        pTopDev = IoAttachDeviceToDeviceStack(pFltObj, pOldObj);
        if(pTopDev == NULL){
            IoDeleteDevice(pFltObj);
            pFltObj = NULL;
            status = STATUS_UNSUCCESSFUL;
            return status;
        }
        pFltObj->Flags &= ~DO_DEVICE_INITIALIZING;
        pDevExt = (PCOMDRV_DEVEXT)pFltObj->DeviceExtension;
        pDevExt->pFltObj = pFltObj;
        pDevExt->pTopDev = pTopDev;
        return STATUS_SUCCESS;
    }
    
    //打印出内存的16进制
    void PrintHexString(char* prefix, UCHAR* buffer, ULONG length)
    {
        int x;
        char* outbuf = NULL;
        char* poutbuf = NULL;
        //char* prefix = "comdrv_write:";
        int buflen = length*3+3+strlen(prefix);
        do{
            if(length == 0) break;
            outbuf = (char*)ExAllocatePool(NonPagedPool, buflen);
            if(outbuf == NULL){
                KdPrint(("ExAllocatePool failed!\r\n"));
                break;
            }
            strcpy(outbuf, prefix);
            poutbuf = outbuf+strlen(prefix);
            for(x=0; x<length; x++){
                sprintf(poutbuf, "%02X ", buffer[x]);
                poutbuf += 3;
            }
            sprintf(poutbuf, "\r\n");
            KdPrint((outbuf));
            ExFreePool(outbuf);
        }while(0);
    }
    
    //对写操作的处理
    NTSTATUS comdrvWrite(PDEVICE_OBJECT pDevice, PIRP pIrp)
    {
        NTSTATUS status;
        PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
        PCOMDRV_DEVEXT pDevExt = (PCOMDRV_DEVEXT)pDevice->DeviceExtension;
        ULONG len = pIrpSp->Parameters.Write.Length;
        PUCHAR buf = NULL;
        if(pIrp->MdlAddress != NULL)
            buf = (PUCHAR)MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority);
        else
            buf = (PUCHAR)pIrp->UserBuffer;
        if(buf == NULL)
            buf = (PUCHAR)pIrp->AssociatedIrp.SystemBuffer;
        //打印出内容
        PrintHexString("comdrv_write:", buf, len);
        IoSkipCurrentIrpStackLocation(pIrp);
        return IoCallDriver(pDevExt->pTopDev, pIrp);
    }
    
    //对读完成的处理
    NTSTATUS comdrvReadCompletion(PDEVICE_OBJECT  pDeviceObject, PIRP  pIrp, PVOID  pContext)
    {
        PIO_STACK_LOCATION CurIrp = NULL;
        ULONG length = 0;
        PUCHAR buffer = NULL;
        ULONG i;
        CurIrp = IoGetCurrentIrpStackLocation(pIrp);
        //在操作成功的前提下进行操作
        if(NT_SUCCESS(pIrp->IoStatus.Status)){
            //得到输出缓冲区
            buffer = (PUCHAR)pIrp->AssociatedIrp.SystemBuffer;
            length = pIrp->IoStatus.Information;
            //打印出读取到的内容
            PrintHexString("comdrv_read:", buffer, length);
        }
        //读操作已完成,保持平衡
        gReadRequestionCounter--;
    
        if(pIrp->PendingReturned)
            IoMarkIrpPending(pIrp);
        return pIrp->IoStatus.Status;
    }
    
    //对读操作的处理
    NTSTATUS comdrvRead(PDEVICE_OBJECT pDevice, PIRP pIrp)
    {
        NTSTATUS status;
        PCOMDRV_DEVEXT pDevExt = NULL;
        PIO_STACK_LOCATION CurIrp = NULL;
        //错误处理
        if(pIrp->CurrentLocation == 1){
            ULONG ReturnedInfo = 0;
            KdPrint(("comdrv irp current location error\r\n"));
            status = STATUS_INVALID_DEVICE_REQUEST;
            pIrp->IoStatus.Status = status;
            pIrp->IoStatus.Information = ReturnedInfo;
            return status;
        }
        //读操作增加
        gReadRequestionCounter++;
    
        pDevExt = (PCOMDRV_DEVEXT)pDevice->DeviceExtension;
        //设置读完成回调函数并下发IRP
        CurIrp = IoGetCurrentIrpStackLocation(pIrp);
        IoCopyCurrentIrpStackLocationToNext(pIrp);
        IoSetCompletionRoutine(pIrp, comdrvReadCompletion, NULL, TRUE, TRUE, TRUE);
        return IoCallDriver(pDevExt->pTopDev, pIrp);
    }
    
    //通用分发函数
    NTSTATUS comdrvDispatch(PDEVICE_OBJECT pDevice, PIRP pIrp)
    {
        NTSTATUS status;
        PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
        PCOMDRV_DEVEXT pDevExt = (PCOMDRV_DEVEXT)pDevice->DeviceExtension;
    
        //忽略所有电源操作
        if(pIrpSp->MajorFunction == IRP_MJ_POWER){
            PoStartNextPowerIrp(pIrp);
            IoSkipCurrentIrpStackLocation(pIrp);
            return PoCallDriver(pDevExt->pTopDev, pIrp);
        }
        //直接下发所有请求
        IoSkipCurrentIrpStackLocation(pIrp);
        return IoCallDriver(pDevExt->pTopDev, pIrp);
    }
    
    void comdrvDriverUnload(PDRIVER_OBJECT pDriverObject)
    {
    #define  DELAY_ONE_MICROSECOND  (-10)
    #define  DELAY_ONE_MILLISECOND (DELAY_ONE_MICROSECOND*1000)
    #define  DELAY_ONE_SECOND (DELAY_ONE_MILLISECOND*1000)
        LARGE_INTEGER li;
        PCOMDRV_DEVEXT pDevExt = NULL;
        li.QuadPart = 3*1000*DELAY_ONE_MILLISECOND;
        pDevExt = (PCOMDRV_DEVEXT)pDriverObject->DeviceObject->DeviceExtension;
        IoDetachDevice(pDevExt->pTopDev);
        while(gReadRequestionCounter)
            KeDelayExecutionThread(KernelMode, FALSE, &li);
        IoDeleteDevice(pDevExt->pFltObj);
    }
    
    NTSTATUS DriverEntry(IN PDRIVER_OBJECT  pDriverObject, IN PUNICODE_STRING  pRegistryPath)
    {
        NTSTATUS status;
        int it;
        PDEVICE_OBJECT pDevObj = NULL;
        //我们只过滤读写操作,其它的操作交给下层驱动处理
        for(it=0; it<IRP_MJ_MAXIMUM_FUNCTION; it++)
            pDriverObject->MajorFunction[it] = comdrvDispatch;
        pDriverObject->MajorFunction[IRP_MJ_WRITE] = comdrvWrite;
        pDriverObject->MajorFunction[IRP_MJ_READ] = comdrvRead;
        pDriverObject->DriverUnload = comdrvDriverUnload;
        //1代表COM2,2代表COM3, ...
        status = comdrvOpenCom(1, &pDevObj);
        if(!NT_SUCCESS(status))
            return status;
        status = comdrvAttachDevice(pDriverObject, pDevObj);
        if(!NT_SUCCESS(status))
            return status;
        return STATUS_SUCCESS;
    }

    源代码下载:https://files.cnblogs.com/nbsofer/comdrv.7z
    女孩不哭(QQ:191035066)@2013-02-25 13:59:23 http://www.cnblogs.com/nbsofer

    2013-03-09:
      发现一个原书中的错误,作者说Windows上的串口设备按串口号依次是\Device\Serial0,\Device\Serial1, ...
      这在事实上是不正确的, 因为Prolific的PL2303 USB转RS232驱动生成的设备就不叫\Device\Serialx, 而叫\Device\ProlificSerialx, 这可让我调试程序花了好多时间, 找时间告诉作者.


      

  • 相关阅读:
    【转载】总结一下Android中主题(Theme)的正确玩法
    Android获唯一标识
    AS问题解决系列3—iCCP: Not recognizing known sRGB profile
    AS问题解决系列1—Unable to execute DX错误
    Android Studio Error2
    Android Error
    NAT简单介绍
    redis缓存工具Jedis进行跨jvm加锁(分布式应用)--不幸暂弃用--能够做第三方锁使用
    工作总结1.怎样高效跟客户确定需求?
    Sqoop处理Clob与Blob字段
  • 原文地址:https://www.cnblogs.com/memset/p/2931999.html
Copyright © 2011-2022 走看看