首页
社区
课程
招聘
[原创]驱动通信基础
发表于: 2024-11-29 23:29 2987

[原创]驱动通信基础

2024-11-29 23:29
2987

驱动本身无法进行通信,通信一般是通过设备进行通信,设备对象是挂在驱动对象下的,一个驱动对象可以创建多个设备对象
图片描述

存在两个设备类型,一个是Type,一个是DeviceType
- Type:描述对象的基本类型
- DeviceType:描述设备的具体类型
NextDevice,通过该设备对象指向下一个设备对象,所以在驱动下的设备对象也是一个链表结构,并且该链表为单向链表,最后一个设备对象的NextDevice为空,而对于AttachedDevice,首先需要明确设备对象也有区分,一个是FDO过滤设备对象,一个是PDO物理设备对象,该对象是对硬件的一个抽象,通过该抽象可以控制设备
而内核驱动中对于PDO的通信都会先通过FDO,由FDO决定消息是否往PDO发送,而FDO可能有多个:
图片描述
CurrentIrp指向当前设备的IRP,IRP为Io Request Package ,理解为Web的POST和GET包即可,具体参数通过实验再一步步了解

通过IoCreateDevice创建设备对象:https://learn.microsoft.com/zh-cn/windows-hardware/drivers/ddi/wdm/nf-wdm-iocreatedevice

设备类型,总共是0x5D种类型,大部分类型针对到具体的设备,在wdm.h中具有所有DEVICE_TYPE的枚举定义,这里我们直接用FILE_DEVICE_UNKNOWN

设备属性在DEVICE_OBJECT中有定义,一般创建的虚拟对象选择FILE_DEVICE_SECURE_OPEN即可:
图片描述
Exclusive:根据文档提示直接设置成FALSE即可
图片描述
此时就能成功创建一个设备了:

但此时创建的设备还无法被三环下的程序进行访问,还需要通过一个符号链接将设备的接口暴露给三环,通过IoCreateSymbolicLink绑定设备

在某些系统下,创建完设备后需要将标志位上的初始化去掉,并且设置通信方式:

当完成以上操作后,此时还需要一个派遣函数,来处理接收到的消息:

在驱动对象的最后一组参数中:

跟进看到所有的IRP功能号的枚举值:

该函数中指向的是驱动的派遣函数,可以将每个功能号都对应一个派遣函数,在正式开发中,对每个功能编写一个派遣函数是最佳选择,在该测试中,可以将所有的功能号都指向同一个派遣函数:

主要通信方式:

在驱动对象的MajorFunction中的下标跟功能号的枚举值是一一对应的,所以也可以不用对所有的功能号都填充派遣函数,仅填充基础通信的派遣函数即可:

对IRP_MJ_CREATE和IRP_MJ_CLOSE定义一个派遣函数,只需要将IoStatus的状态设置成STATUS_SUCCESS即可,调用IoCompeleteRequest表示IRP请求已完成:

处理请求的第一步是获得请求的当前栈空间(Current Stack Location),可以通过IoGetCurrentIrpStackLocation获得,判断功能号后(一般如果在前面设置了对应功能号的派遣函数,此时没必要再判断,这里为了严谨性可以重复判断一下功能号是不是对应的),获取Parameters,该参数是一个联合体,对于不同的功能号都有不同的结构体,当前的功能号为IRP_MJ_DEVICE_CONTROL,对应的联合体结构为DeviceIoControl该结构体不需要手动定义,在wdm.h中已定义

IoControlCode控制码的定义:

需要传入四个参数:

启动驱动后,再运行应用层程序,此时程序就获取到IRP包后断下,可以看到创建的设备对象,此时的驱动对象指向的第一个设备对象就是创建的设备对象,StackSize=1,说明没有其他设备附加到当前设备对象上,只有设备对象本身,驱动对象跟设备对象此时就是互相引用的状态:
图片描述
dt Irp -r1展开一层查看IRP请求包:
图片描述
此时成功将R3的数据传入到0环中:
图片描述
图片描述
以上为Ring3到Ring0的数据传输,还有Ring0-Ring3的数据传输,也是类似的,通过DeviceIoControl设置lpOutBuffer和nOutBufferSize即可:
应用层:

驱动层:

图片描述
图片描述
注意到此时的SystemBuffer的地址3环是不可读不可写的,对比前面ring3到ring0的读取操作,当从ring0往ring3写数据时,多了一块UserBuffer的空间,该空间就是3环下读取ring0写入的地址,也就是说会将SystemBuffer中的值复制一份到Userbuffer:
图片描述
此时UserBuffer中的值还是空,说明此时仅开辟了空间未做内存复制,通过ba对该地址下硬件断点:
图片描述

当下完断点运行时,可以在IoCompleteRequest的时候断下,此时会根据IoStatus.Information的值,将SystemBuffer的值赋值到UserBuffer中,通过bc *清除硬件断点,输出结果:
图片描述
图片描述

前面提到过,在0环下的栈空间只有12KB,而3环下有1MB,此时如果将1MB的数据从3环传到0环,就会直接蓝屏
可以通过一个链表存储从应用层接收的字符串:

分配内存并初始化一个链表节点:

在前面的代码中可以发现存在ASSERT断言,需要注意断言是不能作为正式版使用,仅在开发调试中使用,所以需要手动做缓冲区长度检查:

安全检查的原则之一就是越简单越好
当前面做了输入长度的限制,攻击者可使用的缓冲区攻击的长度就从无限大急剧缩小到512字节
输入缓冲区的长度即使是正确,也需要对内容做检查
使用strlen内容检查往往是不正确,因为strlen是以\\0 为结束符,攻击者只需要构造没有\\0的字符串,strlen则会一直找下去,这很有可能导致异常。
所以可以使用strnlen检查字符串长度,因为其存在一个最大限度,超过限度便不会继续搜索结束符

字符串拷贝出于安全考虑,也需要用strncpy替代strcpy

以上是对于输入处理,输出也需要进行处理,同样需要通过缓冲区:

通过while死循环做等待会浪费CPU资源,所以此时需要用到事件:

到这里基本输入输出就完成了,然后需要注意链表节点结构需要卸载:

实际的运用中,DeviceIoControl容易被检测,只需要获取到驱动对象,通过驱动对象找到IRP_MJ_DEVICE_CONTROL下的派遣函数就能进行检测,所以利用IRP_MJ_READIRP_MJ_WRITE更容易绕过检测

同样,需要针对IRP_MJ_CREATEIRP_MJ_CLOSE编写通用派遣函数:

在DeviceIoControl中有IoControlCode,此时不需要再定义IoControlCode,通过IO_STACK_LOCATION查看Read和Write的结构:

在3环中通过ReadFile和WriteFile进行读写,需要注意
ReadFile对应IRP_MJ_READ,此时是Ring3从Ring0读数据
WriteFile对应IRP_MJ_WRITE,此时是Ring3写数据到Ring0

对应的驱动层代码:

图片描述

typedef struct _DEVICE_OBJECT {
  CSHORT                   Type; // 设备类型
  USHORT                   Size; // 设备大小
  LONG                     ReferenceCount;
  struct _DRIVER_OBJECT    *DriverObject; // 由哪个驱动对象创建
  struct _DEVICE_OBJECT    *NextDevice; //下一个设备对象
  struct _DEVICE_OBJECT    *AttachedDevice; // 附加设备对象
  struct _IRP              *CurrentIrp; // 当前设备对象指向的IRP请求包
  PIO_TIMER                Timer; // 定时器
  ULONG                    Flags;
  ULONG                    Characteristics; // 设备属性
  __volatile PVPB          Vpb;
  PVOID                    DeviceExtension;
  DEVICE_TYPE              DeviceType; // 设备具体类型
  CCHAR                    StackSize;
  union {
    LIST_ENTRY         ListEntry; // 插入LIST_ENTRY,使DeivceObject称为链表结构
    WAIT_CONTEXT_BLOCK Wcb;
  } Queue;
  ULONG                    AlignmentRequirement;
  KDEVICE_QUEUE            DeviceQueue;
  KDPC                     Dpc;
  ULONG                    ActiveThreadCount;
  PSECURITY_DESCRIPTOR     SecurityDescriptor; // 安全描述符
  KEVENT                   DeviceLock;
  USHORT                   SectorSize;
  USHORT                   Spare1;
  struct _DEVOBJ_EXTENSION *DeviceObjectExtension;
  PVOID                    Reserved;
} DEVICE_OBJECT, *PDEVICE_OBJECT;
typedef struct _DEVICE_OBJECT {
  CSHORT                   Type; // 设备类型
  USHORT                   Size; // 设备大小
  LONG                     ReferenceCount;
  struct _DRIVER_OBJECT    *DriverObject; // 由哪个驱动对象创建
  struct _DEVICE_OBJECT    *NextDevice; //下一个设备对象
  struct _DEVICE_OBJECT    *AttachedDevice; // 附加设备对象
  struct _IRP              *CurrentIrp; // 当前设备对象指向的IRP请求包
  PIO_TIMER                Timer; // 定时器
  ULONG                    Flags;
  ULONG                    Characteristics; // 设备属性
  __volatile PVPB          Vpb;
  PVOID                    DeviceExtension;
  DEVICE_TYPE              DeviceType; // 设备具体类型
  CCHAR                    StackSize;
  union {
    LIST_ENTRY         ListEntry; // 插入LIST_ENTRY,使DeivceObject称为链表结构
    WAIT_CONTEXT_BLOCK Wcb;
  } Queue;
  ULONG                    AlignmentRequirement;
  KDEVICE_QUEUE            DeviceQueue;
  KDPC                     Dpc;
  ULONG                    ActiveThreadCount;
  PSECURITY_DESCRIPTOR     SecurityDescriptor; // 安全描述符
  KEVENT                   DeviceLock;
  USHORT                   SectorSize;
  USHORT                   Spare1;
  struct _DEVOBJ_EXTENSION *DeviceObjectExtension;
  PVOID                    Reserved;
} DEVICE_OBJECT, *PDEVICE_OBJECT;
nt!_IRP
   +0x000 Type             : Int2B
   +0x002 Size             : Uint2B
   +0x004 MdlAddress       : Ptr32 _MDL
   +0x008 Flags            : Uint4B
   +0x00c AssociatedIrp    : <unnamed-tag>
   +0x010 ThreadListEntry  : _LIST_ENTRY
   +0x018 IoStatus         : _IO_STATUS_BLOCK
   +0x020 RequestorMode    : Char
   +0x021 PendingReturned  : UChar
   +0x022 StackCount       : Char // 设备栈的数量
   +0x023 CurrentLocation  : Char // 当前设备栈的索引
   +0x024 Cancel           : UChar
   +0x025 CancelIrql       : UChar
   +0x026 ApcEnvironment   : Char
   +0x027 AllocationFlags  : UChar
   +0x028 UserIosb         : Ptr32 _IO_STATUS_BLOCK
   +0x02c UserEvent        : Ptr32 _KEVENT
   +0x030 Overlay          : <unnamed-tag>
   +0x038 CancelRoutine    : Ptr32     void
   +0x03c UserBuffer       : Ptr32 Void
   +0x040 Tail             : <unnamed-tag>
nt!_IRP
   +0x000 Type             : Int2B
   +0x002 Size             : Uint2B
   +0x004 MdlAddress       : Ptr32 _MDL
   +0x008 Flags            : Uint4B
   +0x00c AssociatedIrp    : <unnamed-tag>
   +0x010 ThreadListEntry  : _LIST_ENTRY
   +0x018 IoStatus         : _IO_STATUS_BLOCK
   +0x020 RequestorMode    : Char
   +0x021 PendingReturned  : UChar
   +0x022 StackCount       : Char // 设备栈的数量
   +0x023 CurrentLocation  : Char // 当前设备栈的索引
   +0x024 Cancel           : UChar
   +0x025 CancelIrql       : UChar
   +0x026 ApcEnvironment   : Char
   +0x027 AllocationFlags  : UChar
   +0x028 UserIosb         : Ptr32 _IO_STATUS_BLOCK
   +0x02c UserEvent        : Ptr32 _KEVENT
   +0x030 Overlay          : <unnamed-tag>
   +0x038 CancelRoutine    : Ptr32     void
   +0x03c UserBuffer       : Ptr32 Void
   +0x040 Tail             : <unnamed-tag>
NTSTATUS
IoCreateDevice(
    _In_  PDRIVER_OBJECT DriverObject, // 指向的驱动对象
    _In_  ULONG DeviceExtensionSize, // 设备扩展内存,如有会分配对应字节的空间
    _In_opt_ PUNICODE_STRING DeviceName, // 设备名称
    _In_  DEVICE_TYPE DeviceType, // 设备类型
    _In_  ULONG DeviceCharacteristics, // 设备属性
    _In_  BOOLEAN Exclusive,
    _Outptr_result_nullonfailure_
    _At_(*DeviceObject,
        __drv_allocatesMem(Mem)
        _When_((((_In_function_class_(DRIVER_INITIALIZE))
               ||(_In_function_class_(DRIVER_DISPATCH)))),
             __drv_aliasesMem))
    PDEVICE_OBJECT *DeviceObject
    );
NTSTATUS
IoCreateDevice(
    _In_  PDRIVER_OBJECT DriverObject, // 指向的驱动对象
    _In_  ULONG DeviceExtensionSize, // 设备扩展内存,如有会分配对应字节的空间
    _In_opt_ PUNICODE_STRING DeviceName, // 设备名称
    _In_  DEVICE_TYPE DeviceType, // 设备类型
    _In_  ULONG DeviceCharacteristics, // 设备属性
    _In_  BOOLEAN Exclusive,
    _Outptr_result_nullonfailure_
    _At_(*DeviceObject,
        __drv_allocatesMem(Mem)
        _When_((((_In_function_class_(DRIVER_INITIALIZE))
               ||(_In_function_class_(DRIVER_DISPATCH)))),
             __drv_aliasesMem))
    PDEVICE_OBJECT *DeviceObject
    );
#define FILE_DEVICE_BEEP                0x00000001
#define FILE_DEVICE_CD_ROM              0x00000002
#define FILE_DEVICE_CD_ROM_FILE_SYSTEM  0x00000003
......
#define FILE_DEVICE_UNKNOWN             0x00000022
......
#define FILE_DEVICE_PERSISTENT_MEMORY   0x00000059
#define FILE_DEVICE_NVDIMM              0x0000005a
#define FILE_DEVICE_HOLOGRAPHIC         0x0000005b
#define FILE_DEVICE_SDFXHCI             0x0000005c
#define FILE_DEVICE_UCMUCSI             0x0000005d
#define FILE_DEVICE_BEEP                0x00000001
#define FILE_DEVICE_CD_ROM              0x00000002
#define FILE_DEVICE_CD_ROM_FILE_SYSTEM  0x00000003
......
#define FILE_DEVICE_UNKNOWN             0x00000022
......
#define FILE_DEVICE_PERSISTENT_MEMORY   0x00000059
#define FILE_DEVICE_NVDIMM              0x0000005a
#define FILE_DEVICE_HOLOGRAPHIC         0x0000005b
#define FILE_DEVICE_SDFXHCI             0x0000005c
#define FILE_DEVICE_UCMUCSI             0x0000005d
UNICODE_STRING deviceName = { 0 };
RtlInitUnicodeString(&deviceName, DEVICE_NAME);
 
PDEVICE_OBJECT pDevice = NULL;
 
NTSTATUS status = IoCreateDevice(
    pDriver,
    0,
    &deviceName,
    FILE_DEVICE_UNKNOWN,
    FILE_DEVICE_SECURE_OPEN,
    FALSE,
    pDevice
);
 
if (NT_SUCCESS(status)) {
    KdPrintEx((77, 0, "res: %x\r\n", status));
    return status;
}
UNICODE_STRING deviceName = { 0 };
RtlInitUnicodeString(&deviceName, DEVICE_NAME);
 
PDEVICE_OBJECT pDevice = NULL;
 
NTSTATUS status = IoCreateDevice(
    pDriver,
    0,
    &deviceName,
    FILE_DEVICE_UNKNOWN,
    FILE_DEVICE_SECURE_OPEN,
    FALSE,
    pDevice
);
 
if (NT_SUCCESS(status)) {
    KdPrintEx((77, 0, "res: %x\r\n", status));
    return status;
}
#define SYM_NAME L"\\??\\TestDevice"
UNICODE_STRING symName = { 0 };
RtlInitUnicodeString(&symName, SYM_NAME);
 
// 绑定符号链接
status = IoCreateSymbolicLink(&symName, &deviceName);
 
if (!NT_SUCCESS(status)) {
    IoDeleteDevice(pDevice);
    KdPrintEx((77, 0, "res: %x\r\n", status));
    return status;
}
#define SYM_NAME L"\\??\\TestDevice"
UNICODE_STRING symName = { 0 };
RtlInitUnicodeString(&symName, SYM_NAME);
 
// 绑定符号链接
status = IoCreateSymbolicLink(&symName, &deviceName);
 
if (!NT_SUCCESS(status)) {
    IoDeleteDevice(pDevice);
    KdPrintEx((77, 0, "res: %x\r\n", status));
    return status;
}
pDevice->Flags &= ~DO_DEVICE_INITIALIZING;
pDevice->Flags |= DO_BUFFERED_IO;
pDevice->Flags &= ~DO_DEVICE_INITIALIZING;
pDevice->Flags |= DO_BUFFERED_IO;
NTSTATUS dispatch(
    IN PDEVICE_OBJECT dev,
    IN PIRP irp
);
NTSTATUS dispatch(
    IN PDEVICE_OBJECT dev,
    IN PIRP irp
);
PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];
PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];
#define IRP_MJ_CREATE                   0x00
#define IRP_MJ_CREATE_NAMED_PIPE        0x01
#define IRP_MJ_CLOSE                    0x02
#define IRP_MJ_READ                     0x03
#define IRP_MJ_WRITE                    0x04
#define IRP_MJ_QUERY_INFORMATION        0x05
#define IRP_MJ_SET_INFORMATION          0x06
#define IRP_MJ_QUERY_EA                 0x07
#define IRP_MJ_SET_EA                   0x08
#define IRP_MJ_FLUSH_BUFFERS            0x09
#define IRP_MJ_QUERY_VOLUME_INFORMATION 0x0a
#define IRP_MJ_SET_VOLUME_INFORMATION   0x0b
#define IRP_MJ_DIRECTORY_CONTROL        0x0c
#define IRP_MJ_FILE_SYSTEM_CONTROL      0x0d
#define IRP_MJ_DEVICE_CONTROL           0x0e
#define IRP_MJ_INTERNAL_DEVICE_CONTROL  0x0f
#define IRP_MJ_SHUTDOWN                 0x10
#define IRP_MJ_LOCK_CONTROL             0x11
#define IRP_MJ_CLEANUP                  0x12
#define IRP_MJ_CREATE_MAILSLOT          0x13
#define IRP_MJ_QUERY_SECURITY           0x14
#define IRP_MJ_SET_SECURITY             0x15
#define IRP_MJ_POWER                    0x16
#define IRP_MJ_SYSTEM_CONTROL           0x17
#define IRP_MJ_DEVICE_CHANGE            0x18
#define IRP_MJ_QUERY_QUOTA              0x19
#define IRP_MJ_SET_QUOTA                0x1a
#define IRP_MJ_PNP                      0x1b
#define IRP_MJ_PNP_POWER                IRP_MJ_PNP      // Obsolete....
#define IRP_MJ_MAXIMUM_FUNCTION         0x1b
#define IRP_MJ_CREATE                   0x00
#define IRP_MJ_CREATE_NAMED_PIPE        0x01
#define IRP_MJ_CLOSE                    0x02
#define IRP_MJ_READ                     0x03
#define IRP_MJ_WRITE                    0x04
#define IRP_MJ_QUERY_INFORMATION        0x05
#define IRP_MJ_SET_INFORMATION          0x06
#define IRP_MJ_QUERY_EA                 0x07
#define IRP_MJ_SET_EA                   0x08
#define IRP_MJ_FLUSH_BUFFERS            0x09
#define IRP_MJ_QUERY_VOLUME_INFORMATION 0x0a
#define IRP_MJ_SET_VOLUME_INFORMATION   0x0b
#define IRP_MJ_DIRECTORY_CONTROL        0x0c
#define IRP_MJ_FILE_SYSTEM_CONTROL      0x0d
#define IRP_MJ_DEVICE_CONTROL           0x0e
#define IRP_MJ_INTERNAL_DEVICE_CONTROL  0x0f
#define IRP_MJ_SHUTDOWN                 0x10
#define IRP_MJ_LOCK_CONTROL             0x11
#define IRP_MJ_CLEANUP                  0x12
#define IRP_MJ_CREATE_MAILSLOT          0x13
#define IRP_MJ_QUERY_SECURITY           0x14
#define IRP_MJ_SET_SECURITY             0x15
#define IRP_MJ_POWER                    0x16
#define IRP_MJ_SYSTEM_CONTROL           0x17
#define IRP_MJ_DEVICE_CHANGE            0x18
#define IRP_MJ_QUERY_QUOTA              0x19
#define IRP_MJ_SET_QUOTA                0x1a
#define IRP_MJ_PNP                      0x1b
#define IRP_MJ_PNP_POWER                IRP_MJ_PNP      // Obsolete....
#define IRP_MJ_MAXIMUM_FUNCTION         0x1b
for (int i = 0; i < IRP_MJ_MAXIMUN_FUNCTION; i++) {
    driver->MajorFunction[i] = testDispatch;
}
for (int i = 0; i < IRP_MJ_MAXIMUN_FUNCTION; i++) {
    driver->MajorFunction[i] = testDispatch;
}
// 读写的方式
#define IRP_MJ_READ                     0x03
#define IRP_MJ_WRITE                    0x04
 
// 设备IO的方式
#define IRP_MJ_DEVICE_CONTROL           0x0e
// 读写的方式
#define IRP_MJ_READ                     0x03
#define IRP_MJ_WRITE                    0x04
 
// 设备IO的方式
#define IRP_MJ_DEVICE_CONTROL           0x0e
#define IRP_MJ_CREATE                   0x00
#define IRP_MJ_CLOSE                    0x02
#define IRP_MJ_DEVICE_CONTROL           0x0e
 
 
pDriver->MajorFunction[IRP_MJ_CREATE] = InitDispatch;
pDriver->MajorFunction[IRP_MJ_CLOSE] = InitDispatch;
pDriver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = TestDispatch;
#define IRP_MJ_CREATE                   0x00
#define IRP_MJ_CLOSE                    0x02
#define IRP_MJ_DEVICE_CONTROL           0x0e
 
 
pDriver->MajorFunction[IRP_MJ_CREATE] = InitDispatch;
pDriver->MajorFunction[IRP_MJ_CLOSE] = InitDispatch;
pDriver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = TestDispatch;
NTSTATUS InitDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
    NTSTATUS status = STATUS_SUCCESS;
    ULONG retLen = 0;
    Irp->IoStatus.Status = status;
    Irp->IoStatus.Information = retLen;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return status;
}
NTSTATUS InitDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
    NTSTATUS status = STATUS_SUCCESS;
    ULONG retLen = 0;
    Irp->IoStatus.Status = status;
    Irp->IoStatus.Information = retLen;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return status;
}
struct {
    ULONG OutputBufferLengSth;
    ULONG POINTER_ALIGNMENT InputBufferLength;
    ULONG POINTER_ALIGNMENT IoControlCode;
    PVOID Type3InputBuffer;
} DeviceIoControl;
 
NTSTATUS TestDispatch(
    PDEVICE_OBJECT DeviceObject,
    PIRP Irp
) {
    PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp); // 获取IRP的栈空间
    NTSTATUS status = STATUS_SUCCESS;
    ULONG retLen = 0;
    DbgBreakPoint();
    if (ioStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) {
        PVOID buffer = Irp->AssociatedIrp.SystemBuffer; // 获取从3环输入Buffer
        ULONG inlen = ioStack->Parameters.DeviceIoControl.InputBufferLength; // 获取3环传入的字节数
        ULONG outlen = ioStack->Parameters.DeviceIoControl.OutputBufferLength; // 获取可传回3环的字节数
    switch (IoControlCode) {
        case TEST_CODE:
        {
            int* buffer = (int*)Irp->AssociatedIrp.SystemBuffer; // 读取3环传入的字符串
            KdPrintEx((77, 0, "[db]: %x\r\n", *buffer));
            break;
        }
    }
}
struct {
    ULONG OutputBufferLengSth;
    ULONG POINTER_ALIGNMENT InputBufferLength;
    ULONG POINTER_ALIGNMENT IoControlCode;
    PVOID Type3InputBuffer;
} DeviceIoControl;
 
NTSTATUS TestDispatch(
    PDEVICE_OBJECT DeviceObject,
    PIRP Irp
) {
    PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp); // 获取IRP的栈空间
    NTSTATUS status = STATUS_SUCCESS;
    ULONG retLen = 0;
    DbgBreakPoint();
    if (ioStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) {
        PVOID buffer = Irp->AssociatedIrp.SystemBuffer; // 获取从3环输入Buffer
        ULONG inlen = ioStack->Parameters.DeviceIoControl.InputBufferLength; // 获取3环传入的字节数
        ULONG outlen = ioStack->Parameters.DeviceIoControl.OutputBufferLength; // 获取可传回3环的字节数
    switch (IoControlCode) {
        case TEST_CODE:
        {
            int* buffer = (int*)Irp->AssociatedIrp.SystemBuffer; // 读取3环传入的字符串
            KdPrintEx((77, 0, "[db]: %x\r\n", *buffer));
            break;
        }
    }
}
#define CTL_CODE( DeviceType, Function, Method, Access ) (                 \
    ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
)
#define CTL_CODE( DeviceType, Function, Method, Access ) (                 \
    ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
)
#define CODE_CTR_INDEX 0x800
#define TEST_CODE CTL_CODE(FILE_DEVICE_UNKNOWN, CODE_CTR_INDEX, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define CODE_CTR_INDEX 0x800
#define TEST_CODE CTL_CODE(FILE_DEVICE_UNKNOWN, CODE_CTR_INDEX, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define TEST_R0TOR3_CODE (ULONG)CTL_CODE(FILE_DEVICE_UNKNOWN, CRL_CODE_INDEX+1, METHOD_BUFFERED, FILE_ANY_ACCESS)
 
 
void receiveMessage() {
    HANDLE pDevice = OpenDevice();
 
    int ret = 0;
    ULONG retLen = 0;
 
    BOOLEAN res = DeviceIoControl(pDevice, TEST_R0TOR3_CODE, NULL, NULL, &ret, sizeof(ULONG), &retLen, NULL);
    if (!res) {
        printf("[db] Receive Message Failed..\r\n");
        CloseHandle(pDevice);
    }
 
    printf("[db] Receive Message From Ring0: %x\r\n", ret);
}
#define TEST_R0TOR3_CODE (ULONG)CTL_CODE(FILE_DEVICE_UNKNOWN, CRL_CODE_INDEX+1, METHOD_BUFFERED, FILE_ANY_ACCESS)
 
 
void receiveMessage() {
    HANDLE pDevice = OpenDevice();
 
    int ret = 0;
    ULONG retLen = 0;
 
    BOOLEAN res = DeviceIoControl(pDevice, TEST_R0TOR3_CODE, NULL, NULL, &ret, sizeof(ULONG), &retLen, NULL);
    if (!res) {
        printf("[db] Receive Message Failed..\r\n");
        CloseHandle(pDevice);
    }
 
    printf("[db] Receive Message From Ring0: %x\r\n", ret);
}
switch (ioStack->Parameters.DeviceIoControl.IoControlCode) {
    case TEST_R3TOR0_CODE:
    {
        // receive Message
        KdPrintEx((77, 0, "[db]:%s\r\n", buffer));
        break;
    }
    case TEST_R0TOR3_CODE:
    {
        // send Message
        ULONG x = 2000;
        memcpy(buffer, &x, outlen);
        Irp->IoStatus.Information = outlen;
        break;
    }
    default:
        status = STATUS_INVALID_PARAMETER;
        break;
}
switch (ioStack->Parameters.DeviceIoControl.IoControlCode) {
    case TEST_R3TOR0_CODE:
    {
        // receive Message
        KdPrintEx((77, 0, "[db]:%s\r\n", buffer));
        break;
    }
    case TEST_R0TOR3_CODE:
    {
        // send Message
        ULONG x = 2000;
        memcpy(buffer, &x, outlen);
        Irp->IoStatus.Information = outlen;
        break;
    }
    default:
        status = STATUS_INVALID_PARAMETER;
        break;
}
ba w4 0x0015fb2c
ba w4 0x0015fb2c
#include <ntifs.h>
 
#define CRL_CODE_INDEX 0x800
#define TEST_R3TOR0_CODE (ULONG)CTL_CODE(FILE_DEVICE_UNKNOWN, CRL_CODE_INDEX, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define TEST_R0TOR3_CODE (ULONG)CTL_CODE(FILE_DEVICE_UNKNOWN, CRL_CODE_INDEX+1, METHOD_BUFFERED, FILE_ANY_ACCESS)
 
#define CDO_NAME L"\\Device\\TestDevice2"
#define SYM_NAME L"\\??\\TestDevice2"
 
PDEVICE_OBJECT pDevice = NULL;
 
NTSTATUS TestCreateCDO(PDRIVER_OBJECT pDriver) {
    UNICODE_STRING cdoName = RTL_CONSTANT_STRING(CDO_NAME);
    NTSTATUS status = IoCreateDevice(
        pDriver,
        0,
        &cdoName,
        FILE_DEVICE_UNKNOWN,
        FILE_DEVICE_SECURE_OPEN,
        FALSE,
        &pDevice
    );
 
    return status;
}
 
NTSTATUS TestCreateSymbolicLink(PDRIVER_OBJECT drvier) {
    UNICODE_STRING cdoName = RTL_CONSTANT_STRING(CDO_NAME);
    UNICODE_STRING symName = RTL_CONSTANT_STRING(SYM_NAME);
    return IoCreateSymbolicLink(&symName, &cdoName);
}
 
NTSTATUS InitDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
    NTSTATUS status = STATUS_SUCCESS;
    ULONG retLen = 0;
    Irp->IoStatus.Status = status;
    Irp->IoStatus.Information = retLen;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return status;
}
 
NTSTATUS TestDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
    PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
    NTSTATUS status = STATUS_SUCCESS;
    ULONG retLen = 0;
 
    if (ioStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) {
 
        switch (ioStack->Parameters.DeviceIoControl.IoControlCode) {
            case TEST_R3TOR0_CODE:
            {  
                //DbgBreakPoint();
                PVOID buffer = Irp->AssociatedIrp.SystemBuffer;
                ULONG inlen = ioStack->Parameters.DeviceIoControl.InputBufferLength;
                // receive Message
                KdPrintEx((77, 0, "[db]:%s\r\n", buffer));
                break;
            }
            case TEST_R0TOR3_CODE:
            {
                ULONG outlen = ioStack->Parameters.DeviceIoControl.OutputBufferLength;
                // send Message
                ULONG x = 2000;
                memcpy(Irp->AssociatedIrp.SystemBuffer, &x, outlen);
                Irp->IoStatus.Information = outlen; // 设置
                DbgBreakPoint();
                break;
            }
            default:
                status = STATUS_INVALID_PARAMETER;
                break;
        }
 
    }
 
    Irp->IoStatus.Status = status;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return status;
 
}
 
VOID Unload(PDRIVER_OBJECT driver) {
    UNICODE_STRING symName = RTL_CONSTANT_STRING(SYM_NAME);
    if (NT_SUCCESS(IoDeleteSymbolicLink(&symName))) {
        KdPrintEx((77, 0, "Delete Symbolic Link..\r\n"));
    }
    IoDeleteDevice(pDevice);
}
 
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg) {
    pDriver->DriverUnload = Unload;
    pDriver->MajorFunction[IRP_MJ_CREATE] = InitDispatch;
    pDriver->MajorFunction[IRP_MJ_CLOSE] = InitDispatch;
    pDriver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = TestDispatch;
 
    NTSTATUS status;
    status = TestCreateCDO(pDriver);
    if (!NT_SUCCESS(status)) {
        KdPrint(("create CDO Failed..."));
        return status;
    }
    pDevice->Flags &= ~DO_DEVICE_INITIALIZING;
    pDevice->Flags |= DO_BUFFERED_IO;
 
    status = TestCreateSymbolicLink(pDriver);
    if (!NT_SUCCESS(status)) {
        KdPrint(("create symboliclink failed..."));
        return status;
    }
 
    return STATUS_SUCCESS;
}
#include <ntifs.h>
 
#define CRL_CODE_INDEX 0x800
#define TEST_R3TOR0_CODE (ULONG)CTL_CODE(FILE_DEVICE_UNKNOWN, CRL_CODE_INDEX, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define TEST_R0TOR3_CODE (ULONG)CTL_CODE(FILE_DEVICE_UNKNOWN, CRL_CODE_INDEX+1, METHOD_BUFFERED, FILE_ANY_ACCESS)
 
#define CDO_NAME L"\\Device\\TestDevice2"
#define SYM_NAME L"\\??\\TestDevice2"
 
PDEVICE_OBJECT pDevice = NULL;
 
NTSTATUS TestCreateCDO(PDRIVER_OBJECT pDriver) {
    UNICODE_STRING cdoName = RTL_CONSTANT_STRING(CDO_NAME);
    NTSTATUS status = IoCreateDevice(
        pDriver,
        0,
        &cdoName,
        FILE_DEVICE_UNKNOWN,
        FILE_DEVICE_SECURE_OPEN,
        FALSE,
        &pDevice
    );
 
    return status;
}
 
NTSTATUS TestCreateSymbolicLink(PDRIVER_OBJECT drvier) {
    UNICODE_STRING cdoName = RTL_CONSTANT_STRING(CDO_NAME);
    UNICODE_STRING symName = RTL_CONSTANT_STRING(SYM_NAME);
    return IoCreateSymbolicLink(&symName, &cdoName);
}
 
NTSTATUS InitDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
    NTSTATUS status = STATUS_SUCCESS;
    ULONG retLen = 0;
    Irp->IoStatus.Status = status;
    Irp->IoStatus.Information = retLen;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return status;
}
 
NTSTATUS TestDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
    PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
    NTSTATUS status = STATUS_SUCCESS;
    ULONG retLen = 0;
 
    if (ioStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) {
 
        switch (ioStack->Parameters.DeviceIoControl.IoControlCode) {
            case TEST_R3TOR0_CODE:
            {  
                //DbgBreakPoint();
                PVOID buffer = Irp->AssociatedIrp.SystemBuffer;
                ULONG inlen = ioStack->Parameters.DeviceIoControl.InputBufferLength;
                // receive Message

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2024-11-29 23:33 被Gushang编辑 ,原因: 修改话题为原创
收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//