不正确校验用户空间指针
很多KAV安装的挂钩(包括KAV自定义的系统服务)都会因为操作系统的不同而出现问题。比如,在KAV修
改的NtOpenProcess函数中企图通过直接和硬编码的0x7FFF0000比较,来判断是否是用户空间地址。在
绝大部分x86 Windows系统上,用户空间地址的最大值都是0x7FFEFFFF。但是硬编码用户空间的最大值
并不是好办法。比如把Boot.ini中的启动参数设定为"/3GB",将把默认的虚拟内存空间由2GB内核空间和
2GB用户空间改变为1GB内核空间和3GB用户空间。因此安装有KAV的系统启动参数配置为/3GB,在调用
NtOpenAddress(比如Win32 API OpenProcess)的时候,如果参数的地址在用户空间的2GB以上,系统
就可能随机崩溃。
.text:F82237B0 ; NTSTATUS __stdcall KavNtOpenProcess(PHANDLE ProcessHandle,
ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes,
PCLIENT_ID ClientId)
.text:F82237B0 KavNtOpenProcess proc near ; DATA XREF: sub_F82249D0+BFo
...
.text:F8223800 cmp eax, 7FFF0000h ; eax = ClientId
.text:F8223805 jbe short loc_F822380D
.text:F8223807
.text:F8223807 loc_F8223807: ; CODE XREF: KavNtOpenProcess+4Ej
.text:F8223807 call ds:ExRaiseAccessViolation
正确校验的方法是在SEH下使用公开函数ProbeForRead,在不正确的用户空间地址的时候,该函数将触
发一个Access异常。
此外,在很多KAV的自定义系统服务中都没有校验用户空间指针的正确性,这可能导致系统崩溃。
.text:F8222BE0 ; int __stdcall KAVService10(int,PVOID OutputBuffer,int)
.text:F8222BE0 KAVService10 proc near ; DATA XREF: .data:F8227D14o
.text:F8222BE0
.text:F8222BE0 arg_0 = dword ptr 4
.text:F8222BE0 OutputBuffer = dword ptr 8
.text:F8222BE0 arg_8 = dword ptr 0Ch
.text:F8222BE0
.text:F8222BE0 mov edx, [esp+OutputBuffer]
.text:F8222BE4 push esi
.text:F8222BE5 mov esi, [esp+4+arg_8]
.text:F8222BE9 lea ecx, [esp+4+arg_8]
.text:F8222BED push ecx ; int
.text:F8222BEE mov eax, [esi] ; 没有校验用户空间指针的正确性
.text:F8222BF0 mov [esp+8+arg_8], eax
.text:F8222BF4 push eax ; OutputBufferLength
.text:F8222BF5 mov eax, [esp+0Ch+arg_0]
.text:F8222BF9 push edx ; OutputBuffer
.text:F8222BFA push eax ; int
.text:F8222BFB call sub_F821F9A0 ; 本函数认为所有的传入指针都是正确的
.text:F8222C00 mov edx, [esi]
.text:F8222C02 mov ecx, [esp+4+arg_8]
.text:F8222C06 cmp ecx, edx
.text:F8222C08 jbe short loc_F8222C13
.text:F8222C0A mov eax, 0C0000173h
.text:F8222C0F pop esi
.text:F8222C10 retn 0Ch
.text:F8222C13 ; ------------------------------------------------------------------------
---
.text:F8222C13
.text:F8222C13 loc_F8222C13: ; CODE XREF: KAVService10+28j
.text:F8222C13 mov [esi], ecx
.text:F8222C15 pop esi
.text:F8222C16 retn 0Ch
.text:F8222C16 KAVService10 endp
.text:F8222C20 KAVService11 proc near ; DATA XREF: .data:F8227D18o
.text:F8222C20
.text:F8222C20 arg_0 = dword ptr 4
.text:F8222C20 arg_4 = dword ptr 8
.text:F8222C20 arg_8 = dword ptr 0Ch
.text:F8222C20
.text:F8222C20 mov edx, [esp+arg_4]
.text:F8222C24 push esi
.text:F8222C25 mov esi, [esp+4+arg_8]
.text:F8222C29 lea ecx, [esp+4+arg_8]
.text:F8222C2D push ecx
.text:F8222C2E mov eax, [esi] ; 没有校验用户空间指针的正确性
.text:F8222C30 mov [esp+8+arg_8], eax
.text:F8222C34 push eax
.text:F8222C35 mov eax, [esp+0Ch+arg_0]
.text:F8222C39 push edx
.text:F8222C3A push eax
.text:F8222C3B call sub_F8214CE0 ; 本函数认为所有的传入指针都是正确的
.text:F8222C40 test eax, eax
.text:F8222C42 jnz short loc_F8222C59
.text:F8222C44 mov ecx, [esp+4+arg_8]
.text:F8222C48 mov edx, [esi]
.text:F8222C4A cmp ecx, edx
.text:F8222C4C jbe short loc_F8222C57
.text:F8222C4E mov eax, STATUS_INVALID_BLOCK_LENGTH
.text:F8222C53 pop esi
.text:F8222C54 retn 0Ch
.text:F8222C57 ; ------------------------------------------------------------------------
---
.text:F8222C57
.text:F8222C57 loc_F8222C57: ; CODE XREF: KAVService11+2Cj
.text:F8222C57 mov [esi], ecx
.text:F8222C59
.text:F8222C59 loc_F8222C59: ; CODE XREF: KAVService11+22j
.text:F8222C59 pop esi
.text:F8222C5A retn 0Ch
.text:F8222C5A KAVService11 endp
Kaspersky Flaw的都是翻译自Skywing的"What Were They Thinking? Anti-Virus Software Gone
Wrong",只对其中关于Kaspersky的部分进行翻译。