• [1]编程实现加载驱动


    • 加载驱动的  标准方法 只有一种,就是利用服务管理器函数加载----SCM 加载法。

     

    WIN64驱动模板

    //[0]包含的头文件。可以加入系统或自己定义的头文件
    #include <ntddk.h>
    #include <windef.h>
    #include<stdlib.h>
    
    
    //[1]定义符号链接,一般来说修改为驱动的名字即可
    #define DEVICE_NAME   L"\Device\KrnlHW64" 
    #define LINK_NAME   L"\DosDevices\KrnlHW64" 
    #define LINK_GLOBAL_NAME  L"\DosDevices\Global\KrnlHW64" 
    
    
    //[2]定义驱动功能号和名字,提供接口给应用程序调用
    #define IOCTL_IO_TEST  CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS) 
    #define IOCTL_SAY_HELLO  CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS) 
    
    //【3】驱动卸载的处理例程 
    
    VOID DriverUnload(PDRIVER_OBJECT pDriverObj)
    {
        UNICODE_STRING strLink;
        DbgPrint("[KrnlHW64]DriverUnload
    "); 
        RtlInitUnicodeString(&strLink, LINK_NAME);  IoDeleteSymbolicLink(&strLink);
        IoDeleteDevice(pDriverObj->DeviceObject);
    }
    
    //【4】IRP_MJ_CREATE对应的处理例程,一般不用管它 
    NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
    { 
        DbgPrint("[KrnlHW64]DispatchCreate
    ");  
        pIrp->IoStatus.Status = STATUS_SUCCESS;
        pIrp->IoStatus.Information = 0; 
        IoCompleteRequest(pIrp, IO_NO_INCREMENT);
        return STATUS_SUCCESS; 
    } 
    
    //【5】IRP_MJ_CLOSE对应的处理例程,一般不用管它
    NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp) 
    { 
        DbgPrint("[KrnlHW64]DispatchClose
    ");
        pIrp->IoStatus.Status = STATUS_SUCCESS; 
        pIrp->IoStatus.Information = 0; 
        IoCompleteRequest(pIrp, IO_NO_INCREMENT);
        return STATUS_SUCCESS;
    } 
    
    //【6】IRP_MJ_DEVICE_CONTROL对应的处理例程,驱动最重要的函数之一,一般走正常途径调 用驱动功能的程序,都会经过这个函数 
    NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
    { 
        NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST; 
        PIO_STACK_LOCATION pIrpStack; 
        ULONG uIoControlCode;  
        PVOID pIoBuffer; 
        ULONG uInSize; 
        ULONG uOutSize;
        DbgPrint("[KrnlHW64]DispatchIoctl
    ");
        pIrpStack = IoGetCurrentIrpStackLocation(pIrp);  //控制码 
        uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;  //输入输出缓冲区  
        pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;  //输入区域大小  
        uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;  //输出区域大小 
        uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength; 
        switch(uIoControlCode) 
        {  
            //在这里加入接口   
            case IOCTL_IO_TEST:  
            {    
                DWORD dw=0;    //获得输入的内容   
                memcpy(&dw,pIoBuffer,sizeof(DWORD));    //使用输入的内容  
                dw++;    //输出处理的结果    
                memcpy(pIoBuffer,&dw,sizeof(DWORD));    //处理成功,返回非STATUS_SUCCESS会让DeviveIoControl返回失败 
                status = STATUS_SUCCESS;  
                break;   
            } 
            case IOCTL_SAY_HELLO: 
            {  
                DbgPrint("[KrnlHW64]IOCTL_SAY_HELLO
    ");   
                status = STATUS_SUCCESS;  
                break; 
            } 
        } 
        if(status == STATUS_SUCCESS)  
            pIrp->IoStatus.Information = uOutSize; 
        else  
            pIrp->IoStatus.Information = 0; 
        pIrp->IoStatus.Status = status; 
        IoCompleteRequest(pIrp, IO_NO_INCREMENT); 
        return status; 
    } 
    
            //【7】驱动加载的处理例程,里面进行了驱动的初始化工作
    NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString) 
    {  
        NTSTATUS status = STATUS_SUCCESS; 
        UNICODE_STRING ustrLinkName;  
        UNICODE_STRING ustrDevName;   
        PDEVICE_OBJECT pDevObj;  //初始化驱动例程  
        pDriverObj->MajorFunction[IRP_MJ_CREATE] = DispatchCreate; 
        pDriverObj->MajorFunction[IRP_MJ_CLOSE] = DispatchClose; 
        pDriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl;
        pDriverObj->DriverUnload = DriverUnload;
        //创建驱动设备
        RtlInitUnicodeString(&ustrDevName, DEVICE_NAME); 
        status = IoCreateDevice(pDriverObj, 0, &ustrDevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDevObj);
        if(!NT_SUCCESS(status)) return status; 
        if(IoIsWdmVersionAvailable(1, 0x10))  
            RtlInitUnicodeString(&ustrLinkName, LINK_GLOBAL_NAME); 
        else  
            RtlInitUnicodeString(&ustrLinkName, LINK_NAME);  //创建符号链接 
        status = IoCreateSymbolicLink(&ustrLinkName, &ustrDevName);  
        if(!NT_SUCCESS(status)) 
        {  
            IoDeleteDevice(pDevObj);  
            return status; 
        } 
        //走到这里驱动实际上已经初始化完成,下面添加的是功能初始化的代码 
        DbgPrint("[KrnlHW64]DriverEntry
    "); 
        return STATUS_SUCCESS; 
    }

    使用SCM 系列函数加载卸载驱动的过程并不复杂,总体流程是:打开SCM 管理器(获得SCM 句柄)->创建驱动服务(获得服务句柄,如果服务已经存在,此步则变成打开服务)->启动服务->停止服务->移除服务->关闭服务句柄->关闭SCM 句柄。如果要与驱动通信,则用CreateFile 打开驱动的符号链接(可以理解成获得一个“通信句柄”),然后使DeviceIoControl 与驱动进行信息交互。如果曾经打开过驱动的符号链接,则必须在卸载驱动前关闭“通信句柄”,否则再次加载相同的驱动时会有一些麻烦。

     DeviceIoControl 的参数也很好理解,只有5 个重要参数:控制码,输入缓冲区,输入长度,输出缓冲区,输出长度

     

  • 相关阅读:
    改进昨天的电梯电梯问题
    电梯调度
    结对开发四---实现环状二维数组求最大子数组的和
    结对开发五--对一千个数long型的一维数组求最大子数组的和
    结对开发四------求一维无头数组最大子数组的和
    结对开发3--电梯调度问题需求分析
    SQL基础题
    类和对象(课后题)
    再战文件(小甲鱼课后题)python超级入门
    快来集合!python超级入门笔记
  • 原文地址:https://www.cnblogs.com/hanhandaren/p/11351711.html
Copyright © 2020-2023  润新知