加载一个 Windows 驱动程序 Class 而不是 NetService 来充当 NDIS 过滤器

Loading a Windows Driver Class other than NetService to act as an NDIS Filter

是否可以采用 Windows 驱动程序,例如 Ports class 驱动程序,然后将其自身设置为 NDIS 过滤器(NetService class) 驱动程序通过在它的 DriverEntry() 中调用 NdisFRegisterFilterDriver()?这实际上是让驱动程序作为 PortsNetService class 驱动程序双重职责,但在单个代码库和二进制文件中。

我正在尝试执行此操作,但我看到注册 NDIS 驱动程序的调用失败,特别是以下跟踪消息:

[0][mp]<==ndisCreateFilterDriverRegistry, FilterServiceName 807EFA18 Status c0000001
[0][mp]==>NdisFRegisterFilterDriver: DriverObject 84C6C428      
[0][mp]==>ndisCreateFilterDriverRegistry, FilterServiceName 807EFA18
[0][mp]<==ndisCreateFilterDriverRegistry, FilterServiceName 807EFA18 Status c0000001

我环顾四周,似乎 NDIS 驱动程序严重依赖于 INF 和 INF 本身放置在注册表中的值。在尝试注册 NDIS 过滤器之前,我试图通过手动添加 NetCfgInstanceId 并在我的代码中调用该值来欺骗注册表项,但遇到了一个似乎是错误方法的点关于它。

推荐的解决方法是什么?在这一点上,我想这将需要一个 Ports class 驱动程序和 NetService class 驱动程序分开,用某种复合驱动程序将它们绑定在一起以便能够进行通信,或者通过进程间通信让一个或另一个进行通信。

严正警告

不要尝试通过手动写入注册表项来"install" 过滤器。正如您所注意到的,这并不容易,而且即使您看起来可以正常工作,当 OS 尝试安装下一个 LWF 时,它也会全部崩溃。此外,我添加了一些额外的强化功能,旨在防止人们对 Windows 10 执行此操作;在 Windows 10.

中劫持网络绑定之前,您必须对 OS 造成一些重大破坏

如何构建您的 driver 包

总之,你说的确实是有可能的。方法是在您的 driver 包中提供以下内容:

  1. A PNP-style INF。这个 INF 有:
    1. PORTS class
    2. 一个 AddService 指令,用于安装您的 driver 服务
    3. 一个 CopyFiles 指令来引入你需要的任何文件
    4. PNP 设备所需的任何其他位
  2. A NetCfg-style INF。这个 INF 有:
    1. NETSERVICEclass
    2. 通常的 LWF 内容:Characteristics=0x40000FilterMediaTypes=xxxFilterType=xxx
    3. 对您在其他 INF (HKR,Ndi,Service,,xxx) 中安装的服务的引用
    4. 不要包含 AddServiceCopyFiles;第一个 INF
    5. 已经解决了
  3. 一个 .sys 文件。这 driver 做:
    1. DriverEntry 中调用 NdisFRegisterFilterDriver,并传递您的服务名称 "xxx"
    2. DriverEntry 中,调用 WdfDriverCreate 或填写 DRIVER_OBJET 调度 table,就像您通常对任何其他 PNP driver
    3. 正常执行FilterAttach等;正常实施 WDF EvtXxx 或 WDM IRP 处理程序
    4. 不要忘记在 EvtDriverUnloadDriverUnload 中调用 NdisFDeregisterFilterDriver,也在 DriverEntry
    5. 的失败路径中调用

如何安装这个乱七八糟的东西

好消息是,使用这 2 个 INF,您可以满足让 1 个 .sys 文件做两件事的要求。坏消息是您现在有 2 个 INF。更糟糕的是,其中一个 INF 是 NetCfg-style INF,因此您不能只是 Include+Need 它。 安装 NetCfg-style INF 的方法是调用 INetCfgClassSetup::Install(或 NetCfg.exe,它的 command-line 包装器)。 Windows Update 只知道如何安装 PNP-style INF,而 PNP 只知道如何 Include 其他 PNP-style INF。

所以最简单的解决方案是发布一个调用 INetCfg API 的安装程序 exe/msi。如果你能做到这一点,只需调用 SetupCopyOemInfINetCfg 样板文件即可,你可以在 the bindview sample.

中找到这些样板文件

但是,如果您 支持 hardware-first 安装,则需要拿出大手笔。您需要编写一个 Co-Installer 并将其包含在您的 driver 包中。 Co-Installer 的工作是在安装 driver 软件包时调用 INetCfg APIs,并在卸载软件包时注销。

通常不鼓励

Co-Installers,并且不支持通用 drivers。所以你应该避免 Co-Installer 除非你别无选择。不幸的是,当通过 Windows 更新安装 PNP 设备 driver 时,我想不出任何其他方法来注册 NDIS LWF。 (这并不意味着没有巧妙的方法;我不是什么都知道。)

请注意,即使您要传送 2 个 .sys 文件,您仍然需要 Co-Installer。调用 INetCfg 的需求不会因为合并了 driver 二进制文件而改变。

限制

您将拥有一个 full-fledged NDIS LWF driver,以及一个 full-fledged PNP 设备 driver。唯一(次要)不起作用的是你不能在这个 driver 中调用 NdisRegisterDeviceEx。原因是当您从 LWF 调用 NdisRegisterDeviceEx 时,NDIS 将尝试 co-opt 您的 driver 的调度 table。但是在这个 PNP+LWF 对偶 driver 中,dispatch table 是 WDF 或你所有的。这个限制没有问题,因为你 可以 调用 WdfDeviceCreate,而且这个例程更容易使用,而且比 NDIS 例程有更多的功能。

通过上述配置,driver 服务归 PNP 所有。这意味着您的 .sys 文件的生命周期归 PNP 所有。您不能手动 "net start" PNP driver 服务;加载 .sys 文件的唯一方法是实际枚举硬件。这意味着当硬件不存在时,您无法拥有 NDIS LWF 运行。通常这就是您想要的。如果不是,您可以尝试弄乱 ServiceName 指令,但有一些奇怪的警告,我自己也不完全理解。