windows 驱动实例分析系列: wintun驱动分析-example篇(上)
Wintun Example 示例程序深度解析这部分作为演示如何使用wintun驱动进行二次开发的例子分为两部分。一、模块概述example文件夹是 Wintun 项目提供的一个完整的、可直接运行的示例程序用于演示如何使用wintun.dll的 API 来创建虚拟网络适配器、配置 IP 地址、收发数据包ICMP 回显请求/响应。它充当了一个最小化 VPN 客户端原型展示了从初始化到清理的完整生命周期。这个示例不仅是一个教学工具也是 Wintun 开发者进行集成测试的基准程序。其代码风格严谨、错误处理周全完全可以作为实际项目开发的参考模板。二、核心代码逐段分析2.1 函数指针与动态加载InitializeWintunstaticWINTUN_CREATE_ADAPTER_FUNC*WintunCreateAdapter;// ... 其余 13 个函数指针staticHMODULEInitializeWintun(void){HMODULE WintunLoadLibraryExW(Lwintun.dll,NULL,LOAD_LIBRARY_SEARCH_APPLICATION_DIR|LOAD_LIBRARY_SEARCH_SYSTEM32);if(!Wintun)returnNULL;#defineX(Name)((*(FARPROC*)NameGetProcAddress(Wintun,#Name))NULL)if(X(WintunCreateAdapter)||X(...)||/* ... */)#undefX{/* 错误处理并释放 */}returnWintun;}设计要点使用LoadLibraryEx并指定LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32确保优先从应用目录和系统目录加载wintun.dll防止 DLL 劫持。通过宏X批量获取所有导出函数的地址若任一失败则回滚并报错。返回的HMODULE在程序结束时释放确保资源正确清理。这种做法体现了延迟绑定的思想不静态链接wintun.lib而是运行时动态加载使得示例程序可以在未安装 Wintun 的系统上优雅地报错退出也方便替换不同版本的 DLL 进行测试。2.2 日志系统ConsoleLogger Log 辅助staticvoidCALLBACKConsoleLogger(WINTUN_LOGGER_LEVEL Level,DWORD64 Timestamp,constWCHAR*LogLine){SYSTEMTIME SystemTime;FileTimeToSystemTime((FILETIME*)Timestamp,SystemTime);WCHAR LevelMarker(LevelWINTUN_LOG_INFO)?L:(LevelWINTUN_LOG_WARN)?L-:L!;fwprintf(stderr,L%04u-%02u-%02u %02u:%02u:%02u.%04u [%c] %s\n,...);}亮点实现了 Wintun 要求的WINTUN_LOGGER_CALLBACK回调原型通过WintunSetLogger注册使 Wintun 内部日志也能输出到控制台。时间戳100 ns 间隔自 1601-01-01被正确转换为本地时间便于阅读。用、-、!分别代表 Info、Warn、Error 级别直观简洁。此外程序还提供了LogError、LogLastError、Log三个辅助函数LogError利用FormatMessage将 Win32 错误码转换为可读的字符串并自动添加前缀。LogLastError封装GetLastError()LogError简化调用。Log变参函数格式化输出到日志回调。这组日志工具使得程序在任何错误发生时都能输出详尽的诊断信息极大提升了调试效率。2.3 控制台信号处理优雅退出staticHANDLE QuitEvent;staticvolatileBOOL HaveQuit;staticBOOL WINAPICtrlHandler(DWORD CtrlType){switch(CtrlType){caseCTRL_C_EVENT:caseCTRL_BREAK_EVENT:caseCTRL_CLOSE_EVENT:caseCTRL_LOGOFF_EVENT:caseCTRL_SHUTDOWN_EVENT:Log(WINTUN_LOG_INFO,LCleaning up and shutting down...);HaveQuitTRUE;SetEvent(QuitEvent);returnTRUE;}returnFALSE;}机制HaveQuit是volatile全局标志供工作线程轮询。QuitEvent是一个手动重置事件用于唤醒阻塞在WaitForSingleObject上的线程。当用户按下 CtrlC 或关闭控制台时CtrlHandler被调用设置标志并触发事件所有线程收到信号后自行退出。这保证了示例程序在退出前能正确调用WintunEndSession和WintunCloseAdapter避免驱动资源泄漏。2.4 数据包处理逻辑PrintPacket MakeICMP2.4.1 收包解析PrintPacketstaticvoidPrintPacket(constBYTE*Packet,DWORD PacketSize){if(PacketSize20){/* 错误 */return;}BYTE IpVersionPacket[0]4,Proto;WCHAR Src[46],Dst[46];if(IpVersion4){RtlIpv4AddressToStringW((structin_addr*)Packet[12],Src);RtlIpv4AddressToStringW((structin_addr*)Packet[16],Dst);ProtoPacket[9];Packet20;PacketSize-20;}elseif(IpVersion6){// 检查最小长度 40 字节RtlIpv6AddressToStringW((structin6_addr*)Packet[8],Src);RtlIpv6AddressToStringW((structin6_addr*)Packet[24],Dst);ProtoPacket[6];Packet40;PacketSize-40;}else{Log(WINTUN_LOG_INFO,LReceived packet that was not IP);return;}// 如果协议是 ICMP (1) 且是回显应答 (type0)特殊标记if(Proto1PacketSize8Packet[0]0)Log(WINTUN_LOG_INFO,LReceived IPv%d ICMP echo reply from %s to %s,IpVersion,Src,Dst);elseLog(WINTUN_LOG_INFO,LReceived IPv%d proto 0x%x packet from %s to %s,IpVersion,Proto,Src,Dst);}解析要点通过 IPv4 首部第一个字节的高 4 位判断版本区分 IPv4 和 IPv6。使用RtlIpv4AddressToStringW/RtlIpv6AddressToStringW将二进制地址转换为字符串需链接ip2string.h和ntdll.lib。对于 ICMP 回显应答Echo Replytype0专门输出“ICMP echo reply”提示便于观察 ping 响应。2.4.2 发包构造MakeICMPstaticvoidMakeICMP(BYTE Packet[28]){memset(Packet,0,28);Packet[0]0x45;// IPv4, 首部长度 5*(USHORT*)Packet[2]htons(28);// 总长度 28Packet[8]255;// TTLPacket[9]1;// 协议 ICMP*(ULONG*)Packet[12]htonl((1024)|(616)|(78)|(80));// 源 10.6.7.8*(ULONG*)Packet[16]htonl((1024)|(616)|(78)|(70));// 目的 10.6.7.7*(USHORT*)Packet[10]IPChecksum(Packet,20);// IPv4 首部校验和Packet[20]8;// ICMP 类型: Echo Request*(USHORT*)Packet[22]IPChecksum(Packet[20],8);// ICMP 校验和Log(WINTUN_LOG_INFO,LSending IPv4 ICMP echo request to 10.6.7.8 from 10.6.7.7);}注意构造的是ICMP Echo Requestping 请求源地址为10.6.7.8目的地址为10.6.7.7。但示例程序在后续配置中将适配器的 IP 设为了10.6.7.7见后文这意味着它将 ping自身——实际上数据包会由操作系统路由回本机然后被ReceivePackets捕获并打印为“ICMP echo reply”不对因为源地址是 10.6.7.8而适配器是 10.6.7.7所以实际上是从 10.6.7.8 发往 10.6.7.7但源地址 10.6.7.8 并未分配给任何接口因此这个包会进入网络栈并被路由由于目标 10.6.7.7 是本机系统会响应 ICMP Echo Reply但源地址仍为 10.6.7.7目标为 10.6.7.8。所以最终接收到的包应该是 Echo ReplyPrintPacket 会识别出 type0输出“ICMP echo reply”。这个设计巧妙模拟了 ping 环回测试。IPv4 校验和计算函数IPChecksum实现了标准的一进制补码求和支持任意长度。

相关新闻

北邻京网站茵建设:小站深耕长尾流量的逆袭之路

北邻京网站茵建设:小站深耕长尾流量的逆袭之路

在这个流量为王、大V横行的互联网时代,很多人一听到“建站”这两个字,脑子里蹦出来的全是高大上的电商平台、炫酷的3A级门户或者动辄百万预算的定制化开发。大家总觉得,只有那些拥有庞大服务器集群、顶尖UI设计团队和海量资金支撑的项目,才配叫“做网站”。然而,现实往往是…

2026/10/16 18:58:55 阅读更多 →
OpenGeos/GeoLibre开源GIS工具实测:从环境搭建到核心功能验证

OpenGeos/GeoLibre开源GIS工具实测:从环境搭建到核心功能验证

这类开源地理空间工具最值得先看的不是功能列表,而是它到底解决了数据处理、发布还是协作中的哪个具体问题。OpenGeos / GeoLibre 这个名字听起来像是一个平台或工具集,对于需要处理地图、矢量数据、栅格影像或者搭建简单 GIS 服务器的开发者、数据分析师…

2026/10/17 6:09:01 阅读更多 →
管理系统通过邮箱自动备份数据思路|阿雪技术观-东方仙盟

管理系统通过邮箱自动备份数据思路|阿雪技术观-东方仙盟

数字化经营环境下,企业各类管理系统沉淀的业务单据、台账资料、流程记录,是支撑经营追溯、业务持续运转的核心信息资产。在日常运维管理中,多数企业更加关注系统能否稳定对外提供服务,却常常忽视数据留存体系的建设。一旦出现存储…

2026/10/16 10:30:25 阅读更多 →

最新新闻

MATLAB数学实验大作业避坑指南:数值计算与代码验证技巧

MATLAB数学实验大作业避坑指南:数值计算与代码验证技巧

简介:MATLAB数学实验课程的练习题与大作业答案,可作为南邮计算机专业学生及MATLAB初学者的配套参考,用于完成实验报告、考前复习或命令自查。压缩包共1个docx文档,大小约635KB,打开即可看到按题号组织的完整解答。内容…

2026/10/18 15:28:03 阅读更多 →
163MusicLyrics 上手攻略:5 步搞定网易云与 QQ 音乐歌词批量保存

163MusicLyrics 上手攻略:5 步搞定网易云与 QQ 音乐歌词批量保存

163MusicLyrics 上手攻略:5 步搞定网易云与 QQ 音乐歌词批量保存 【免费下载链接】163MusicLyrics 云音乐歌词获取处理工具【网易云、QQ音乐】 项目地址: https://gitcode.com/GitHub_Trending/16/163MusicLyrics 163MusicLyrics 是一款跨平台的开源音乐歌词…

2026/10/18 15:28:03 阅读更多 →
AIStore免费AI公开课-智能体篇(十):Claude Code接入TaoToken,用Claude改整个代码库,开箱即用

AIStore免费AI公开课-智能体篇(十):Claude Code接入TaoToken,用Claude改整个代码库,开箱即用

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 15:28:03 阅读更多 →
KV Cache上下文契约:一次批量推理注意力掩码错误的深度排查

KV Cache上下文契约:一次批量推理注意力掩码错误的深度排查

某个自研推理项目的调试过程,让我在一种极其隐蔽的 KV Cache 问题上耗了整整一天。事情背景并不复杂:为了提升吞吐,我把批处理推理里的缓存从"每请求独立申请"改成"共享显存池复用",顺带为适配某个优化 kerne…

2026/10/18 15:28:03 阅读更多 →
AI内容创作变现真相:合规生产与长期资产如何平衡

AI内容创作变现真相:合规生产与长期资产如何平衡

最近圈子里都在转一条消息:某个靠情感话题起号、以各种“恋爱技巧”和“人设剧本”收割流量的头部账号,被平台全线封杀,连小号、矩阵号都没放过。传播的截图里常配一句话:这人早就不靠内容吃饭了,切了AI工具&#xff0…

2026/10/18 15:28:03 阅读更多 →
小程序时间戳与日期转换全攻略:避开iOS时区与格式化大坑

小程序时间戳与日期转换全攻略:避开iOS时区与格式化大坑

不少开发者第一次在小程序里处理日期和时间戳,都会觉得这是个"小功能",随手搜个方法就完事了。但真到了上线前,各种怪异问题就冒出来了:时间差了8小时、iOS上日期解析直接报错、凌晨零点生成的订单总是显示昨天……我自…

2026/10/18 15:27:02 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →