加载一个 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()
?这实际上是让驱动程序作为 Ports
和 NetService
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 包中提供以下内容:
- A PNP-style INF。这个 INF 有:
-
PORTS
class
- 一个
AddService
指令,用于安装您的 driver 服务
- 一个
CopyFiles
指令来引入你需要的任何文件
- PNP 设备所需的任何其他位
- A NetCfg-style INF。这个 INF 有:
NETSERVICE
class
- 通常的 LWF 内容:
Characteristics=0x40000
、FilterMediaTypes=xxx
、FilterType=xxx
等
- 对您在其他 INF (
HKR,Ndi,Service,,xxx
) 中安装的服务的引用
- 不要包含
AddService
或 CopyFiles
;第一个 INF 已经解决了
- 一个 .sys 文件。这 driver 做:
- 在
DriverEntry
中调用 NdisFRegisterFilterDriver
,并传递您的服务名称 "xxx"
- 在
DriverEntry
中,调用 WdfDriverCreate
或填写 DRIVER_OBJET
调度 table,就像您通常对任何其他 PNP driver
- 正常执行
FilterAttach
等;正常实施 WDF EvtXxx 或 WDM IRP 处理程序
- 不要忘记在
EvtDriverUnload
或 DriverUnload
中调用 NdisFDeregisterFilterDriver
,也在 DriverEntry
的失败路径中调用
如何安装这个乱七八糟的东西
好消息是,使用这 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。如果你能做到这一点,只需调用 SetupCopyOemInf
和 INetCfg
样板文件即可,你可以在 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 指令,但有一些奇怪的警告,我自己也不完全理解。
是否可以采用 Windows 驱动程序,例如 Ports
class 驱动程序,然后将其自身设置为 NDIS 过滤器(NetService
class) 驱动程序通过在它的 DriverEntry()
中调用 NdisFRegisterFilterDriver()
?这实际上是让驱动程序作为 Ports
和 NetService
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 包中提供以下内容:
- A PNP-style INF。这个 INF 有:
-
PORTS
class - 一个
AddService
指令,用于安装您的 driver 服务 - 一个
CopyFiles
指令来引入你需要的任何文件 - PNP 设备所需的任何其他位
-
- A NetCfg-style INF。这个 INF 有:
NETSERVICE
class- 通常的 LWF 内容:
Characteristics=0x40000
、FilterMediaTypes=xxx
、FilterType=xxx
等 - 对您在其他 INF (
HKR,Ndi,Service,,xxx
) 中安装的服务的引用 - 不要包含
AddService
或CopyFiles
;第一个 INF 已经解决了
- 一个 .sys 文件。这 driver 做:
- 在
DriverEntry
中调用NdisFRegisterFilterDriver
,并传递您的服务名称 "xxx" - 在
DriverEntry
中,调用WdfDriverCreate
或填写DRIVER_OBJET
调度 table,就像您通常对任何其他 PNP driver - 正常执行
FilterAttach
等;正常实施 WDF EvtXxx 或 WDM IRP 处理程序 - 不要忘记在
EvtDriverUnload
或DriverUnload
中调用NdisFDeregisterFilterDriver
,也在DriverEntry
的失败路径中调用
- 在
如何安装这个乱七八糟的东西
好消息是,使用这 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。如果你能做到这一点,只需调用 SetupCopyOemInf
和 INetCfg
样板文件即可,你可以在 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 指令,但有一些奇怪的警告,我自己也不完全理解。