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

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

2025-1-21 23:45
4805

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

本文提出了一种方法可以在内核层使用“过滤”的方法来捕获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);

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2025-1-21 23:46 被moshuiD编辑 ,原因:
收藏
免费 16
支持
分享
赞赏记录
参与人
雪币
留言
时间
iamasbcx
你的帖子非常有用,感谢分享!
3天前
雪梨不是雪莉
感谢你的积极参与,期待更多精彩内容!
3天前
TubituX
+5
为你点赞!
5天前
hzfjl
这个讨论对我很有帮助,谢谢!
2025-1-26 19:59
mb_vceogglu
这个讨论对我很有帮助,谢谢!
2025-1-26 14:24
ThanatosKer
感谢你分享这么好的资源!
2025-1-26 00:52
appview
这个讨论对我很有帮助,谢谢!
2025-1-25 19:33
丶kk
你的分享对大家帮助很大,非常感谢!
2025-1-25 15:52
HOWMP
+1
感谢你的积极参与,期待更多精彩内容!
2025-1-25 10:49
煜凡
你的帖子非常有用,感谢分享!
2025-1-22 11:12
NoHeart
你的分享对大家帮助很大,非常感谢!
2025-1-22 09:59
coNg叶
感谢你的贡献,论坛因你而更加精彩!
2025-1-22 09:24
UserXCh
为你点赞!
2025-1-22 08:45
我的小拇指啊
期待更多优质内容的分享,论坛有你更精彩!
2025-1-22 03:45
顽劣
为你点赞!
2025-1-22 01:11
huangyalei
为你点赞!
2025-1-22 00:23
最新回复 (8)
雪    币: 221
活跃值: (2481)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
学习了。。
2025-1-22 08:23
0
雪    币: 95
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
看看
2025-1-22 09:06
0
雪    币: 240
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
4
Filter Driver
2025-1-22 09:59
0
雪    币: 1020
活跃值: (946)
能力值: ( LV3,RANK:36 )
在线值:
发帖
回帖
粉丝
5
NoHeart Filter Driver
差不多是这个意思
2025-1-22 11:35
0
雪    币: 677
活跃值: (3825)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
你如何保证你的完成例程就一定会被IoCompleteRequest执行,万一在你驱动的下层驱动设的完成例程里直接返回了MORE_PROCESSING_REQUIRED,回流就被打断了,人家回到自己分发函数中直接释放该irp了。
2025-1-23 03:04
0
雪    币: 206
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
7
看看
2025-1-24 12:42
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
8
感谢分享!
2025-1-26 14:50
0
雪    币: 460
活跃值: (185)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
9
感谢分享
4天前
0
游客
登录 | 注册 方可回帖
返回