当前位置: 首页 > news >正文

windows 驱动实例分析系列: wintun驱动分析-api篇(二)

Wintun API 模块深度解析(文档二):适配器生命周期与驱动管理

一、概述

本文档深入分析api模块中的适配器管理和驱动安装逻辑,主要涉及文件:

  • adapter.c/adapter.h
  • adapter_win7.h
  • driver.c/driver.h
  • registry.c/registry.h(辅助读取注册表)
  • resource.c/resource.h(提取嵌入式文件)

适配器管理是 Wintun 最核心的功能之一,涵盖了从创建、打开、关闭、删除到孤儿设备清理的全过程。驱动安装则负责在首次使用或版本更新时,将 Wintun 内核驱动(wintun.sys)和配套 INF/CAT 文件部署到系统。


二、驱动安装与版本管理(driver.c

2.1 驱动版本检测

  • WintunGetRunningDriverVersion:通过NtQuerySystemInformation枚举已加载的内核模块,查找名为wintun.sys的驱动,然后读取其文件版本(通过GetFileVersionInfo)。若未加载,返回 0 并设置ERROR_FILE_NOT_FOUND
  • 内部辅助函数MaybeGetRunningDriverVersion(ReturnOneIfRunningInsteadOfVersion)支持仅检测是否存在(返回 1),用于等待驱动卸载。

2.2 驱动安装流程(DriverInstall

此函数在WintunCreateAdapter中被调用(首次创建适配器时)。流程如下:

  1. 获取互斥锁:通过NamespaceTakeDriverInstallationMutex()确保同一时刻只有一个进程执行安装,避免竞争。
  2. 创建设备信息:使用SetupDiCreateDeviceInfoListExW创建网络设备类的一个临时设备信息元素,设置硬件 ID 为Wintun
  3. 枚举已安装的兼容驱动:通过SetupDiBuildDriverInfoList获取系统中所有匹配Wintun硬件 ID 的驱动。
  4. 版本比较:遍历每个驱动信息,与 Wintun 内置驱动版本(从 INF 提取的WINTUN_INF_VERSIONWINTUN_INF_FILETIME)比较。如果现有驱动更新,则直接使用;如果内置驱动更新,则:
    • 禁用所有使用当前驱动创建的 Wintun 适配器(调用DisableAllOurAdapters),等待驱动卸载(EnsureWintunUnloaded)。
    • 调用SetupUninstallOEMInfW卸载旧驱动(SUOI_FORCEDELETE强制删除)。
    • 继续寻找下一个驱动。
  5. 若没有找到可用驱动,则执行全新安装:
    • 使用ResourceCreateTemporaryDirectory%WINDIR%\Temp下创建随机临时目录。
    • 根据本机架构(NativeMachine),从 DLL 资源中提取对应的wintun.syswintun.catwintun.inf到临时目录。
    • 调用SetupCopyOEMInfW将 INF 复制到系统驱动存储(%SystemRoot%\INF),完成安装。
    • 删除临时文件并移除目录。
  6. 保存上下文:将之前禁用的适配器列表通过输出参数DevInfoExistingAdaptersForCleanupExistingAdaptersForCleanup返回,由调用方在适配器创建完成后重新启用它们(通过DriverInstallDeferredCleanup)。

2.3 驱动卸载(WintunDeleteDriver

  • 首先调用AdapterCleanupOrphanedDevices清理所有孤儿适配器(无所有者进程)。
  • 再次枚举匹配Wintun硬件 ID 的驱动,对每个驱动调用SetupUninstallOEMInfW移除。
  • 此操作需获取驱动安装互斥锁,且仅在无适配器使用时成功。

2.4 版本比较逻辑

IsNewer函数通过比较FILETIME和 64 位版本号(高 16 位为主版本,其次为次版本,其次为构建号,低 16 位为修订)决定新旧。优先比较日期,再比较版本号。


三、适配器创建(WintunCreateAdapter

这是最复杂的函数,需要处理 Windows 7/8/10 的不同 API,并支持 WOW64 代理。

3.1 前期准备

  • 获取设备安装互斥锁(NamespaceTakeDeviceInstallationMutex)。
  • 调用DriverInstall确保驱动已安装。
  • 分配并初始化WINTUN_ADAPTER结构。

3.2 Windows 8+ 的软件设备创建路径

步骤:

  1. 生成实例 ID:若调用方提供了RequestedGUID,则直接使用;否则调用CoCreateGuid生成随机 GUID。将 GUID 转换为字符串作为设备实例 ID。
  2. 创建存根设备(Stub):在 Windows 10 上,先通过SwDeviceCreate创建一个临时的存根设备,仅设置硬件 ID 为空字符串,并在其软件注册表项中写入SuggestedInstanceId(用于影响 NLA GUID)。然后立即关闭该存根。
    • 此步骤的目的是为系统网络位置感知(NLA)提供确定的 GUID,避免每次创建新适配器都生成新的 NLA 条目。
  3. 创建主设备:再次调用SwDeviceCreate,传入实际的硬件 ID(WINTUN_HWID)和设备属性:
    • DEVPKEY_Wintun_Name:用户指定的适配器名称(如 “Demo”)。
    • DEVPKEY_Device_FriendlyName:隧道类型名称 + " Tunnel"。
    • DEVPKEY_Device_DeviceDesc:同上。
    • 设置标志SWDeviceCapabilitiesSilentInstall(静默安装)和SWDeviceCapabilitiesDriverRequired(需要驱动)。
  4. 等待设备创建完成:通过回调DeviceCreateCallback设置事件,然后等待。
  5. 等待接口可用:调用WaitForInterface,使用DevCreateObjectQuery查询设备接口(GUID_DEVINTERFACE_NET)是否已启用,超时 15 秒。这确保了驱动已正确加载并注册了设备接口。
  6. 打开设备信息:通过SetupDiOpenDeviceInfo打开该设备,然后调用PopulateAdapterData从注册表读取NetCfgInstanceIdNetLuidIndex*IfType等关键信息。
  7. 设置网络连接名称:调用NciSetAdapterName(内部使用NciSetConnectionName)将网络连接显示名设置为用户指定的名称,若冲突则自动添加序号后缀。
  8. Windows 7 特殊处理:若系统为 Windows 7,则路径不同(见下文)。

3.3 Windows 7 的专用创建路径

Windows 7 不支持SwDeviceCreate,因此 Wintun 使用传统的 Setup API 进行设备创建(参考adapter_win7.h中的CreateAdapterWin7函数):

  • 创建设备信息元素,设置硬件 ID 为Wintun
  • 构建兼容驱动列表,选中第一个匹配的驱动。
  • 依次调用DIF_REGISTERDEVICEDIF_REGISTER_COINSTALLERSDIF_INSTALLINTERFACESDIF_INSTALLDEVICE
  • 设置自定义属性DEVPKEY_Wintun_OwningProcess(包含进程 ID 和创建时间),用于孤儿设备清理。
  • 等待设备接口可用(通过轮询检查注册表值和设备状态)。
  • 返回设备实例 ID。

3.4 WOW64 代理调用

在 32 位进程运行于 64 位系统上时,直接调用 Setup API 会失败。因此,adapter.c中的AdapterRemoveInstanceAdapterEnableInstanceAdapterDisableInstance等函数会检查全局NativeMachineIMAGE_FILE_PROCESS,若不同则通过rundll32.c中的辅助函数启动 64 位代理进程(setupapihost.dll)来执行操作。

代理调用的实现细节已在之前《setupapihost 深度解析》中详细说明,此处不再重复。

3.5 适配器打开(WintunOpenAdapter

  • 枚举所有网络设备,过滤枚举器为SWD\Wintun(Win8+)或ROOT\Wintun(Win7),查找DEVPKEY_Wintun_Name与给定名称匹配的设备。
  • 获取设备实例 ID,打开设备信息,填充WINTUN_ADAPTER结构。
  • 同样等待接口可用并填充数据。

3.6 适配器关闭(WintunCloseAdapter

  • 若适配器由CreateAdapter创建(具有SwDevice或通过 Windows 7 路径),则调用AdapterRemoveInstance删除设备。
  • 否则只释放句柄,不删除(打开模式)。
  • 释放内存后,触发异步孤儿设备清理(QueueUpOrphanedDeviceCleanupRoutine)。

3.7 孤儿设备清理(AdapterCleanupOrphanedDevices

孤儿设备是指那些没有关联进程(或关联进程已退出)的 Wintun 适配器。这类设备可能因进程崩溃或未正确调用CloseAdapter而遗留。

清理逻辑(Win8+):

  • 枚举所有网络设备,检查设备状态是否有问题(CM_Get_DevNode_StatusDN_HAS_PROBLEM)。
  • 对于有问题的设备,尝试通过DEVPKEY_Wintun_Name获取名称,并调用AdapterRemoveInstance删除。

Windows 7 特殊版本(AdapterCleanupOrphanedDevicesWin7):

  • 检查自定义属性DEVPKEY_Wintun_OwningProcess,若进程不存在或进程创建时间不匹配,则判定为孤儿并删除。

此外,AdapterCleanupLegacyDevices用于清理早期 Wintun 版本在ROOT\NET枚举器下遗留的设备。


四、辅助函数与注册表操作

4.1PopulateAdapterData

从设备驱动注册表项(DIREG_DRV)读取:

  • NetCfgInstanceId:转换为 GUID 存入CfgInstanceID
  • NetLuidIndex:用于构造NET_LUID
  • *IfType:接口类型。

4.2AdapterGetDeviceObjectFileName

通过CM_Get_Device_Interface_ListW获取设备接口的符号链接名(如\\.\Wintun_{GUID}),用于后续CreateFile打开设备对象。

4.3WaitForInterface

使用 Windows 8 引入的DevCreateObjectQuery创建设备查询,等待设备接口启用,超时 15 秒。若超时或失败,记录详细错误信息(包括问题代码和 NTSTATUS)。

4.4 名称冲突解决(NciSetAdapterName

调用NciSetConnectionName尝试设置网络连接名,若返回ERROR_DUP_NAME,则自动在名称后添加空格加数字序号(最多尝试 1000 次),并尝试重命名冲突的现有连接。


五、总结

本文详细剖析了 Wintun 适配器的创建、打开、关闭、删除流程,以及驱动安装/卸载的完整机制。关键亮点包括:

  • 跨版本兼容性:为 Windows 7 保留传统 Setup API 路径,同时为 Windows 8+ 使用更现代的软件设备模型。
  • WOW64 透明代理:自动检测进程位数,通过rundll32启动代理 DLL 执行需要本机架构的 Setup API 调用。
  • 驱动版本管理:智能比较现有驱动与内置驱动版本,必要时升级并禁用/重新启用现有适配器。
  • 孤儿设备清理:确保崩溃进程留下的适配器能被自动回收,保持系统整洁。

下一篇文章将转向会话管理与数据路径,揭示 Wintun 高效收发的核心——环形缓冲区与无锁设计。


http://www.jsqmd.com/news/1400865/

相关文章:

  • NumPy数组创建全解析:empty、zeros、ones与full函数性能与应用指南
  • 群晖NAS通过虚拟机稳定同步115网盘:架构、部署与优化指南
  • Claude Code Tools计划模式:从AI意图解析到多步骤开发任务自动化
  • SpringMVC视图渲染原理深度解析:从DispatcherServlet到模板引擎的完整流程
  • 餐饮加盟哪家好:【美洲汉堡】商机无限 - 晴光转树
  • VS Code Doxygen插件:自动化代码文档生成与团队协作实践
  • SV学习记录(九)
  • 开源工具实现AI智能体免费网络访问:原理、集成与实战指南
  • Claude-Red AI红队攻防技能库实战教程:Web漏洞渗透落地与大模型对抗测试
  • SciPy 模块列表:核心子模块与实战代码示例
  • 多智能体应用实战 | 从理论到实战:4个真实落地案例,看OpenClaw如何解决企业真实问题
  • 2026年天津春考冲刺班选择指南 本地考生备考提分实用参考 - 贰拾壹度
  • CTF逆向工程实战:从入门到企业级应用
  • 国资穿透式监管合规怎么做?从政策到执行的全流程拆解
  • Prometheus 监控 Fluentd 全栈实战:从缓冲区堆积到输出延迟的日志管道可观测性
  • Diffusion模型与滚动时域控制:构建机器人动作生成的鲁棒闭环系统
  • JSON数据格式全解析:从语法基础到跨语言实战与性能优化
  • 2026年杭州AI搜索优化实战:企业从0到1布局全流程
  • 餐饮加盟推荐:【美洲汉堡】前景向好 - 云溪自乐
  • Java Stream核心操作精讲
  • 2026年上海GEO代运营选型对比及中小微企业选购指南 - 筑云鲸
  • 传播易凭什么成为企业全媒体智能发稿的优选平台?
  • Dify 中级实验(13):多 Agent 协作——如何编排多个智能体分工干活?
  • 软件开发中的上下文湮灭:从代码考古到主动防腐的工程实践
  • 2.8万亿参数本地跑起来是什么体验?Kimi K3开源权重部署与性能调优实录
  • 技术人如何用工程思维管理社交媒体算法依赖,夺回注意力主权
  • NC|婴儿肠道病毒组全球荟萃分析揭示生命早期三年噬菌体群落构建与功能演进规律
  • 天道13~14集
  • 湖南人力资源服务业破577亿,湘楚人力以23亿营收与国家级调解资质领跑全省出海用工赛道
  • Clawdbot本地化AI助手部署与配置指南