文章标题:金山卫士ksafebc.sys内核驱动后门利用漏洞
文章作者:ZzAge[LCG][80DFJ][DST]
联系邮箱:zzage@163.com
吾爱破解[LCG]:http://www.52pojie.net
[80DFJ]:http://www.80dfj.org
暗组安全技术论坛[DST]:http://forum.darkst.com
影响版本:金山卫士<=1.5.0.1147
文件名:Ksafebc.sys <=1.4.0.1124
MD5:61fe31b0a815197db8508580a0ac8dce
文件签名:Kingsoft Security Co.,Ltd
(金山官方已更新此漏洞)
漏洞原因:Ksafebc.sys这个是BOOT级驱动,在开机启动加载驱动后,此驱动会检测是否存在“KSafeFileBootClean.config”,“KSafeFileBootOccupy.config”,“KSafeFileBootReplace.config”这三个配置文件,如果存在就会读取配置文件里的数据,并实现相关功能!但因为检测和加密配置文件的方式比较简单,也没有其他校验的方法,所以只要伪造一个配置文件,就可以简单的实现其文件操作功能!因为驱动是Boot级别,它启动加载的时机比较早,所以基本上可以利用它达到对任意文件的删除,替换,占坑的目的!
KSafeFileBootClean.config 文件删除功能配置文件
KSafeFileBootOccupy.config 文件占坑功能配置文件
KSafeFileBootReplace.config 文件替换功能配置文件
例子:KSafeFileBootClean.config
.text:00011B60 push ebp
.text:00011B61 mov ebp, esp
.text:00011B63 push 0FFFFFFFFh
.text:00011B65 push offset dword_12840
.text:00011B6A push offset _except_handler3
.text:00011B6F mov eax, large fs:0
.text:00011B75 push eax
.text:00011B76 mov large fs:0, esp
.text:00011B7D add esp, 0FFFFFFD8h
.text:00011B80 push ebx
.text:00011B81 push esi
.text:00011B82 push edi
.text:00011B83 mov [ebp+var_18], esp
.text:00011B86 mov [ebp+var_34], 0C0000001h
.text:00011B8D mov [ebp+var_28], 0
.text:00011B94 mov [ebp+P], 0
.text:00011B9B mov [ebp+var_2C], 0
.text:00011BA2 mov [ebp+var_21], 0
.text:00011BA6 mov [ebp+var_20], 0
.text:00011BAD mov [ebp+var_1C], 0
.text:00011BB4 mov [ebp+var_35], 0
.text:00011BB8 mov eax, [ebp+SourceString]
//打开配置文件,并返回文件句柄hFile
.text:00011BBB push eax ; SourceString
.text:00011BBC call sub_12620
.text:00011BC1 mov [ebp+var_35], al
.text:00011BC4 movzx ecx, [ebp+var_35]
.text:00011BC8 test ecx, ecx
//判断hFile是否为零
.text:00011BCA jnz short loc_11BD8
.text:00011BCC mov [ebp+var_34], 0
.text:00011BD3 jmp loc_11CA7
.text:00011BD8 ; ---------------------------------------------------------------------------
.text:00011BD8
.text:00011BD8 loc_11BD8: ; CODE XREF: sub_11B60+6Aj
.text:00011BD8 lea edx, [ebp+var_2C]
.text:00011BDB push edx ; int
.text:00011BDC lea eax, [ebp+P]
.text:00011BDF push eax ; int
.text:00011BE0 mov ecx, [ebp+SourceString]
.text:00011BE3 push ecx ; SourceString
//读取配置文件的数据,并返回读取到的数据的地址和文件大小
.text:00011BE4 call sub_12670
.text:00011BE9 mov [ebp+var_34], eax
.text:00011BEC cmp [ebp+var_34], 0
.text:00011BF0 jz short loc_11BF7
.text:00011BF2 jmp loc_11CA7
.text:00011BF7 ; ---------------------------------------------------------------------------
.text:00011BF7
.text:00011BF7 loc_11BF7: ; CODE XREF: sub_11B60+90j
.text:00011BF7 mov [ebp+var_21], 1
.text:00011BFB mov [ebp+var_4], 0
.text:00011C02 mov edx, [ebp+var_2C]
.text:00011C05 push edx
.text:00011C06 mov eax, [ebp+P]
.text:00011C09 push eax
//异或解密读取到的配置文件的数据
.text:00011C0A call sub_12630
.text:00011C0F mov ecx, [ebp+P]
.text:00011C12 mov [ebp+var_20], ecx
.text:00011C15 mov edx, [ebp+var_20]
.text:00011C18 mov eax, [edx+4]
.text:00011C1B imul eax, 24Ah
.text:00011C21 add eax, 8
//比较文件大小是否等于读取到的数据长度大小
//if (FileLength==(*DWORD*)(BufferAddr+4)*0x24A+8)
.text:00011C24 cmp eax, [ebp+var_2C]
.text:00011C27 jz short loc_11C39
.text:00011C29 mov [ebp+var_34], 0C0000001h
.text:00011C30 mov [ebp+var_4], 0FFFFFFFFh
.text:00011C37 jmp short loc_11CA7
.text:00011C39 ; ---------------------------------------------------------------------------
.text:00011C39
.text:00011C39 loc_11C39: ; CODE XREF: sub_11B60+C7j
.text:00011C39 mov [ebp+var_28], 0
.text:00011C40 jmp short loc_11C4B
.text:00011C42 ; ---------------------------------------------------------------------------
.text:00011C42
.text:00011C42 loc_11C42: ; CODE XREF: sub_11B60+115j
.text:00011C42 mov ecx, [ebp+var_28]
.text:00011C45 add ecx, 1
.text:00011C48 mov [ebp+var_28], ecx
.text:00011C4B
.text:00011C4B loc_11C4B: ; CODE XREF: sub_11B60+E0j
.//读取配置文件里需要删除文件的个数=*(DWORD*)(BufferAddr+4)
.text:00011C4B mov edx, [ebp+var_20]
.text:00011C4E mov eax, [ebp+var_28]
.text:00011C51 cmp eax, [edx+4]
.text:00011C54 jnb short loc_11C77
.text:00011C56 mov ecx, [ebp+var_28]
.text:00011C59 imul ecx, 24Ah
.text:00011C5F mov edx, [ebp+P]
.text:00011C62 lea eax, [edx+ecx+8]
.text:00011C66 mov [ebp+var_1C], eax
.//读取配置文件里需要删除的文件路径=(wchar_t *)(uFileBufferAddr+0x24A*i+8)
.text:00011C69 mov ecx, [ebp+var_1C]
//删除从配置文件读取到的文件
.text:00011C6C push ecx ; wchar_t *
.text:00011C6D call sub_11880
.text:00011C72 mov [ebp+var_34], eax
.text:00011C75 jmp short loc_11C42
.text:00011C77 ; ---------------------------------------------------------------------------
.text:00011C77
.text:00011C77 loc_11C77: ; CODE XREF: sub_11B60+F4j
.text:00011C77 mov [ebp+var_4], 0FFFFFFFFh
.text:00011C7E jmp short loc_11CA0
.text:00011C80 ; ---------------------------------------------------------------------------
.text:00011C80
.text:00011C80 loc_11C80: ; DATA XREF: .text:00012844o
.text:00011C80 mov eax, 1
.text:00011C85 retn
.text:00011C86 ; ---------------------------------------------------------------------------
.text:00011C86
.text:00011C86 loc_11C86: ; DATA XREF: .text:00012848o
.text:00011C86 mov esp, [ebp+var_18]
.text:00011C89 mov [ebp+var_34], 0C0000001h
.text:00011C90 mov [ebp+var_4], 0FFFFFFFFh
.text:00011C97 jmp short loc_11CA7
.text:00011C99 ; ---------------------------------------------------------------------------
.text:00011C99 mov [ebp+var_4], 0FFFFFFFFh
.text:00011CA0
.text:00011CA0 loc_11CA0: ; CODE XREF: sub_11B60+11Ej
.text:00011CA0 mov [ebp+var_34], 0
.text:00011CA7
.text:00011CA7 loc_11CA7: ; CODE XREF: sub_11B60+73j
.text:00011CA7 ; sub_11B60+92j ...
.text:00011CA7 movzx edx, [ebp+var_21]
.text:00011CAB cmp edx, 1
.text:00011CAE jnz short loc_11CB9
.text:00011CB0 mov eax, [ebp+P]
.text:00011CB3 push eax ; P
.text:00011CB4 call sub_12800
.text:00011CB9
.text:00011CB9 loc_11CB9: ; CODE XREF: sub_11B60+14Ej
.text:00011CB9 mov eax, [ebp+var_34]
.text:00011CBC mov ecx, [ebp+var_10]
.text:00011CBF mov large fs:0, ecx
.text:00011CC6 pop edi
.text:00011CC7 pop esi
.text:00011CC8 pop ebx
.text:00011CC9 mov esp, ebp
.text:00011CCB pop ebp
.text:00011CCC retn 4
.text:00011CCC sub_11B60 endp
根据以上的分析得出以下配置文件的数据结构:
typedef struct _CLEANDATA
{
DWORD unknow;
DWORD dwNum;
char FilePath[586*dwNum];
}CLEANDATA;
解密配置文件函数:
void XorFun(ULONG pBuffer,ULONG FileLength)
{
ULONG i;
if (pBuffer>0)
{
for (i=0;i<FileLength;++i)
{
*(BYTE*)(pBuffer+i)=*(BYTE*)(pBuffer+i)^0x48;
}
}
}
上面的读取配置文件数据并根据需要删除文件功能函数源码:
BOOLEAN DoFileClean(BOOLEAN bClean,wchar_t* FilePath)
{
BOOLEAN bDO;
BOOLEAN bRead;
ULONG uFileLength;
ULONG uDataLength,i;
wchar_t *FileName;
ULONG uFileBufferAddr;
if (bClean)
{
bDO=MyOpenFile(FilePath);
bRead=FALSE;
uFileBufferAddr=0;
uFileLength=0;
if (bDO)
{
bDO=MyReadFile(FilePath,(ULONG)&uFileBufferAddr,(ULONG)&uFileLength);
if (bDO)
{
bRead=TRUE;
XorFun(uFileBufferAddr,uFileLength);
uDataLength=*(DWORD*)(uFileBufferAddr+4)*0x24A+8;
if (uDataLength==uFileLength)
{
for (i=0;i<*(DWORD*)(uFileBufferAddr+4);++i)
{
FileName=(wchar_t *)(uFileBufferAddr+0x24A*i+8);
MyDeleteFile(bDO,FileName);
}
} else
{
bDO=FALSE;
}
}
}
if (bRead)
{
ExFreePoolWithTag(pBuffer,0);
}
}
return bDO;
}
漏洞利用方法:创建一个字节大小为586*文件个数+8的文件,1-4个字节未使用,可以任意字节,5-8字节为文件个数,9-594字节为第一个文件路径,该文件命名KSafeFileBootClean.config,并放在%windir%\system32\目录下,然后创建一个Boot方式加载ksafebc.sys的驱动服务!重启后,利用完成,占坑和替换利用方法与此类似...
|