OWN-Defender 是一个 Windows 安全研究项目,专注于理解 Windows 安全中心(WSC) 如何通过其 COM 接口表示和管理防病毒安全产品。
该项目最初是对 DefendNot 所展示行为的一项调查,但我没有将现有实现视为黑盒,而是将其作为独立逆向工程和验证的起点。
该项目的目标是理解完整的执行路径:
COM
↓
CLSID / IID
↓
CoCreateInstance
↓
QueryInterface
↓
ATL 接口映射
↓
vtable
↓
IWscAVStatus4
↓
CWscIsv
↓
WSCAPI.dll
↓
RPC
↓
Windows 安全中心
该项目是在受控的 Windows 研究环境中开发和测试的。
仅限研究/教育用途
本项目旨在用于 Windows 内部研究、逆向工程、安全教育以及经授权的安全测试。请勿将其用于干扰您不拥有或未经明确许可测试的系统上的安全软件。
最初的问题很简单:
Windows 安全中心如何知道存在一款防病毒产品?
我没有停留在公开的 API 文档上,而是想了解 API 底层发生了什么。
这引出了几个问题:
QueryInterface() 如何解析该接口?__int64 a1?Register() 函数才是真正的 AV 注册函数?第一步是识别 Windows 安全中心的 COM 类。
该项目使用 WSC COM 类:
CLSID_WscIsv
F2102C37-90C3-450C-B3F6-92BE1693BDF2
实现中还包含从 Windows 注册表动态定位 CLSID 的逻辑,而不是完全依赖硬编码值。
概念上:
HKLM
└── SOFTWARE
└── Classes
└── CLSID
└── {CLSID}
└── Windows 安全中心 ISV API
这提供了第一个重要的关系:
注册表
↓
CLSID
↓
Windows 安全中心 ISV API
下一个挑战是确定应请求哪个 COM 接口。
该项目使用:
IWscAVStatus4
其 IID 为:
4DCBAFAC-29BA-46B1-80FC-B8BDE3C0AE4D
研究中的一个重要教训是:
仅凭 GUID 名称不足以作为证据。
我通过逆向工程验证了这种关系,而不是假设接口名称和 GUID 是正确的。
调查包括:
QueryInterface_ATL_INTMAP_ENTRYQueryInterface最有用的逆向步骤之一是跟踪以下实现:
CComAggObject<CWscIsv>::QueryInterface()
它最终到达:
ATL::CComObjectRootBase::InternalQueryInterface()
ATL 接口映射用于将请求的 IID 与已注册的接口条目进行比较。
概念上:
请求的 IID
↓
QueryInterface()
↓
InternalQueryInterface()
↓
ATL 接口映射
↓
GUID 比较
↓
匹配的接口
↓
接口指针
这提供了独立证据,证明所调查的 GUID 确实对应于预期的 COM 接口。
Register() 的困惑最大的逆向挑战之一是理解为什么 IDA/Ghidra 并不总是显示我预期的函数签名。
重建的接口包含:
virtual HRESULT __stdcall Register(
BSTR path,
BSTR name,
unsigned int,
unsigned int
) = 0;
然而,反编译器可能显示如下实现:
_IWscAVStatus4<CWscIsv>::Register(__int64 a1)
起初这看起来不一致。
进一步调查表明,反编译器表示的是包装器/跳板以及底层的间接 vtable 调用,而不是呈现完整的逻辑接口签名。
这成为一个重要的教训:
反编译器输出是对机器代码的解释,而非原始源代码层面的真相。
为了解决这些差异,我比较了:
COM 接口定义
↓
vtable 布局
↓
汇编代码
↓
包装器/跳板
↓
调用约定
↓
实际目标函数
Register() 函数另一个困惑来源是存在多个名称相似但功能不同的函数,例如:
IWscAVStatus2::Register
IWscAVStatus4::Register
IWscFWStatus2::Register
RegisterAV
重要的认识是:相似的名称并不意味着相同的接口。
例如:
防病毒
↓
IWscAVStatus4
↓
AV 注册
而:
防火墙
↓
IWscFWStatus2
↓
防火墙注册
必须验证接口编号及其周围的实现,而不是仅仅因为函数名称包含 Register 就选择它。
这是研究中最有价值的部分之一,因为它迫使我关联:
接口
+
IID
+
vtable
+
实现
+
参数布局
+
调用目标
在识别出正确的接口后,我将注册操作追踪到了二进制文件的更深处。
观察到的路径大致为:
IWscAVStatus4::Register()
↓
CWscIsv
↓
RegisterSecurityProductFunction
↓
wscRegisterSecurityProduct()
↓
WSCAPI.dll
↓
s_wscRegisterSecurityProduct()
↓
NdrClientCall3()
↓
RPC
↓
Windows 安全中心
这一点特别重要,因为 COM 方法本身并不是最终操作。
该调用最终跨越了 RPC 边界。
这改变了我对架构的看法:
COM
≠
最终实现
相反:
COM
↓
本地实现
↓
WSC API
↓
RPC 客户端
↓
Windows 组件
WSCAPI.dll下一层是 WSCAPI.dll。
逆向工程得到的路径到达:
wscRegisterSecurityProduct()
它最终调用:
s_wscRegisterSecurityProduct()
然后:
NdrClientCall3()
这是调查从普通的 COM 调用进入 Windows RPC 基础设施的转折点。
理解这一层有助于解释为什么仅查看原始 COM DLL 无法完全理解该行为。
静态分析只是研究的一部分。
在重建相关接口和调用路径后,我创建了自己的受控实现,并将结果行为与 Windows 安全中心进行了比较。
我使用了 Windows 安全中心 / WMI 信息,例如:
ROOT\SecurityCenter2
AntiVirusProduct
来独立观察已注册的产品信息。
验证过程为:
逆向工程
↓
接口重建
↓
自有实现
↓
运行时执行
↓
Windows 安全中心
↓
WMI 观察
↓
比较结果
这使我能够验证静态分析的结论与可观察的 Windows 行为是否一致。
这个项目教给我的远不止如何与一个 COM 接口交互。
CoCreateInstanceQueryInterfaceWSCAPI.dllNdrClientCall3最重要的是,我学会了避免依赖单一证据。
相反:
符号
↓
反编译器
↓
汇编代码
↓
GUID
↓
接口映射
↓
vtable
↓
调用图
↓
RPC
↓
运行时验证
每一层都增加了结论的可信度。
研究实现由两个主要组件组成。
OWN-Defender
│
├── OWN-Defender.cpp
│ ├── WSC COM 交互
│ ├── CLSID 发现
│ ├── COM 初始化
│ ├── IWscAVStatus4 交互
│ ├── 注册
│ ├── 状态更新
│ └── 清理
│
└── dllmain.cpp
├── DLL 入口点
├── 研究加载器
├── 受控执行
└── 清理/停止处理
该仓库刻意保持精简,以便逆向工程行为与实现之间的关系易于理解。
这个项目是围绕问题而非简单地复现功能而构建的:
WSC 如何识别 COM 类?
IID 如何映射到接口?
QueryInterface 如何定位接口?
为什么 IDA 显示不同的函数签名?
实际的 vtable 在哪里?
哪个 Register() 是 AV 实现?
COM 方法之后会发生什么?
WSCAPI.dll 在调用链中的什么位置介入?
RPC 从哪里开始?
如何独立验证结果?
这些问题最终比最终实现本身更有价值。
该项目还为研究以下安全边界提供了一个有用的起点:
应用程序
↓
COM
↓
Windows 安全中心
↓
安全提供程序信息
一个重要的区别是:注册安全产品信息并不自动等同于禁用 Defender 引擎或绕过其保护机制。
因此,本项目应主要被视为:
Windows 安全中心 / COM 逆向工程研究
而不是声称仅凭 WSC 注册就构成 Defender 漏洞。
任何安全影响都需要单独的调查和验证。
这项研究部分受到 DefendNot(作者 es3n1n)所展示工作的启发。
特别感谢作者为理解 WSC 机制提供了一个有用的起点。
原始项目: https://github.com/es3n1n/defendnot
本仓库的目的不是将原始研究据为己有,而是记录我自己的逆向工程过程、独立实现以及对底层 Windows 行为的验证。
本仓库提供用于:
请仅在您拥有或明确获准测试的系统上使用本项目。
作者对滥用、损坏、数据丢失、安全控制干扰或未经授权的部署不承担任何责任。
本项目采用 GNU 通用公共许可证 v3.0 授权。
详情请参阅 LICENSE。
OWN-Defender 的主要目标不仅仅是复现一种 AV 注册技术。
它旨在展示一种可重复的逆向工程方法论:
发现
↓
映射
↓
逆向
↓
重建
↓
追踪
↓
实现
↓
验证
从一个关于 Windows 安全中心的问题开始,最终演变为对 COM、ATL、GUID/IID 映射、vtable、编译器生成代码、WSCAPI、RPC 和 Windows 安全架构 的深入探索。
实现是结果。逆向工程的过程才是真正的项目。