
简介这是 A盾 v5.0 的完整源代码包定位于 Windows 安全防护类软件开发与驱动逆向分析。代码整体围绕进程保护、NDIS 网络过滤和内核交互等底层安全机制展开适合具备 C/C 基础的中高级开发者或者对安全工具内部实现感兴趣的学习者。压缩包共 319 个文件体积约 5.1MB核心源码以 133 个 h 头文件、54 个 c 文件和 52 个 cpp 文件组成另有 38 个 ico 图标、4 个 bmp 位图等界面资源以及若干 sys 驱动文件、sln/vcproj 工程文件和构建脚本可直接在 Visual Studio 环境中加载和重新编译。源码中还能看到 ndis5pkt.c、ldasm.c 这类底层文件分别涉及 NDIS 驱动和汇编级解析配合 Control.c、Function.c 等逻辑模块可清晰梳理驱动与应用层的调用关系。此外包含 dll、lib、exe 等辅助二进制以及资源脚本和过滤器配置有助于研究其界面布局和工程组织方式。整体目录结构清晰源码完整性也便于逐个模块对照研读。该项目已有 420 人学习查看可作为二次开发、安全机制参考或毕业设计的代码蓝本。 先交代一下项目背景。A盾是我这边一直在维护的一套主机侧安全防护工具v5.0 是第五个大版本的重构发布主要面向 Windows Server 环境下的站点和业务防护。项目最开始只是解决一个问题——网站被人传了一个脚本后门但我们只能靠人工去翻文件找了一整天才定位到后来慢慢迭代成集文件监控、进程行为分析、规则检测、日志审计于一体的防护体系。这套代码内部叫 A盾外部也习惯这么称呼v5.0 则是一次从引擎到规则体系全部推倒重来的大改版。这篇文章就从源码结构和实际落地角度把 v5.0 的核心设计、关键模块实现、攻防对抗后的迭代思路以及线上踩过的一些坑完整梳理一遍。适合正在做安全产品研发、网站防护、主机加固或代码审计的同学参考也适合运维同学了解一套防护工具的内部逻辑知道它到底在“盾”什么。1. 项目定位与整体设计从单点查杀到闭环防护先聊一个真实场景。当时有客户反馈网站后台被登录上传了一个伪装成图片的脚本文件随后数据库被拖走。传统的杀毒软件确实可以扫出已知样本但问题在于——样本太新引擎不认识而且就算查杀了攻击链路已经发生了我们连攻击者什么时候进来的都说不清楚。这暴露了老版本最大的短板只有“检测”没有“溯源”和“预防”。1.1 版本迭代里沉淀下来的设计变化v1.0 到 v4.0 的演变其实记录了我们对防护系统的认识升级v1.0 只做文件扫描就是一个带规则库的命令行扫描器效率低规则还经常误报。v2.0 加了文件系统实时监控只要有新增或修改文件就触发扫描解决“事后查杀”的滞后问题。v3.0 加入网络层拦截同时把进程行为纳入检测范围开始关注“谁在动文件”而不是只盯着文件本身。v4.0 引入规则热更新和简单的白名单机制降低了误报但引擎和规则强耦合改一个检测逻辑就要全量回归测试。v5.0 这版彻底解耦把检测引擎拆成独立模块规则统一成标准格式同时补上了完整的审计与自保护模块。为什么要这么改核心原因是攻击方式已经不再是单一文件落地而是一条完整链路初始入侵、权限提升、持久化、数据外带。单点查杀挡不住链路所以 v5.0 的目标很明确——做成一个“事前预防 事中拦截 事后溯源”的闭环系统。1.2 五大模块的分工与选型逻辑v5.0 在代码结构上分成五个独立模块每个模块之间通过标准接口通信而不是互相调用函数这是基于可维护性的考虑。检测引擎负责特征匹配、行为分析和权重判定是整套系统的计算核心。规则库以独立文件目录存放支持热加载规则格式统一为 JSON带版本号和生效范围。日志审计所有检测事件、拦截动作、规则命中记录统一写入本地库支持导出。自保护模块保护进程、文件、注册表不被恶意篡改防止攻击者“拆盾”。管理控制台负责策略下发、规则更新、告警展示和报表输出。这里要额外解释一个容易被忽略的点模块间为什么要用接口而不是直接调用最开始我们图省事让检测引擎直接读写日志模块的数据表结果一次日志模块的改动导致引擎全部报错。v5.0 全部改成消息队列和标准接口虽然初期开发量大了但后期迭代非常省心改日志存储不影响引擎换新引擎也不用动规则库。2. 核心模块拆解代码结构里的关键决策这章深入源码层面讲讲几个核心模块的落地方式。不是贴完整代码而是把最关键的判断逻辑和数据格式解剖开。2.1 检测引擎特征匹配之外的“行为预判”检测引擎大概是整个项目里最复杂的一块。v5.0 的引擎分成三层检测管线第一层是哈希匹配。对已知恶意文件计算 MD5、SHA1、SHA256和黑名单库比对。这一层最快但只能对付已知样本。第二层是特征正则匹配。用正则表达式匹配文件内容或进程命令行中的恶意模式比如一句话木马、异常编码函数、危险系统调用。第三层是行为权重评分。把一系列可疑动作综合起来打分超过阈值才告警避免单个动作就误杀。下面这段是引擎里行为评分的一个核心逻辑示例用 Python 伪代码表示def behavior_score(events): score 0 for event in events: if event.type FILE_CREATE and event.extension in [php, aspx, jsp]: score 30 if event.type PROCESS_CREATE and event.name in [cmd.exe, powershell.exe]: score 20 if event.type REGISTRY_SET and Run in event.path: score 20 if event.type NETWORK_CONNECT and event.remote_port 4444: score 30 # 同一进程短时间连续命中权重翻倍 if score 80: return BLOCK elif score 50: return ALERT return PASS这段逻辑的价值在于它把“单个不可疑、组合很可疑”的行为串了起来。比如一个进程既创建了脚本文件又启动了命令行进程还改了开机启动项单看哪个都像正常操作但组合起来就很危险。实际使用中这个权重表不是死的会根据业务场景动态调整比如开发服务器上出现命令行进程就相对常见阈值要放松。2.2 规则库的组织方式为什么拆成三层v5.0 的规则库最大的变化是三层分级基础规则、行为规则、业务白名单。基础规则面向已知威胁格式最简单每条规则就是一个特征加一个处置动作。行为规则面向未知威胁描述的是行为组合而不是具体特征。业务白名单则是给正常业务“开绿灯”的防止误报。一个标准的行为规则 JSON 长这样{ rule_id: BR-10086, name: WebShell 创建后门账户, level: high, conditions: [ {type: file_write, extension: [php, aspx], match: eval|base64_decode|assert}, {type: process_exec, name: cmd.exe, args_contains: net user}, {type: window: 5} ], action: block_and_alert }为什么要把规则库拆成三层而不是一个大列表最初我们确实把所有规则放在一个文件里结果误报率居高不下。拆开以后每个层级的更新频率和审核标准可以分开基础规则每周更新行为规则每月评审白名单按需调整。这样规则运营压力小很多也不会出现“升级一个规则导致整个引擎崩掉”的情况。2.3 日志与审计不做事后还原的防护都是耍流氓日志模块在 v5.0 里虽然代码量不大但设计上花了很多心思。每一条审计日志都遵循统一格式包含事件时间、事件类型、进程名、进程 PID、文件路径、命中规则 ID、处置动作、当前机器指纹。这样设计的目的只有一个出事后能还原完整攻击链。v5.0 默认把日志落在本地 SQLite 数据库里因为轻量、无需额外部署。但在大规模部署场景下可以用侧车方式把 SQLite 数据同步到 Elasticsearch。我个人的建议是日志字段宁可多不可少尤其是进程 PID 和父进程 PID这是溯源的关键线索。我们早期版本漏了父进程字段结果追溯攻击来源时只能靠猜非常被动。3. 关键功能实现与注意点恶意代码检测、自保护与授权这章讲三个最容易被忽略但实际特别重要的功能点每个都对应着线上踩过的具体教训。3.1 恶意代码特征提取与误报控制检测引擎再强规则特征没写好也会漏报误报。v5.0 在特征提取上总结了几个原则第一特征要选稳定的代码片段不能选变量名这种随便改的东西第二匹配前先做归一化处理统一换行符、去掉注释、压缩连续空格避免攻击者通过加注释或换行绕过。第三涉及正则的特征必须小范围测试防止正则回溯导致引擎卡死。关于误报控制这里分享一下我们的做法。每次新增规则先放到观察模式而不是拦截模式跑一周假阳性统计如果误报率高于 1%规则直接打回。同时引入“规则灰度”机制一个规则先对 5% 的机器生效确认无误后再全量推送。这个思路和代码发布的灰度发布是一样的安全产品尤其需要这种心态因为一次误杀可能导致整个业务停机。3.2 自保护模块的实现思路自保护模块最初我们用纯用户态实现通过钩子函数监控进程和注册表。事实证明这条路走不通——攻击者拿到管理员权限后可以直接结束进程或恢复钩子。v5.0 把自保护下沉到内核层利用文件系统过滤驱动和控制回调来实现用户态恶意程序很难在不触发异常的情况下关掉保护。当然内核驱动的开发量比用户态大很多调试也麻烦。实操中有一个非常关键的点驱动签名。Windows x64 系统强制要求驱动签名没签名的驱动根本无法加载。我们早期在测试机上装了个没签名的驱动导致系统直接拒绝加载排查了半天才发现是签名问题。所以建议做类似功能时先把签名流程跑通再开发具体功能。3.3 授权机制与网络验证设计A盾 v5.0 的授权体系参考过市面上“卫士盾网络验证”这类商业方案的思路但自研时做了很多简化。核心逻辑是客户端启动时读取本地授权文件里面的授权码通过非对称加密签名客户端每 24 小时和授权服务器做一次心跳校验确认授权状态有效。本地校验保证离线可用在线心跳则用来处理吊销授权和授权到期的场景。这里有一个很容易踩的坑千万不要把授权校验做成“必须联网才能用”。因为很多服务器是内网隔离的强制联网会导致产品直接被客户卸载。v5.0 的做法是离线优先在线增强。同时授权文件的签名算法要足够强否则攻击者可以自己伪造授权文件。我们在 v3.0 就吃过亏当时用的是简单的自定义加密结果被人直接写程序解了出来这算是交过学费的教训。4. 攻防视角的版本迭代从被逆向到主动防护说到安全产品必然绕不开“被攻击者研究”这件事。A盾 v5.0 的开发过程中我们不止一次被别人逆向分析、尝试绕过。这章讲讲防御视角下的几个应对策略。4.1 一次真实的对抗复盘有一次内测时攻击者在绕过文件监控后试图篡改规则配置文件把检测规则全部置为不生效。我们的日志系统记录了规则文件的哈希变化但是没有实时告警因为当时的自保护模块并没有把规则目录纳入保护范围。发现问题以后我们增加了对规则文件、引擎配置文件、日志文件这三类关键文件的完整性校验每次启动和定时巡检都会比对哈希。这个改进听起来简单但非常有效——很多攻击路径其实并不复杂只是没人想到要防这一下。4.2 代码混淆与完整性校验抬高门槛而不是追求完美做安全产品的都知道没有无法绕过的保护只能尽量提高攻击者的成本。v5.0 对核心模块做了三件事编译后用加壳工具做了一层壳关键字符串数据库地址、密钥、授权服务器地址全部做了加密存储运行时再解密核心函数的逻辑在启动时做自校验如果被修改则拒绝继续运行。这里我想说一句实在话加壳和反调试这些东西本质上不是用来“防住大神”的而是用来拦住 90% 试图投机取巧的人。真正的安全边界还是要靠服务端和强校验逻辑来保证客户端代码只能提供延缓。4.3 用源代码审计工具给自家代码“找茬”国内做代码审计的同学应该都用过 Seay 源代码审计系统它可以扫描 PHP 代码里的常见漏洞模式。我们虽然主要是 C 和 Python但同样会定期把核心模块代码丢进静态分析工具里跑排查缓冲区溢出、危险函数调用、未初始化变量等问题。自审清单里我常年保留这么几条所有外部输入是否做了长度和类型校验文件路径拼接是否可被特殊字符穿越日志内容是否可被注入线程处理是否有竞态条件。这些不会在功能测试阶段暴露问题但一旦上线就是安全隐患。5. 实操过程记录从源码到可部署版本很多人以为写完代码就结束了实际上从源码到可部署版本这段路才是坑最多的地方。5.1 编译打包与发布流程A盾 v5.0 的客户端主体用 C 编写编译环境是 Visual Studio 2019关键依赖全部静态链接避免目标机器缺少运行库。发布包固定包含以下内容主程序、驱动文件、规则目录、日志目录、配置文件、管理工具命令行版本。驱动和主程序都需要数字签名发布前用脚本统一签名发布包生成后还要做一次全量哈希所有文件哈希写入发布清单。5.2 兼容性与性能压测要点安全工具最怕的是装了以后业务出事。v5.0 发布前必须在 Windows Server 2008 R2、2012、2016、2019 四个系统版本上完成一轮完整回归测试。这里提醒大家Windows Server 2008 R2 已经停止官方支持很多新 API 在上面不可用写代码时要注意兼容性。性能压测的重点集中在三个方向全盘扫描时的磁盘 IO 和 CPU 占用峰值文件实时监控在高 IO 场景下的响应延迟以及日志入库在多事件并发时是否有队列堆积。v5.0 在开发机上做过一次 10 万文件全盘扫描压测规则命中 2000 条CPU 占用控制在 20% 以下这个结果我们可以接受。5.3 误报调优的“观察期”上线初期我们不能直接开启全部拦截而是分两个阶段前一周只告警不拦截观察误报情况第二周再开启高危规则的自动拦截低危规则仍然只告警。每次规则库更新也重复这个流程。这个方法虽然保守但对于生产环境的业务来说稳妥远比“激进拦截”重要得多。6. 常见问题与排错实录最后整理一个线上高频问题的速查表都是我们实际运维中遇到过的。下面这张表可以帮同行少走弯路。现象可能原因排查步骤解决办法安装后服务无法启动驱动未签名或签名过期查看系统事件日志确认驱动加载报错检查签名日期重新签名驱动启用测试签名模式排查全盘扫描时机器卡死引擎线程数设置过高IO 队列拥堵查看 CPU 和磁盘队列长度降低扫描线程数增加扫描限速策略大量文件被误报为恶意规则特征过宽或白名单未同步查看命中规则的样本确认特征片段收紧规则补充业务白名单WebShell 未被查杀规则库未更新或样本做了混淆手工比对样本和规则特征更新规则库对新样本做特征提取入库自保护被关闭后不再触发核心进程被结束保护未自恢复检查进程存活状态增加看门狗进程自保护异常时自动拉起还有两个印象深刻的排错案例值得单独拿出来说。一个是某次规则库更新后全网机器告警量突然暴涨后来定位到是一条正则表达式存在灾难性回溯匹配超长字符串时导致 CPU 打满。从那以后我们的规则测试流程里就多了一步用超长随机字符串做性能测试只有当执行时间稳定后才会发布。另一个是 Windows 系统大版本更新后自保护模块突然失效了。原因是系统内核回调机制有变化旧版驱动无法正常注册。这个问题的教训是涉及内核层的代码必须在系统更新的预览版里提前适配测试不能等正式发布再去处理那样会有一个用户暴露窗口期。最后再分享一个我自己的感受。A盾 v5.0 开发中最值得的投入是把引擎和规则彻底解耦这让我们后续每次做规则升级都变得很轻松而最大的教训则是早期忽略了对关键配置文件的完整性保护。如果你也在写类似的防护工具我的建议是先想清楚“你的产品到底要防谁、被他攻击之后你如何感知”再动手写代码这比任何技术选型都重要。本文还有配套的精品资源点击获取