最近通过反汇编分析发现了一个 symantec 的漏洞,这个漏洞是在 symtdi.sys 中存在的,由 于驱动程序中处理 IRP_MJ_DEVICE_CONTROL 例程没有检查用户传入的缓冲区地址的合法性, 造成任意内核地址可写的漏洞,用户可以发送恶意的 DeviceIoControl 的来完全的控制计算 机。 在 symtdi.sys 中,以下代码用来处理IRP_MJ_DEVICE_CONTROL请求 loc_387C0: ; CODE XREF: sub_38736+6Cj .text:000387C0 cmp dword_4B258, 0 .text:000387C7 jz short loc_387EF .text:000387C7 .text:000387C9 call KeGetCurrentIrql .text:000387C9 .text:000387CE and eax, 0FFh .text:000387D3 test eax, eax .text:000387D5 jnz short loc_387EF .text:000387D5 .text:000387D7 call sub_37B5F .text:000387D7 .text:000387DC test eax, eax .text:000387DE jz short loc_387EF .text:000387DE .text:000387E0 mov dword_4B258, 0 .text:000387EA call sub_37B9A .text:000387EA .text:000387EF .text:000387EF loc_387EF: ; CODE XREF: sub_38736+91j .text:000387EF ; sub_38736+9Fj .text:000387EF ; sub_38736+A8j .text:000387EF mov ecx, [ebp+var_20] .text:000387F2 mov edx, [ecx+0Ch] .text:000387F5 mov [ebp+var_38], edx .text:000387F8 mov eax, [ebp+var_38] .text:000387FB shr eax, 10h .text:000387FE mov [ebp+var_44], eax .text:00038801 cmp [ebp+var_44], 8302h .text:00038808 jnz loc_3983C .text:00038808 .text:0003880E cmp [ebp+var_38], 83022227h .text:00038815 jnb short loc_38854 .text:00038815 .text:00038817 cmp dword_4B0DC, 0 .text:0003881E jnz short loc_38842 .text:0003881E .text:00038820 call ds:KeEnterCriticalRegion .text:00038826 mov ecx, offset stru_4B060 ; FastMutex .text:0003882B call ds:ExAcquireFastMutexUnsafe .text:00038831 mov ecx, offset stru_4B060 ; FastMutex .text:00038836 call ds:ExReleaseFastMutexUnsafe .text:0003883C call ds:KeLeaveCriticalRegion .text:0003883C .text:00038842 .text:00038842 loc_38842: ; CODE XREF: sub_38736+E8j .text:00038842 cmp dword_4B258, 0 .text:00038849 jnz short loc_38854 .text:00038849 .text:0003884B mov ecx, [ebp+var_38] .text:0003884E push ecx .text:0003884F call sub_16E17 .text:0003884F .text:00038854 .text:00038854 loc_38854: ; CODE XREF: sub_38736+DFj .text:00038854 ; sub_38736+113j 以下开始处理 ControlCode,他们基本都被定义为 METHOD_NEITHER 这种方式 .text:00038854 mov edx, [ebp+var_38] ; edx = ControlCode .text:00038857 mov [ebp+var_F0], edx .text:0003885D cmp [ebp+var_F0], 830221E7h .text:00038867 ja loc_38985 ; 如果ConrolCode > 830221E7h 则跳转 .text:00038867 .text:0003886D cmp [ebp+var_F0], 830221E7h .text:00038877 jz loc_38F5E .text:00038877 .text:0003887D cmp [ebp+var_F0], 830221BFh .text:00038887 ja loc_38952 .text:00038887 .text:0003888D cmp [ebp+var_F0], 830221BFh .text:00038897 jz loc_38C2C .text:00038897 .text:0003889D cmp [ebp+var_F0], 830221A7h .text:000388A7 ja short loc_3891F .text:000388A7 .text:000388A9 cmp [ebp+var_F0], 830221A7h .text:000388B3 jz loc_38BB0 .text:000388B3 .text:000388B9 cmp [ebp+var_F0], 8302219Ah .text:000388C3 ja short loc_388FA .text:000388C3 .text:000388C5 cmp [ebp+var_F0], 8302219Ah .text:000388CF jz loc_38E15 .text:000388CF .text:000388D5 cmp [ebp+var_F0], 83022003h .text:000388DF jz loc_38B49 ; 注意这里 .text:000388DF .text:000388E5 cmp [ebp+var_F0], 83022196h .text:000388EF jz loc_38DD5 .text:000388EF .text:000388F5 jmp loc_392EE 其上的很多控制码都存在问题,当然最好利用的控制码就是 83022003h 了,我们来看看 symtdi.sys 中如何处理 83022003h loc_38B49: ; CODE XREF: sub_38736+1A9j .text:00038B49 mov ecx, [ebp+Irp] .text:00038B4C mov edx, [ecx+3Ch] ; edx = irp->UserBuffer .text:00038B4F mov [ebp+var_24], edx .text:00038B52 mov eax, [ebp+var_20] .text:00038B55 mov ecx, [eax+4] .text:00038B58 mov [ebp+var_40], ecx .text:00038B5B mov edx, [ebp+var_40] .text:00038B5E push edx .text:00038B5F mov eax, [ebp+var_24] .text:00038B62 push eax .text:00038B63 call sub_3B7B0 sub_3B7B0 proc near ; CODE XREF: sub_38736+42Dp .text:0003B7B0 .text:0003B7B0 var_4 = dword ptr -4 .text:0003B7B0 arg_0 = dword ptr 8 .text:0003B7B0 arg_4 = dword ptr 0Ch .text:0003B7B0 .text:0003B7B0 push ebp .text:0003B7B1 mov ebp, esp .text:0003B7B3 push ecx .text:0003B7B4 mov [ebp+var_4], 0 .text:0003B7BB cmp [ebp+arg_0], 0 .text:0003B7BF jz short loc_3B7EB .text:0003B7BF .text:0003B7C1 cmp [ebp+arg_4], 9 .text:0003B7C5 jb short loc_3B7EB .text:0003B7C5 .text:0003B7C7 mov eax, [ebp+arg_0] ; eax = irp->UserBuffer 以前没有对irp->UserBuffer进行任何检查 .text:0003B7CA mov ecx, dword_45544 .text:0003B7D0 mov [eax], ecx ; 以下是对UserBuffer进行写操作,一共写入了9字节,形成了任意内核地址可写的漏洞 .text:0003B7D2 mov edx, dword_45548 .text:0003B7D8 mov [eax+4], edx .text:0003B7DB mov cl, byte_4554C .text:0003B7E1 mov [eax+8], cl .text:0003B7E4 mov [ebp+var_4], 9 .text:0003B7E4 .text:0003B7EB .text:0003B7EB loc_3B7EB: ; CODE XREF: sub_3B7B0+Fj .text:0003B7EB ; sub_3B7B0+15j .text:0003B7EB mov eax, [ebp+var_4] .text:0003B7EE mov esp, ebp .text:0003B7F0 pop ebp .text:0003B7F1 retn 8 .text:0003B7F1 .text:0003B7F1 sub_3B7B0 endp 看完代码,我们大家已经很清楚地知道了这个漏洞如何利用,我们可以去Hook一个SSDT上的函 数,在我们进行调用被Hook的函数时,有机会让我们的ring0代码得到运行,Hook的函数我依旧 选择 NtVdmControl,虽然这里覆盖了9字节的数据,但是由于NtVdmControl后面的一个函数也 为一个不常用的api,所以我们的exploit可以保证%80以上的有效率,但是一定要在调用ring 0 代码的时候进行一些现场恢复,不然一定会死的比较难看的。 在发现这个漏洞的兴奋之余,我上网搜索了一下 symtdi.sys,发现在今年3月份国外已经有人发 现了这个漏洞,不过报告为拒绝服务,然而厂商估计是因为认为这个漏洞的安全级别比较低,也 没有对这个漏洞进行修补,希望安全厂商能够报着为用户负责的心态尽快修补该漏洞,如果对 以上还有什么问题请发送邮件到 [email protected] 联系我,谢谢。 |