首页
社区
课程
招聘
[原创] R0下一种简单的Irp包数据捕获方法
发表于: 2025-1-21 23:45 7366

[原创] R0下一种简单的Irp包数据捕获方法

2025-1-21 23:45
7366

本人学艺不精才疏学浅,只作为一种简单知识分享 欢迎各位大佬批评指正!

本文提出了一种方法可以在内核层使用“过滤”的方法来捕获Irp数据包。其中可以捕获到进入目标驱动前目标驱动处理完后的Irp数据包。

现在很多驱动都在使用Irp包的方式来与R3的程序进行通信。Irp是一个结构,由一个管理器进行分配管理。Irp从不单独分配,它总是伴随着多个IO栈位置结构(_IO_STACK_LOCATION),所以一般的驱动程序在获取真正的数据时需要使用IoGetCurrentIrpStackLocation函数来获取其中的数据。

Windows是以设备(DEVICE_OBJECT)为中心的,同时Windows支持设备分层。在多层设备的结构中,一个设备是堆叠在另一个设备的上面的,看起来就像一个栈一样,这组设备被称为设备栈。

我使用堆叠设备栈的方式,来获取Irp数据包(写过过滤驱动的肯定熟悉)。所以我们需要IoAttachDeviceToDeviceStack函数来附加到目标设备,这样就会让调用来的时候,先到我们的派遣函数

问题就变成了我们如何让目标驱动处理完后我们依然可以获取到数据呢?此时解决的关键就是IoSetCompletionRoutine函数了,它可以让下层的派遣函数调用IoCompleteRequest后到达指定的回调函数。

如下是一些关键代码:

我们针对WinARK的DeviceIoControl的数据来进行过滤测试。
为了验证我们数据的正确性,我们查看源码选择获取驱动派遣函数的这个功能进行测试。

如上是该功能的源码,传入的是设备名字,传回去的是派遣函数数组。
安装好我们的测试驱动后 查看一下自己的派遣函数列表就能捕获到如下信息

经观察可以发现传入的内容的确为L"\\driver\\AntiRootkit",传出的内容则是派遣函数列表(总长度为0x1b * 8)。已第一个为例则是0xFFFFF8024E911AA0,对比发现无误。

VOID DriverUnload(PDRIVER_OBJECT pDriver) {
    PDEVICE_OBJECT deviceObject = pDriver->DeviceObject;
    IoDetachDevice(deviceObject->DeviceObjectExtension->AttachedTo);
    IoDeleteDevice(deviceObject);
    KdPrint(("[+] Release done.\r\n"));
}
 
NTSTATUS MyCompletionRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context) {
    auto ioStack = IoGetCurrentIrpStackLocation(Irp);
    return STATUS_SUCCESS;
}
 
NTSTATUS Dispatch(_DEVICE_OBJECT* DeviceObject, _IRP* Irp) {
 
    auto ioStack = IoGetCurrentIrpStackLocation(Irp);
    KdPrint(("Func: %x\n", ioStack->MajorFunction));
    if (ioStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) {
        KdPrint(("IRP_DEVICE_CONTROL\n"));
        KdPrint(("Code: %x\n", ioStack->Parameters.DeviceIoControl.IoControlCode));
         
        IoCopyCurrentIrpStackLocationToNext(Irp);
        IoSetCompletionRoutine(
            Irp,
            MyCompletionRoutine,
            NULL,
            TRUE,
            TRUE,
            TRUE
        );
 
    }
    return IoCallDriver(DeviceObject->DeviceObjectExtension->AttachedTo, Irp);
}
 
extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pReg) {
    if (pDriver) {
        pDriver->DriverUnload = DriverUnload;
    }
 
    UNICODE_STRING name;
    RtlInitUnicodeString(&name, L"设备名");
    PDRIVER_OBJECT targetDriver;
 
    NTSTATUS status = ObReferenceObjectByName(&name, OBJ_CASE_INSENSITIVE, nullptr, 0,
        *IoDriverObjectType, KernelMode, nullptr, (PVOID*)&targetDriver);
 
    pDriver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = Dispatch;//这里我只想过滤这个函数。
 
    if (NT_SUCCESS(status)) {
        PDEVICE_OBJECT targetDevice = targetDriver->DeviceObject;
 
        PDEVICE_OBJECT fltDev;
        IoCreateDevice(
            pDriver,
            0,
            NULL,
            targetDevice->DeviceType,
            0,
            FALSE,
            &fltDev
        );
 
        IoAttachDeviceToDeviceStack(fltDev, targetDevice);
        fltDev->Flags &= ~DO_DEVICE_INITIALIZING;
        ObDereferenceObject(targetDriver);
    }
}
VOID DriverUnload(PDRIVER_OBJECT pDriver) {
    PDEVICE_OBJECT deviceObject = pDriver->DeviceObject;
    IoDetachDevice(deviceObject->DeviceObjectExtension->AttachedTo);
    IoDeleteDevice(deviceObject);
    KdPrint(("[+] Release done.\r\n"));
}
 
NTSTATUS MyCompletionRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context) {
    auto ioStack = IoGetCurrentIrpStackLocation(Irp);
    return STATUS_SUCCESS;
}
 
NTSTATUS Dispatch(_DEVICE_OBJECT* DeviceObject, _IRP* Irp) {
 
    auto ioStack = IoGetCurrentIrpStackLocation(Irp);
    KdPrint(("Func: %x\n", ioStack->MajorFunction));
    if (ioStack->MajorFunction == IRP_MJ_DEVICE_CONTROL) {
        KdPrint(("IRP_DEVICE_CONTROL\n"));
        KdPrint(("Code: %x\n", ioStack->Parameters.DeviceIoControl.IoControlCode));
         
        IoCopyCurrentIrpStackLocationToNext(Irp);
        IoSetCompletionRoutine(
            Irp,
            MyCompletionRoutine,
            NULL,
            TRUE,
            TRUE,
            TRUE
        );
 
    }
    return IoCallDriver(DeviceObject->DeviceObjectExtension->AttachedTo, Irp);

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

最后于 2025-1-21 23:46 被moshuiD编辑 ,原因:
收藏
免费 27
支持
分享
最新回复 (13)
雪    币: 221
活跃值: (2481)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
学习了。。
2025-1-22 08:23
0
雪    币: 95
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
看看
2025-1-22 09:06
0
雪    币: 277
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
4
Filter Driver
2025-1-22 09:59
0
雪    币: 1051
活跃值: (996)
能力值: ( LV3,RANK:36 )
在线值:
发帖
回帖
粉丝
5
NoHeart Filter Driver
差不多是这个意思
2025-1-22 11:35
0
雪    币: 677
活跃值: (3847)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
你如何保证你的完成例程就一定会被IoCompleteRequest执行,万一在你驱动的下层驱动设的完成例程里直接返回了MORE_PROCESSING_REQUIRED,回流就被打断了,人家回到自己分发函数中直接释放该irp了。
2025-1-23 03:04
0
雪    币: 259
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
7
看看
2025-1-24 12:42
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
8
感谢分享!
2025-1-26 14:50
0
雪    币: 460
活跃值: (200)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
9
感谢分享
2025-1-30 00:49
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
10
感谢师傅的分享
2025-2-7 12:20
0
雪    币: 3849
活跃值: (4087)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
11
看看。
2025-2-7 16:01
0
雪    币: 200
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
12
1
2025-2-8 17:33
0
雪    币: 1110
活跃值: (1630)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
看看
5天前
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
14
看看
4天前
0
游客
登录 | 注册 方可回帖
返回