-
-
[原创]驱动通信基础
-
发表于: 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_READ
和IRP_MJ_WRITE
更容易绕过检测
同样,需要针对IRP_MJ_CREATE
和IRP_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期)
赞赏
- [原创]驱动通信基础 2988
- [原创]PE解析思路 17988
- [原创] SWPUCTF 2019 easyRE 9107
- [原创] ACTF2020 Splendid_MineCraft 7113
- [原创] SUSCTF 2022 DigitalCircuits 分析过程及解题脚本 8252