ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

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

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

Wintun API 模块深度解析(文档一):公共接口与项目结构

一、模块定位与整体架构

api文件夹是 Wintun 用户态动态库(wintun.dll)的完整源代码,它构成了开发者与 Wintun 驱动交互的唯一官方接口。该 DLL 封装了驱动安装、适配器管理、会话控制、数据包收发等全部功能,并以一套简洁、稳定的 C API 对外暴露(定义在wintun.h中)。

整个api模块采用分层设计:

  • 公开接口层wintun.h):定义所有导出函数、常量和类型,供应用程序调用。
  • 适配器管理层adapter.c/.hadapter_win7.hdriver.c/.h):负责适配器的创建、打开、关闭、删除,以及驱动程序的安装/卸载。
  • 会话与数据路径层session.c):管理数据会话的生命周期,实现高效的环形缓冲区收发。
  • 辅助基础层loggernamespaceregistryresourcerundll32ncintdll等):提供日志、同步、注册表、资源嵌入、WOW64 代理、网络配置等通用服务。

本文作为系列第一篇,聚焦公开接口定义、内部数据结构、项目构建配置,为后续深入理解各模块奠定基础。


二、公共头文件wintun.h详解

wintun.h是 Wintun 唯一需要用户引用的头文件,它定义了全部 API 函数原型、回调类型、常量和句柄类型。该头文件采用#pragma onceextern "C"包装,兼容 C/C++。

2.1 句柄类型与基本常量

typedefstruct_WINTUN_ADAPTER*WINTUN_ADAPTER_HANDLE;typedefstruct_TUN_SESSION*WINTUN_SESSION_HANDLE;
  • 两种不透明句柄,分别代表适配器和会话,内部结构在实现文件中定义,外部不可访问。
  • 常量WINTUN_MIN_RING_CAPACITY(128 KiB)和WINTUN_MAX_RING_CAPACITY(64 MiB)规定了会话环形缓冲区容量的合法范围。
  • WINTUN_MAX_IP_PACKET_SIZE(0xFFFF)定义了最大 IP 包大小(64 KiB)。

2.2 API 函数指针类型定义

头文件为每个导出函数定义了对应的函数指针类型(如WINTUN_CREATE_ADAPTER_FUNC),便于应用程序通过GetProcAddress动态加载。所有导出函数如下:

函数名功能
WintunCreateAdapter创建新适配器(指定名称、隧道类型、可选 GUID)
WintunOpenAdapter打开已存在的适配器(按名称)
WintunCloseAdapter关闭并释放适配器(若由创建而来则同时删除)
WintunDeleteDriver卸载驱动(当无适配器使用时)
WintunGetAdapterLUID获取适配器的 NET_LUID(用于路由配置)
WintunGetRunningDriverVersion查询当前加载的驱动版本号
WintunSetLogger设置全局日志回调
WintunStartSession启动数据会话(指定缓冲区容量)
WintunEndSession结束会话
WintunGetReadWaitEvent获取读等待事件句柄(用于非阻塞等待)
WintunReceivePacket从接收环中获取一个数据包
WintunReleaseReceivePacket释放已接收的数据包缓冲区
WintunAllocateSendPacket分配发送缓冲区
WintunSendPacket提交发送数据包

这些函数均采用WINAPI__stdcall)调用约定,确保跨语言兼容。

2.3 日志回调类型

typedefenum{WINTUN_LOG_INFO,WINTUN_LOG_WARN,WINTUN_LOG_ERR}WINTUN_LOGGER_LEVEL;typedefVOID(CALLBACK*WINTUN_LOGGER_CALLBACK)(WINTUN_LOGGER_LEVEL Level,DWORD64 Timestamp,LPCWSTR Message);
  • 时间戳为 100 ns 间隔,自 1601-01-01 UTC(与 Windows FILETIME 一致)。
  • 回调可能从多线程并发调用,需由调用方自行序列化。

三、内部头文件与数据结构

3.1adapter.h—— 适配器内部描述

typedefstruct_WINTUN_ADAPTER{HSWDEVICE SwDevice;// 软件设备句柄(Win8+)HDEVINFO DevInfo;// SetupAPI 设备信息集SP_DEVINFO_DATA DevInfoData;// 设备信息数据WCHAR*InterfaceFilename;// 设备对象文件名(如 \\.\Wintun_xxx)GUID CfgInstanceID;// 网络配置实例 GUID(NetCfgInstanceId)WCHAR DevInstanceID[MAX_DEVICE_ID_LEN];// 设备实例 IDDWORD LuidIndex;// NET_LUID 中的索引DWORD IfType;// 接口类型(IF_TYPE_SOFTWARE_LOOPBACK 等)DWORD IfIndex;// 接口索引(可选)}WINTUN_ADAPTER;

此结构保存了适配器所有必要元数据,被各 API 函数频繁使用。

adapter.h还声明了内部辅助函数:

  • AdapterOpenDeviceObject:打开设备对象句柄(用于 IOCTL 通信)。
  • AdapterGetDeviceObjectFileName:获取设备接口的文件名。
  • AdapterCleanupOrphanedDevices:清理孤儿设备(无所有者进程)。
  • AdapterRemoveInstance/AdapterEnableInstance/AdapterDisableInstance:底层设备操作,内部会判断是否需要通过rundll32代理(WOW64 场景)。

3.2driver.h—— 驱动管理接口

声明了驱动安装/卸载的核心函数:

  • DriverInstall:安装或升级 Wintun 驱动(比较版本、提取资源、调用 Setup API)。
  • WintunDeleteDriver:删除驱动(当无适配器时)。
  • WintunGetRunningDriverVersion:查询当前加载的驱动版本。

此外,driver.c中定义了驱动版本比较、文件版本提取、禁用/启用现有适配器等逻辑。

3.3 全局变量与 DLL 入口

main.h定义了全局变量:

  • ResourceModule:DLL 模块句柄(用于资源提取)。
  • ModuleHeap:私有堆句柄(统一内存管理)。
  • SecurityAttributes:安全描述符(限制仅为 SYSTEM 和 Administrators 访问)。
  • IsLocalSystem:当前进程是否以 SYSTEM 身份运行。
  • NativeMachine:当前进程所处的本机架构(用于决定是否启用 WOW64 代理)。
  • IsWindows7/IsWindows10:版本标志,用于条件编译。

main.c中的DllMain负责:

  1. 创建私有堆。
  2. 初始化安全对象(创建包含 SYSTEM/管理员 SID 的安全描述符)。
  3. 获取操作系统版本和进程位数信息(通过IsWow64Process2IsWow64Process)。
  4. 初始化命名空间(NamespaceInit)并清理旧版适配器(AdapterCleanupLegacyDevices)。
  5. 在卸载时释放资源。

延迟加载钩子(__pfnDliNotifyHook2)强制从System32加载延迟加载的 DLL,避免恶意 DLL 劫持。


四、项目构建配置(api.vcxproj

4.1 基本设置

  • 配置类型DynamicLibrary(生成wintun.dll)。
  • 平台工具集WindowsApplicationForDrivers10.0——允许使用部分驱动开发包中的头文件和库,并支持cfgmgr32.hdevpkey.h等。
  • 输出文件名:通过<TargetName>wintun</TargetName>指定为wintun

4.2 预处理器定义

根据平台定义MAYBE_WOW64(x86、x64、ARM 均有,ARM64 没有),用于条件编译代理调用逻辑。资源编译时还会检查是否已构建其他平台的代理 DLL(BUILT_ARM64_WOW64BUILT_AMD64_WOW64),以便在资源中嵌入它们。

4.3 延迟加载与附加依赖

延迟加载了大量系统 DLL:

  • advapi32.dllcfgmgr32.dlliphlpapi.dllsetupapi.dllshlwapi.dllversion.dll等,以及api-ms-win-devices-query-l1-1-0.dll(设备查询)和api-ms-win-devices-swdevice-l1-1-0.dll(软件设备)。
  • 链接库包括onecore.lib(提供 SwDevice 等 API)、ntdll.libNtQuerySystemInformation等)、swdevice.lib等。

4.4 自定义生成步骤

  • BuildInfVersion:使用cscript.exe运行extract-driverver.js,从driver/wintun.inf中提取驱动版本和日期,生成wintun-inf.hdriver.c包含。这确保了驱动版本信息与 INF 文件同步。
  • BuildNci:将nci.h(内联存根)和nci.def编译为nci.lib,用于动态链接nci.dll(Windows 的网络连接接口)。由于nci.dll没有导入库,因此通过自定义步骤生成。

4.5 资源嵌入

resources.rc编译后嵌入 DLL 资源,包含多个平台的驱动文件(wintun.syswintun.catwintun.inf)和代理 DLL(setupapihost*.dll)。这些资源在driver.crundll32.c中按需提取到临时目录使用。


五、模块间依赖关系

┌─────────────────┐ │ wintun.h │ (公开API) └────────┬────────┘ │ ┌────────────────────────┼─────────────────────────┐ │ │ │ ▼ ▼ ▼ ┌─────────────┐ ┌─────────────────┐ ┌─────────────────────┐ │ adapter.c/h │ │ session.c │ │ driver.c/h │ │(适配器管理)│ │(会话与数据路径)│ │(驱动安装/卸载) │ └──────┬──────┘ └────────┬────────┘ └──────────┬──────────┘ │ │ │ │ ┌──────────────┴──────────────┐ │ │ │ │ │ ▼ ▼ ▼ ▼ ┌─────────────────────────────────────────────────────────────────┐ │ 辅助模块:logger, namespace, registry, resource, rundll32, nci │ └─────────────────────────────────────────────────────────────────┘
  • adapter.c调用driver.c安装驱动,调用namespace获取互斥锁,调用registry读取配置,调用rundll32进行跨位数代理。
  • session.c通过adapter.c打开设备对象,执行 IOCTL 注册环形缓冲区。
  • logger被所有模块使用。
  • resource用于提取嵌入式二进制文件。
  • nci模块负责修改网络连接名称(NciSetConnectionName)。

六、总结

本文作为 API 模块系列的首篇,全面梳理了:

  • 公共接口头文件wintun.h的函数声明与类型定义。
  • 内部关键数据结构(WINTUN_ADAPTERTUN_SESSION)及其作用。
  • 项目构建配置的细节(资源嵌入、延迟加载、自定义生成步骤)。
  • 各模块间的依赖关系和调用层次。

这些内容为后续深入分析适配器生命周期、数据路径和辅助机制提供了完整的上下文。在下一篇文章中,我们将深入剖析adapter.cdriver.c,揭示 Wintun 如何创建适配器、安装驱动,并优雅地处理 Windows 7 兼容性与 WOW64 代理调用。


返回列表