驱动通信:驱动与应用的通信(3)

驱动程序与应用程序的通信离不开派遣函数,派遣函数是Windows驱动编程中的重要概念,一般情况下驱动程序负责处理I/O特权请求,而大部分IO的处理请求是在派遣函数中处理的,当用户请求数据时,操作系统会提前处理好请求,并将其派遣到指定的内核函数中执行,接下来将详细说明派遣函数的使用并通过派遣函数读取Shadow SSDT中的内容。

先来简单介绍一下 IRP(I/O Request Package) 输入输出请求包,该请求包在Windows内核中是一个非常重要的数据结构,当我们的上层应用与底层的驱动程序通信时,应用程序就会发出I/O请求,操作系统将该请求转化为相应的IRP数据,然后会根据不同的请求数据将请求派遣到相应的驱动函数中执行,这一点有点类似于Windows的消息机制。

创建设备对象: 在使用派遣函数的之前需要创建设备对象,因为后期的读写都要通过设备对象来连接。

#include <ntddk.h>

VOID UnDriver(PDRIVER_OBJECT pDriver)
{
    PDEVICE_OBJECT pDev;         // 用来取得要删除设备对象
    UNICODE_STRING SymLinkName;  // 局部变量symLinkName

    //删掉所有设备
    pDev = pDriver->DeviceObject;
    IoDeleteDevice(pDev);                                       // 调用IoDeleteDevice用于删除设备
    RtlInitUnicodeString(&SymLinkName, L"\\??\\My_Driver");     // 初始化字符串将symLinkName定义成需要删除的符号链接名称
    IoDeleteSymbolicLink(&SymLinkName);                         // 调用IoDeleteSymbolicLink删除符号链接
    DbgPrint("删除设备与符号链接成功...");
}

NTSTATUS CreateDriverObject(IN PDRIVER_OBJECT pDriver)
{
    NTSTATUS Status;               // 接收驱动程序的返回状态
    PDEVICE_OBJECT pDevObj;        // 用于返回创建设备
    UNICODE_STRING DriverName;     // 用于存放设备的名称
    UNICODE_STRING SymLinkName;    // 用于存放符号链接名称

    RtlInitUnicodeString(&DriverName, L"\\Device\\My_Device");  // 将DrvierName填充为\\Device\\My_Device

    // 使用命令IoCreateDevice用来创建设备,并将创建后的状态保存在status
    Status = IoCreateDevice(pDriver, 0, &DriverName, FILE_DEVICE_UNKNOWN, 0, TRUE, &pDevObj);
    DbgPrint("当前命令IoCreateDevice状态: %d", Status);
    if (!NT_SUCCESS(Status))
    {
        // 调用IoCreateDevice成功与失败都会返回参数,将返回参数给Status用于判断
        // STATUS_INSUFFICIENT_RESOURCES   资源不足
        // STATUS_OBJECT_NAME_EXISTS       指定对象名存在
        // STATUS_OBJECT_NAME_COLLISION    对象名有冲突
        if (Status == STATUS_OBJECT_NAME_COLLISION)
        {
            DbgPrint("对象名冲突..");
        }
        DbgPrint("创建失败.");
    }

    pDevObj->Flags |= DO_BUFFERED_IO;                            // flags 标识有没有do_buffered_io位标识
    RtlInitUnicodeString(&SymLinkName, L"\\??\\My_Device");      // 对symLinkName初始化字串为 "\\??\\My_Device"
    // 创建设备链接,驱动程序虽然有设备名称,但是这种设备名只能在内核态可见
    // 而对于应用程序是不可见的,因此驱动需要要暴露一个符号链接,该链接指向真正的设备名称
    Status = IoCreateSymbolicLink(&SymLinkName, &DriverName);    // 调用命令IoCreateSymbolicLink用于创建符号链接
    DbgPrint("当前命令IoCreateSymbolicLink状态: %d", Status);
    if (!NT_SUCCESS(Status)) // 如果status不等于0 就执行
    {
        IoDeleteDevice(pDevObj);  // 调用命令IoDeleteDevice删除当前pDevObj设备
        DbgPrint("删除设备成功...");
        return Status;
    }
    else
    {
        DbgPrint("创建符号链接成功...");
    }
    return STATUS_SUCCESS;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING RegistryPath)
{
    CreateDriverObject(pDriver);
    pDriver->DriverUnload = UnDriver;
    return STATUS_SUCCESS;
}

简单的驱动通信: 注册两个派遣函数,当设备创建的时候触发,以及关闭时触发。

#include <ntddk.h>

VOID UnDriver(PDRIVER_OBJECT pDriver)
{
    PDEVICE_OBJECT pDev;         // 用来取得要删除设备对象
    UNICODE_STRING SymLinkName;  // 局部变量symLinkName

    pDev = pDriver->DeviceObject;
    IoDeleteDevice(pDev);                                       // 调用IoDeleteDevice用于删除设备
    RtlInitUnicodeString(&SymLinkName, L"\\??\\My_Driver");     // 初始化字符串将symLinkName定义成需要删除的符号链接名称
    IoDeleteSymbolicLink(&SymLinkName);                         // 调用IoDeleteSymbolicLink删除符号链接
    DbgPrint("删除设备与符号链接成功...");
}

NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
    pIrp->IoStatus.Status = STATUS_SUCCESS;          // 返回成功
    DbgPrint("派遣函数 IRP_MJ_CREATE 成功执行 !\n");
    IoCompleteRequest(pIrp, IO_NO_INCREMENT);        // 指示完成此IRP
    return STATUS_SUCCESS;                           // 返回成功
}

NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
    pIrp->IoStatus.Status = STATUS_SUCCESS;          // 返回成功
    DbgPrint("派遣函数 IRP_MJ_CLOSE 成功执行 !\n");
    IoCompleteRequest(pIrp, IO_NO_INCREMENT);        // 指示完成此IRP
    return STATUS_SUCCESS;                           // 返回成功

}

NTSTATUS CreateDriverObject(IN PDRIVER_OBJECT pDriver)
{
    NTSTATUS Status;
    PDEVICE_OBJECT pDevObj;
    UNICODE_STRING DriverName;
    UNICODE_STRING SymLinkName;

    RtlInitUnicodeString(&DriverName, L"\\Device\\My_Device");
    Status = IoCreateDevice(pDriver, 0, &DriverName, FILE_DEVICE_UNKNOWN, 0, TRUE, &pDevObj);
    DbgPrint("命令 IoCreateDevice 状态: %d", Status);

    // DO_BUFFERED_IO 设置读写方式 Flags的三个不同的值分别为:DO_BUFFERED_IO、DO_DIRECT_IO和0
    pDevObj->Flags |= DO_BUFFERED_IO;
    RtlInitUnicodeString(&SymLinkName, L"\\??\\My_Device");
    Status = IoCreateSymbolicLink(&SymLinkName, &DriverName);
    DbgPrint("当前命令IoCreateSymbolicLink状态: %d", Status);
    return STATUS_SUCCESS;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING RegistryPath)
{
    CreateDriverObject(pDriver);           // 调用创建设备子过程
    // 注册两个派遣函数,分别对应创建与关闭,派遣函数名可自定义
    pDriver->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;    // 创建成功派遣函数
    pDriver->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;      // 关闭派遣函数

    DbgPrint("驱动加载完成...");
    pDriver->DriverUnload = UnDriver;
    return STATUS_SUCCESS;
}

客户端代码

#include <windows.h>
#include <stdio.h>
#include <winioctl.h>

int main()
{
    HANDLE hDevice = CreateFile(L"\\\\.\\My_Device", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hDevice == INVALID_HANDLE_VALUE) //判断hDevice返回值是否为空
    {
        printf("获取驱动句柄失败!错误: %d\n", GetLastError());
        getchar();
    }

    getchar();
    CloseHandle(hDevice);
    return 0;
}

读取驱动中的数据: 实现读取内核缓冲区中的数据,并打印出来。

#include <ntddk.h>

VOID UnDriver(PDRIVER_OBJECT pDriver)
{
    PDEVICE_OBJECT pDev;         // 用来取得要删除设备对象
    UNICODE_STRING SymLinkName;  // 局部变量symLinkName
    pDev = pDriver->DeviceObject;
    IoDeleteDevice(pDev);                                       // 调用IoDeleteDevice用于删除设备
    RtlInitUnicodeString(&SymLinkName, L"\\??\\My_Driver");     // 初始化字符串将symLinkName定义成需要删除的符号链接名称
    IoDeleteSymbolicLink(&SymLinkName);                         // 调用IoDeleteSymbolicLink删除符号链接
    DbgPrint("删除设备与符号链接成功...");
}
NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
    pIrp->IoStatus.Status = STATUS_SUCCESS;          // 返回成功
    DbgPrint("派遣函数 IRP_MJ_CREATE 成功执行 !\n");
    IoCompleteRequest(pIrp, IO_NO_INCREMENT);        // 指示完成此IRP
    return STATUS_SUCCESS;                           // 返回成功
}
NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
    pIrp->IoStatus.Status = STATUS_SUCCESS;          // 返回成功
    DbgPrint("派遣函数 IRP_MJ_CLOSE 成功执行 !\n");
    IoCompleteRequest(pIrp, IO_NO_INCREMENT);        // 指示完成此IRP
    return STATUS_SUCCESS;                           // 返回成功
}

NTSTATUS DispatchRead(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
    NTSTATUS Status = STATUS_SUCCESS;
    PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(pIrp);
    ULONG ulReadLength = Stack->Parameters.Read.Length;
    pIrp->IoStatus.Status = Status;
    pIrp->IoStatus.Information = ulReadLength;
    DbgPrint("应用要读取的长度:%d\n", ulReadLength);

    // 将内核中的缓冲区全部填充为0x68 方便演示读取的效果
    memset(pIrp->AssociatedIrp.SystemBuffer, 0x68, ulReadLength);
    IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    return Status;
}

NTSTATUS CreateDriverObject(IN PDRIVER_OBJECT pDriver)
{
    NTSTATUS Status;
    PDEVICE_OBJECT pDevObj;
    UNICODE_STRING DriverName;
    UNICODE_STRING SymLinkName;

    RtlInitUnicodeString(&DriverName, L"\\Device\\My_Device");
    Status = IoCreateDevice(pDriver, 0, &DriverName, FILE_DEVICE_UNKNOWN, 0, TRUE, &pDevObj);
    DbgPrint("命令 IoCreateDevice 状态: %d", Status);
    pDevObj->Flags |= DO_BUFFERED_IO;
    RtlInitUnicodeString(&SymLinkName, L"\\??\\My_Device");
    Status = IoCreateSymbolicLink(&SymLinkName, &DriverName);
    DbgPrint("当前命令IoCreateSymbolicLink状态: %d", Status);
    return STATUS_SUCCESS;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING RegistryPath)
{
    CreateDriverObject(pDriver);                               // 调用创建设备
    pDriver->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;    // 创建成功派遣函数
    pDriver->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;      // 关闭派遣函数
    pDriver->MajorFunction[IRP_MJ_READ] = DispatchRead;

    DbgPrint("驱动加载完成...");
    pDriver->DriverUnload = UnDriver;
    return STATUS_SUCCESS;
}

客户端代码

#include <windows.h>
#include <stdio.h>
#include <winioctl.h>

int main()
{
    HANDLE hDevice = CreateFile(L"\\\\.\\My_Device", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hDevice == INVALID_HANDLE_VALUE)
    {
        printf("获取驱动句柄失败: %d\n", GetLastError());
        getchar();
    }

    UCHAR buffer[10];
    ULONG ulRead;

    ReadFile(hDevice, buffer, 10, &ulRead, 0);
    for (int i = 0; i < (int)ulRead; i++)
    {
        printf("%02X", buffer[i]);
    }
    getchar();
    CloseHandle(hDevice);
    return 0;
}

向驱动派发命令: 向驱动程序中发送一个结构,驱动程序内部通过DbgPrint打印出来。

#include <ntddk.h>
#define My_Code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)

typedef struct Hread {
    ULONG Flage;
    ULONG Addr;
    ULONG WriteBufferAddr;
    ULONG Size;
    ULONG Pid;
}_Hread, *PtrHread;

typedef struct _DEVICE_EXTENSION {
    UNICODE_STRING SymLinkName;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
    PDEVICE_OBJECT pDevObj;
    pDevObj = pDriverObject->DeviceObject;
    PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
    UNICODE_STRING pLinkName = pDevExt->SymLinkName;
    IoDeleteSymbolicLink(&pLinkName);
    IoDeleteDevice(pDevObj);
}
NTSTATUS DefDispatchRoutine(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
    NTSTATUS status = STATUS_SUCCESS;
    pIrp->IoStatus.Status = status;
    pIrp->IoStatus.Information = 0;
    IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    return status;
}

NTSTATUS IoctlDispatchRoutine(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
    NTSTATUS Status = STATUS_UNSUCCESSFUL;
    ULONG_PTR Informaiton = 0;
    PVOID InputData = NULL;
    ULONG InputDataLength = 0;
    PVOID OutputData = NULL;
    ULONG OutputDataLength = 0;
    PIO_STACK_LOCATION  IoStackLocation = IoGetCurrentIrpStackLocation(pIrp);              // Irp堆栈  
    InputData = pIrp->AssociatedIrp.SystemBuffer;
    OutputData = pIrp->AssociatedIrp.SystemBuffer;
    InputDataLength = IoStackLocation->Parameters.DeviceIoControl.InputBufferLength;      // 输入数据大小
    OutputDataLength = IoStackLocation->Parameters.DeviceIoControl.OutputBufferLength;    // 输出数据大小
    ULONG Code = IoStackLocation->Parameters.DeviceIoControl.IoControlCode;

    switch (Code)
    {
    case My_Code:
        PtrHread PtrBuff = (PtrHread)InputData;
        ULONG RetFlage = PtrBuff->Flage;
        ULONG RetAddr = PtrBuff->Addr;
        ULONG RetBufferAddr = PtrBuff->WriteBufferAddr;
        ULONG Size = PtrBuff->Size;
        ULONG Pid = PtrBuff->Pid;

        DbgPrint("读取文件标志:%d", RetFlage);
        DbgPrint("读取写入地址:%x", RetAddr);
        DbgPrint("读取缓冲区大小:%d", RetBufferAddr);
        DbgPrint("读取当前大小:%d", Size);
        DbgPrint("要操作进程PID: %d", Pid);

        // 通过内存返回数据.
        char *retBuffer = "hello lyshark";
        memcpy(OutputData, retBuffer , strlen(retBuffer));
        Informaiton = strlen(retBuffer) + 1;
        Status = STATUS_SUCCESS;

        // 通过内存返回数据,另一种通信方式.
        PVOID addr = (PVOID)"ok";
        RtlCopyMemory(OutputData, addr, 4);
        Informaiton = 4;
        Status = STATUS_SUCCESS;
        break;
    }

    pIrp->IoStatus.Status = Status;                   // 设置IRP完成状态,会设置用户模式下的GetLastError
    pIrp->IoStatus.Information = Informaiton;    // 设置操作的字节
    IoCompleteRequest(pIrp, IO_NO_INCREMENT);         // 完成IRP,不增加优先级
    return Status;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath)
{
    pDriverObject->DriverUnload = DriverUnload;//注册驱动卸载函数
    pDriverObject->MajorFunction[IRP_MJ_CREATE] = DefDispatchRoutine;   // 注册派遣函数
    pDriverObject->MajorFunction[IRP_MJ_CLOSE] = DefDispatchRoutine;
    pDriverObject->MajorFunction[IRP_MJ_WRITE] = DefDispatchRoutine;
    pDriverObject->MajorFunction[IRP_MJ_READ] = DefDispatchRoutine;
    pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IoctlDispatchRoutine;

    NTSTATUS status;
    PDEVICE_OBJECT pDevObj;
    PDEVICE_EXTENSION pDevExt;

    //创建设备名称的字符串
    UNICODE_STRING devName;
    RtlInitUnicodeString(&devName, L"\\Device\\MyDevice");
    //创建设备
    status = IoCreateDevice(pDriverObject, sizeof(DEVICE_EXTENSION), &devName, FILE_DEVICE_UNKNOWN, 0, TRUE, &pDevObj);
    pDevObj->Flags |= DO_BUFFERED_IO;//将设备设置为缓冲I/O设备
    pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;//得到设备扩展

    //创建符号链接
    UNICODE_STRING symLinkName;
    RtlInitUnicodeString(&symLinkName, L"\\??\\MyDevice");
    pDevExt->SymLinkName = symLinkName;
    status = IoCreateSymbolicLink(&symLinkName, &devName);
    return STATUS_SUCCESS;
}

客户端

#include "stdafx.h"
#include<Windows.h>
// 自定义的控制信号
#define My_Code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)

typedef struct Hread {
    ULONG Flage;
    ULONG Addr;
    ULONG WriteBufferAddr;
    ULONG Size;
    ULONG Pid;
}_Hread, *PtrHread;

int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE handle = CreateFileA("\\\\.\\MyDevice", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

    unsigned char RetBufferData[20] = { 0 };
    DWORD ReturnLength = 4;
    _Hread buf;

    buf.Flage = 2;
    buf.Addr = 0x401234;
    buf.WriteBufferAddr = 1024;
    buf.Size = 100;
    buf.Pid = 2566;

    DeviceIoControl(handle, My_Code, &buf, 20, (LPVOID)RetBufferData, 4, &ReturnLength, 0);
    printf("返回的数据: %s", RetBufferData);

    getchar();
    CloseHandle(handle);
    return 0;
}

驱动读写操作: 网上找到一个驱动读写相关的案例,看着不错这里就转过来啦,我就不自己写了。

这个驱动读写转载于:https://blog.csdn.net/weixin_44286745

服务端:

#pragma once
#include<ntifs.h>
#include<windef.h>

#define READCODE CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ALL_ACCESS)
#define WRITECODE CTL_CODE(FILE_DEVICE_UNKNOWN,0x801,METHOD_BUFFERED,FILE_ALL_ACCESS)

#define DEVICENAME L"\\Device\\ReadWriteDevice"
#define SYMBOLNAME L"\\??\\ReadWriteSymbolName"

typedef struct DATA
{
    DWORD pid;//要读写的进程ID
    unsigned __int64 address;//要读写的地址
    DWORD size;//读写长度
    BYTE* data;//要读写的数据,
}Data;

void DriverUnload(PDRIVER_OBJECT driver)
{

    if (driver->DeviceObject)
    {
        UNICODE_STRING SymbolName;
        RtlInitUnicodeString(&SymbolName, SYMBOLNAME);

        IoDeleteSymbolicLink(&SymbolName);
        IoDeleteDevice(driver->DeviceObject);
    }

    DbgPrint("驱动已卸载");
}

NTSTATUS CreateDevice(PDRIVER_OBJECT driver)
{
    NTSTATUS status = STATUS_SUCCESS;
    PDEVICE_OBJECT device = NULL;
    UNICODE_STRING DeviceName;

    RtlInitUnicodeString(&DeviceName, DEVICENAME);

    status = IoCreateDevice(
        driver,
        sizeof(driver->DriverExtension),
        &DeviceName,
        FILE_DEVICE_UNKNOWN,
        FILE_DEVICE_SECURE_OPEN,
        FALSE,
        &device
        );

    if (status == STATUS_SUCCESS)
    {
        UNICODE_STRING SymbolName;
        RtlInitUnicodeString(&SymbolName, SYMBOLNAME);

        status = IoCreateSymbolicLink(&SymbolName, &DeviceName);

        if (status != STATUS_SUCCESS)
        {
            DbgPrint("创建符号链接失败");
            IoDeleteDevice(device);
        }
    }
    DbgPrint("驱动设备已创建");
    return status;
}


BOOL ReadMemory(Data* data)
{
    BOOL bRet = TRUE;
    PEPROCESS process = NULL;

    PsLookupProcessByProcessId(data->pid, &process);

    if (process == NULL)
    {
        DbgPrint("获取进程对象失败");
        return FALSE;
    }

    BYTE* GetData;
    __try
    {
        GetData = ExAllocatePool(PagedPool, data->size);
    }
    __except (1)
    {
        DbgPrint("内存分配失败");
        return FALSE;
    }

    KAPC_STATE stack = { 0 };
    KeStackAttachProcess(process, &stack);

    __try
    {
        ProbeForRead(data->address, data->size, 1);
        RtlCopyMemory(GetData, data->address, data->size);
    }
    __except (1)
    {
        DbgPrint("读取内存出错");
        bRet = FALSE;
    }

    ObDereferenceObject(process);
    KeUnstackDetachProcess(&stack);
    RtlCopyMemory(data->data, GetData, data->size);
    ExFreePool(GetData);
    return bRet;
}

BOOL WriteMemory(Data* data)
{
    BOOL bRet = TRUE;
    PEPROCESS process = NULL;

    PsLookupProcessByProcessId(data->pid, &process);
    if (process == NULL)
    {
        DbgPrint("获取进程对象失败");
        return FALSE;
    }

    //在进入进程地址空间之前先赋值
    BYTE* GetData;
    __try
    {
        GetData = ExAllocatePool(PagedPool, data->size);
    }
    __except (1)
    {
        DbgPrint("内存分配失败");
        return FALSE;
    }

    for (int i = 0; i < data->size; i++)
    {
        GetData[i] = data->data[i];
    }

    KAPC_STATE stack = { 0 };
    KeStackAttachProcess(process, &stack);

    PMDL mdl = IoAllocateMdl(data->address, data->size, 0, 0, NULL);
    if (mdl == NULL)
    {
        DbgPrint("创建MDL失败");
        return FALSE;
    }

    MmBuildMdlForNonPagedPool(mdl);

    BYTE* ChangeData = NULL;

    __try
    {
        ChangeData = MmMapLockedPages(mdl, KernelMode);
        RtlCopyMemory(ChangeData, GetData, data->size);
    }
    __except (1)
    {
        DbgPrint("内存映射失败,%d", sizeof(ChangeData));
        bRet = FALSE;
        goto END;
    }

END:
    IoFreeMdl(mdl);
    ExFreePool(GetData);
    KeUnstackDetachProcess(&stack);
    ObDereferenceObject(process);

    return bRet;
}

NTSTATUS DriverIrpCtl(PDEVICE_OBJECT device, PIRP pirp)
{
    PIO_STACK_LOCATION stack;
    stack = IoGetCurrentIrpStackLocation(pirp);
    Data* data;

    switch (stack->MajorFunction)
    {

    case IRP_MJ_CREATE:
    {
                          DbgPrint("设备已打开");
                          break;
    }

    case IRP_MJ_CLOSE:
    {
                         DbgPrint("设备已关闭");
                         break;
    }

    case IRP_MJ_DEVICE_CONTROL:
    {
                                  data = pirp->AssociatedIrp.SystemBuffer;
                                  DbgPrint("PID:%d  地址:%x  大小:%d", data->pid, data->address, data->size);
                                  switch (stack->Parameters.DeviceIoControl.IoControlCode)
                                  {

                                  case READCODE:
                                  {
                                                   ReadMemory(data);
                                                   break;
                                  }

                                  case WRITECODE:
                                  {
                                                    WriteMemory(data);
                                                    break;
                                  }

                                  }

                                  pirp->IoStatus.Information = sizeof(data);

                                  break;
    }

    }

    pirp->IoStatus.Status = STATUS_SUCCESS;
    IoCompleteRequest(pirp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING path)
{
    DbgPrint("驱动已加载,路径:%wZ", path);

    driver->DriverUnload = DriverUnload;

    CreateDevice(driver);

    driver->MajorFunction[IRP_MJ_CREATE] = DriverIrpCtl;
    driver->MajorFunction[IRP_MJ_CLOSE] = DriverIrpCtl;
    driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DriverIrpCtl;

    return STATUS_SUCCESS;
}

客户端:

#include "stdafx.h"
#include<Windows.h>
#include <string.h>

#define READCODE CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ALL_ACCESS)
#define WRITECODE CTL_CODE(FILE_DEVICE_UNKNOWN,0x801,METHOD_BUFFERED,FILE_ALL_ACCESS)

typedef struct DATA
{
    DWORD pid;//要读写的进程ID
    unsigned __int64 address;//要读写的地址
    DWORD size;//读写长度
    BYTE* data;//要读写的数据,
}Data;

/*  驱动内存写入,如下
Data data;
data.pid = GetDlgItemInt(IDC_EDIT_PID);
data.address = GetDlgItemInt(IDC_EDIT_address);
data.size = GetDlgItemInt(IDC_EDIT_Size);
data.data = new BYTE[data.size];

for (int i = 0; i < data.size; i++)
{
    data.data[i] = 90909090;   // 写入Nop指令
}

DWORD dwSize = 0;
DeviceIoControl(DeviceHandle,WRITECODE,&data,sizeof(data),&data,sizeof(data),&dwSize,NULL);
delete[] data.data;
*/

int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE handle = CreateFileA("\\??\\ReadWriteSymbolName", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

    Data data;
    DWORD dwSize = 0;

    data.pid = 908;
    data.address = 4198400;
    data.size = 4;
    
    data.data = new BYTE[data.size];
    DeviceIoControl(handle, READCODE, &data, sizeof(data), &data, sizeof(data), &dwSize, NULL);
    for (int i = 0; i < data.size; i++)
    {
        printf("%x", data.data[i]);
    }

    getchar();
    CloseHandle(handle);
    return 0;
}

上方的代码,经过修改后可以正常完成编译链接,并读出内存数据。

1379525-20190928075815990-1927849784.png

转载于:https://www.cnblogs.com/LyShark/p/11570449.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值