windows 驱动实例分析系列: wintun驱动分析-driver篇(一)

📅 2026/8/18 13:05:56
windows 驱动实例分析系列: wintun驱动分析-driver篇(一)
Wintun 驱动模块深度解析整个驱动模块我们分为下面四个部分1.驱动项目配置与概述介绍driver.vcxproj、filters、undocumented.h以及驱动的整体架构。2.驱动初始化与注册DriverEntry、驱动特性、适配器初始化TunInitializeEx、Halt、Pause、Restart等。3.数据路径发送与接收TunSendNetBufferLists、TunReturnNetBufferLists、TunProcessReceiveData、环形缓冲区管理。4.OID请求处理与辅助功能OID查询/设置、设备控制、PNP、进程通知、注册/注销缓冲区等。一、模块概述driver文件夹包含了 Wintun 内核驱动的全部源代码它是整个 Wintun 生态中最底层的组件负责与 Windows 网络栈NDIS交互实现虚拟网络适配器的数据收发。该驱动以wintun.sys文件形式部署通过 INF 文件安装到系统中。驱动代码遵循NDIS 6.20规范支持 Windows 7 至 Windows 11采用WDMWindows Driver Model框架并充分利用了 NDIS 6.x 的高级特性如动态暂停/重启、多处理器支持、直接 OID 请求等。二、项目文件与构建配置2.1driver.vcxproj—— 项目核心配置PropertyGroupLabelConfigurationPlatformToolsetWindowsKernelModeDriver10.0/PlatformToolsetConfigurationTypeDriver/ConfigurationTypeDriverTypeWDM/DriverType/PropertyGroupItemDefinitionGroupClCompilePreprocessorDefinitionsNDIS_MINIPORT_DRIVER1; NDIS620_MINIPORT1; NDIS683_MINIPORT1; NDIS_WDM1; POOL_ZERO_DOWN_LEVEL_SUPPORT; POOL_NX_OPTIN1; %(PreprocessorDefinitions)/PreprocessorDefinitionsAdditionalOptions/volatile:iso %(AdditionalOptions)/AdditionalOptions/ClCompileLinkAdditionalDependenciesndis.lib;wdmsec.lib;%(AdditionalDependencies)/AdditionalDependencies/Link/ItemDefinitionGroup关键解读平台工具集WindowsKernelModeDriver10.0是 WDK 提供的专用工具集支持内核模式驱动的编译链接。预处理器定义NDIS_MINIPORT_DRIVER1声明为 NDIS 微型端口驱动。NDIS620_MINIPORT/NDIS683_MINIPORT支持 NDIS 6.20 和 6.83 版本保证向后兼容。NDIS_WDM1使用 WDM 风格与 NDIS 5 的旧式驱动区分。POOL_ZERO_DOWN_LEVEL_SUPPORT支持内存池清零。POOL_NX_OPTIN1启用 NXNo-Execute保护。链接库ndis.libNDIS API、wdmsec.lib安全相关。INF 处理发布版将$(WintunVersion)写入 INF 的时间戳调试版使用*不替换。2.2driver.vcxproj.filters标准的文件筛选器将wintun.c归入源文件wintun.rc归入资源文件wintun.inf归入源文件undocumented.h归入头文件无特殊逻辑。2.3wintun.inf未提供内容但存在于项目中这是驱动的安装信息文件定义了硬件 IDWintun、驱动文件、服务安装、注册表设置等。api模块中的extract-driverver.js会从中提取版本和日期用于生成wintun-inf.h。2.4undocumented.h—— 未文档化 API 声明此头文件声明了一些未在标准 WDK 中公开的内核函数和数据结构和包括ZwQuerySystemInformation和SystemExtendedHandleInformation枚举系统句柄表用于检测哪个进程持有了适配器文件句柄。ZwYieldExecution让出 CPU用于自旋等待。SeSddlSecurityDescriptorFromSDDL从 SDDL 字符串创建安全描述符但驱动中并未直接调用而是使用预编译的二进制安全描述符。SYSTEM_HANDLE_INFORMATION_EX等结构体用于查询句柄信息。这些定义使驱动能够执行一些高级操作比如在设备移除时强制关闭持有设备对象的进程句柄避免设备残留。三、驱动整体架构3.1 NDIS Miniport 驱动模型Wintun 驱动实现了一个NDIS 微型端口Miniport驱动它向 NDIS 协议栈暴露一张虚拟网络适配器。其核心交互对象是Miniport 适配器上下文TUN_CTX结构包含所有状态信息。Miniport 处理函数InitializeEx、HaltEx、Pause、Restart、SendNetBufferLists、ReturnNetBufferLists、OidRequest等。网络数据交换通过共享环形缓冲区用户态分配驱动映射实现零拷贝。3.2 关键数据结构TUN_CTXtypedefstruct_TUN_CTX{volatileLONG Running;// 运行状态EX_SPIN_LOCK TransitionLock;// RCU 风格的读写锁NDIS_HANDLE MiniportAdapterHandle;// NDIS 句柄DEVICE_OBJECT*FunctionalDeviceObject;// 设备对象NDIS_STATISTICS_INFO Statistics;// 统计信息struct{LIST_ENTRY Entry;// 全局设备列表ERESOURCE RegistrationLock;// 保护注册状态FILE_OBJECT*OwningFileObject;// 持有设备文件的文件对象HANDLE OwningProcessId;// 持有进程 IDKEVENT Disconnected;// 断开事件struct{/* Send ring驱动读取应用程序数据 */MDL*Mdl;TUN_RING*Ring;ULONG Capacity;KEVENT*TailMoved;KSPIN_LOCK Lock;ULONG RingTail;struct{NET_BUFFER_LIST*Head,*Tail;}ActiveNbls;}Send;struct{/* Receive ring应用程序读取驱动数据 */MDL*Mdl;TUN_RING*Ring;ULONG Capacity;KEVENT*TailMoved;HANDLE Thread;KSPIN_LOCK Lock;struct{NET_BUFFER_LIST*Head,*Tail;KEVENT Empty;}ActiveNbls;}Receive;}Device;NDIS_HANDLE NblPool;// NBL 内存池}TUN_CTX;设计要点双向环形缓冲区Send方向是驱动从应用程序获取数据包即用户态发送Receive方向是驱动向应用程序推送数据包用户态接收。命名从驱动视角出发。加锁策略TransitionLock用于状态切换运行/暂停采用共享/独占锁读路径数据收发取共享锁状态变更取独占锁实现 RCU 风格的免锁读。进程关联每个适配器只能被一个进程的会话持有通过OwningProcessId和OwningFileObject标识。统计信息符合 NDIS 统计要求用于OID_GEN_STATISTICS。3.3 全局变量与驱动入口全局变量包括NdisVersion运行时 NDIS 版本。NdisMiniportDriverHandleNDIS 驱动句柄。TunDispatchDeviceList全局适配器列表用于孤儿清理。TunDispatchSecurityDescriptor二进制安全描述符限制只有 SYSTEM 和管理员可打开设备。DriverEntry是驱动入口调用ExInitializeDriverRuntime启用 NX 优化。获取 NDIS 版本若低于 NDIS 6.20 则返回失败。初始化资源锁TunDispatchCtxGuard和TunDispatchDeviceListLock。填充NDIS_MINIPORT_DRIVER_CHARACTERISTICS结构注册所有回调。注册进程创建/退出通知例程TunProcessNotification用于自动清理无主设备。调用NdisMRegisterMiniportDriver完成注册。替换驱动对象的 IRP 分发函数IRP_MJ_DEVICE_CONTROL、IRP_MJ_CLOSE、IRP_MJ_PNP以便拦截用户态 IOCTL 和关闭操作。四、设备对象与安全驱动创建了一个设备对象通过 NDIS 框架自动创建其安全描述符限制为仅 SYSTEM 和 Administrators 可访问。TunDispatchSecurityDescriptor是预编译的二进制 SDDL对应字符串O:SYD:P(A;;FA;;;SY)(A;;FA;;;BA)S:(ML;;NWNRNX;;;HI)。设备对象的Reserved字段被用来存放TUN_CTX指针在TunInitializeEx中设置便于 IRP 分发函数快速获取上下文。五、驱动状态机初始化TunInitializeEx分配并初始化TUN_CTX设置 NDIS 属性介质类型为NdisMediumIP支持统计、暂停等然后返回成功。此时适配器处于“已停止”状态。暂停/重启NDIS 可能因电源管理或即插即用事件而暂停驱动。TunPause将Running置为 FALSE并等待所有挂起的 NBL 返回。TunRestart将Running置为 TRUE。数据收发仅在Running TRUE且Device.Disconnected未置位时进行。注销当用户态调用WintunEndSession或进程退出时触发TunUnregisterBuffers断开连接释放资源。卸载TunUnload注销进程通知调用NdisMDeregisterMiniportDriver最终释放资源。六、总结本文档概述了 Wintun 驱动的项目结构、构建配置、核心数据结构和入口逻辑。驱动代码量虽大约 1500 行但架构清晰充分利用了 NDIS 6.x 的现代特性实现了高性能、低延迟的虚拟网络适配器。后续文档将深入剖析初始化的细节、数据路径、OID 处理以及辅助功能。