驱动编程学习四 通过进程ID获取进程名 将进程监控添加到 数据分发 函数中

在 监控进程 类 中添加 代码

监控进程.h  头文件中

#pragma once
//#include <ntifs.h>
void 安装进程监控();  //通过DriverEntry  或者 DeviceIoControl  来安装
void 卸载进程监控();  //通过DriverUnload

const char*  通过进程ID获取进程名(HANDLE pid);

监控进程.cpp  实现文件中

#pragma once
#include <ntifs.h>
#include "监控进程.h"

//https://www.cnblogs.com/iBinary/p/8399312.html
//PsSetLoadImageNotifyRoutine(PLOAD_IMAGE_NOTIFY_ROUTINE NotifyRoutine);
//PsSetCreateProcessNotifyRoutineEx();

NTSTATUS PsSetCreateProcessNotifyRoutine(
    PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine,//这是一个回调函数指针
    BOOLEAN );//安装为假,卸载时为真。

//PCREATE_PROCESS_NOTIFY_ROUTINE PcreateProcessNotifyRoutine;
VOID NotifyRoutine( HANDLE ParentId,HANDLE ProcessId,BOOLEAN Create)//回调函数
{
    char* p1 = 通过进程ID获取进程名(ParentId);
    char* p2 = 通过进程ID获取进程名(ProcessId);
    if (Create)
    {
      KdPrint(("jw:(%s)ParentId = %d (%s)ProcessId = %d 进程创建 \r\n",p1, ParentId, p2,ProcessId));
    }
    else {
        KdPrint(("jw:(%s)ParentId = %d (%s)ProcessId = %d 进程退出 \r\n",p1, ParentId,p2, ProcessId));
    }
}

void 安装进程监控()
{
    PsSetCreateProcessNotifyRoutine(NotifyRoutine, FALSE);
}

void 卸载进程监控()
{
    PsSetCreateProcessNotifyRoutine(NotifyRoutine, TRUE);
}


NTKERNELAPI UCHAR * PsGetProcessImageFileName(__in PEPROCESS Process);
const char * 通过进程ID获取进程名(HANDLE pid)
{
    PEPROCESS Process = NULL;
    //例程接受进程的进程 ID,并返回指向进程的 EPROCESS 结构的引用指针
    NTSTATUS status = PsLookupProcessByProcessId(pid,//指定进程的进程 ID。
        &Process);//返回指向 由 ProcessId 指定的进程的 EPROCESS 结构的引用指针
    return PsGetProcessImageFileName(Process);
}

在 驱动入口 函数 页中 修改 分发 函数 代码   驱动入口函数中删除  安装进程监控  的调用     在卸载驱动中 移除  卸载进程监控 的调用

 将 进程监控 添加到 分发代码 中

//#include <ntddk.h>//这2个只要一个就可以了。
#include <ntifs.h>
#include "监控进程.h"

#define  符号链接名字 L"\\??\\mylinkName"       //这个是用户层访问的CreateFile
#define  驱动设备名字 L"\\DEVICE\uzDriverName001"         //这是内核访问的NtCreateFile
//创建驱动设备对象
NTSTATUS CreateDevice(PDRIVER_OBJECT driver)
{
    NTSTATUS status;
    UNICODE_STRING uzDriverName;//char*wchar*
    PDEVICE_OBJECT device = NULL;  //这是一个指针
    RtlInitUnicodeString(&uzDriverName, 驱动设备名字);//strcpy//ucscpy,初始化字符串对象

    KdPrint(("jw:未创建设备前:driver->DeviceObject=%p, device=%p \r\n", driver->DeviceObject, device));

    status = IoCreateDevice(driver,
        4,//sizeof(DEVICE_EXTENSION),自己定义的结构的大小
        &uzDriverName,    // 设备名字
        FILE_DEVICE_UNKNOWN,//设备的类型
        FILE_DEVICE_SECURE_OPEN,////独占的话设置为TRUE,非独占设置为FALSE
        FALSE,
        &device);//device 返回设备对象
    
    if (status == STATUS_SUCCESS)
    {
        KdPrint(("jw:驱动设备对象创建成功,ok \n"));
        //创建设备对象之后就可以为驱动对象绑定符号链接,就是为设备创建一个别名
        UNICODE_STRING uzMyLinsName;    //符号链接名字
        RtlInitUnicodeString(&uzMyLinsName, 符号链接名字);//初始化字符串
        status = IoCreateSymbolicLink(&uzMyLinsName, &uzDriverName);
        if (status == STATUS_SUCCESS)
        {
            KdPrint(("jw:创建符号链接 符号链接名= %wZ 成功\r\n", &uzMyLinsName));
        }else{
            IoDeleteSymbolicLink(&uzMyLinsName);//删除符号链接
            KdPrint(("jw:创建符号链接失败 错误代码=%X \r\n", status));//错误就是状态码
        }
    }
    else {
        KdPrint(("jw:驱动设备对象创建失败,删除设备 \n"));
        IoDeleteDevice(device);
    }
    KdPrint(("jw:创建设备之后:driver->DeviceObject=%p, device=%p \r\n", driver->DeviceObject, device));
    return status;
}

//访问驱动设备及IRP事件处理
//https://learn.microsoft.com/zh-cn/windows-hardware/drivers/kernel/irp-major-function-codes
#define  IO_STRING  CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803,METHOD_BUFFERED,FILE_ANY_ACCESS)   //控制码测试
#define  IO_进程监控安装  CTL_CODE(FILE_DEVICE_UNKNOWN, 0x806,METHOD_BUFFERED,FILE_ANY_ACCESS)   //控制码测试
#define  IO_进程监控卸载  CTL_CODE(FILE_DEVICE_UNKNOWN, 0x807,METHOD_BUFFERED,FILE_ANY_ACCESS)   //控制码测试
NTSTATUS IRP_PROC(PDEVICE_OBJECT device, PIRP pirp)//irp回调函数
{//常用的三个处理
    KdPrint(("jw:进入派遣函数"));
    PIO_STACK_LOCATION irpStack;
    ULONG CtlCode;
    ULONG InputBuffLength;

    irpStack = IoGetCurrentIrpStackLocation(pirp);//获取应用层传来的消息

    switch (irpStack->MajorFunction)
    {//分发消息
    case IRP_MJ_DEVICE_CONTROL:  //DeviceIoControl
    {
        ULONG IoCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
        switch (IoCode)
        {//利用控制码分发
        case IO_进程监控安装:
        {
            安装进程监控();
            KdPrint(("jw:SYS IO_进程监控安装 =%X \r\n", IoCode));
            break;
        };
        case IO_进程监控卸载:
        {
            卸载进程监控();
            KdPrint(("jw:SYS IO_进程监控卸载 =%X \r\n", IoCode));
            break;
        };
        case IO_STRING:
        {
            //这里取出用户层传递过来的缓冲区的数据
            char *pInbuf = (char *)pirp->AssociatedIrp.SystemBuffer;
            //取出缓冲区大小
            KdPrint(("jw:pInbuf = %s \r\n", pInbuf));
            KdPrint(("jw:用户层调用了 DeviceIoControl"));
            //返回数据给缓冲区
            strcpy(pInbuf, "这个数据是驱动返回给用户层的。\r\n");
        }
        default:
            break;
        }
        //case irpStack->Parameters.DeviceIoControl.IoControlCode:
        //
        pirp->IoStatus.Status = STATUS_SUCCESS;
        pirp->IoStatus.Information = irpStack->Parameters.DeviceIoControl.OutputBufferLength;  //返回给DeviceIoControl中的 倒数第二个参数lpBytesReturned
        IoCompleteRequest(pirp, IO_NO_INCREMENT);  //调用方已完成所有I/O请求处理操作  并且不增加优先级
        break;
    }
    case IRP_MJ_CREATE:   //CreateFile
    {
        KdPrint(("jw:用户层调用了 CreateFile "));
        break;
    }
    case IRP_MJ_CLOSE:   //CloseHandle
    {
        KdPrint(("jw:用户层调用了 CloseHandle"));
    }
    }

    KdPrint(("jw:离开派遣函数 \r\n"));
    return STATUS_SUCCESS;
};

//卸载驱动
void Unload(PDRIVER_OBJECT driver)
{//因为参数driver没有使用,会出现警告。
    //卸载进程监控();
    //一定要在删除设备前 先删除符号链接
    UNICODE_STRING uzMyLinsName;    //符号链接名字
    RtlInitUnicodeString(&uzMyLinsName, 符号链接名字);//初始化字符串
    IoDeleteSymbolicLink(&uzMyLinsName);
    //删除设备对象
    IoDeleteDevice(driver->DeviceObject);
    KdPrint(("jw:进入卸载例程"));
}

//驱动入口点函数
NTSTATUS DriverEntry(PDRIVER_OBJECT driver,PUNICODE_STRING szReg)
{
    KdPrint(("jw:我的第一个驱动,最简单的驱动+++++++++"));
    KdPrint(("jw:注册路径 = %wZ", szReg));//szReg注册表的路径
    driver->DriverUnload = Unload;//注册卸载例程
    //irp处理
    driver->MajorFunction[IRP_MJ_CREATE] = IRP_PROC;
    driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IRP_PROC;
    driver->MajorFunction[IRP_MJ_CLOSE] = IRP_PROC;

    //调用创建驱动设备函数 CreateDevice
    CreateDevice(driver);//创建驱动设备
    //安装进程监控();//调用
    return STATUS_SUCCESS;
};//最小的驱动  只有一行代码。

在 驱动用户层访问  中修改代码   添加2个按钮    安装进程监控    和  移除进程监控

#define  IO_进程监控安装  CTL_CODE(FILE_DEVICE_UNKNOWN, 0x806,METHOD_BUFFERED,FILE_ANY_ACCESS)   //控制码测试
#define  IO_进程监控卸载  CTL_CODE(FILE_DEVICE_UNKNOWN, 0x807,METHOD_BUFFERED,FILE_ANY_ACCESS)   //控制码测试
//安装进程监控
void C驱动用户层访问Dlg::OnBnClickedBtnInstapromon()
{
    //打开设备,获取设备句柄
    g_sysHandle = CreateFileW(符号链接名字,
        GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

    DWORD  dwRetSize = 0;
    BOOL br = DeviceIoControl(g_sysHandle,//CreateFileW 打开驱动设备 返回的句柄
        IO_进程监控安装,//控制码 CTL_CODE
        NULL,  //输入缓冲区指针   驱动中在irp中的 IRP_MJ_DEVICE_CONTROL中处理放入缓冲区的数据
        NULL, //输入缓冲区大小,直接写100也可以
        NULL,//返回缓冲区的地址
        256,  //返回缓冲区的大小
        &dwRetSize, //返回字节数
        NULL);
    //返回值 
    TRACE("jw:IO_进程监控安装 = %X \r\n", IO_进程监控安装);//
    //另一种方式打印数据
    char buf[1024] = { 0 };
    sprintf_s(buf, "jw:IO_进程监控安装 =%X  \r\n", IO_进程监控安装);
    OutputDebugStringA(buf);//用调试输出
}

//移除进程监控
void C驱动用户层访问Dlg::OnBnClickedBtnUnloadpromon2()
{
    //打开设备,获取设备句柄
    g_sysHandle = CreateFileW(符号链接名字,
        GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

    //传递字符串到设备。
    DWORD  dwRetSize = 0;
    BOOL br = DeviceIoControl(g_sysHandle,//CreateFileW 打开驱动设备 返回的句柄
        IO_进程监控卸载,//控制码 CTL_CODE
        NULL,  //输入缓冲区指针   驱动中在irp中的 IRP_MJ_DEVICE_CONTROL中处理放入缓冲区的数据
        NULL, //输入缓冲区大小,直接写100也可以
        NULL,//返回缓冲区的地址
        256,  //返回缓冲区的大小
        &dwRetSize, //返回字节数
        NULL);
    //返回值 
    TRACE("jw:IO_进程监控卸载 = %X \r\n", IO_进程监控卸载);//
                                         //另一种方式打印数据
    char buf[1024] = { 0 };
    sprintf_s(buf, "jw:IO_进程监控卸载 =%X ", IO_进程监控卸载);
    OutputDebugStringA(buf);//用调试输出
}

 

posted on 2022-11-21 15:00  悠心不已  阅读(37)  评论(0)    收藏  举报

导航