![]() |
2008-09-04
Pointers and Handles - A Story of Unchecked Assumptions in the Windows Kernel Last month on Black Hat conference Alex Ionescu presented several vulnerabilities discovered in Win32k.sys. In first part of the presentation Alex discussed a couple of unchecked pointer dereferences. In the second part (most focused) he discussed about user-mode accessible handles, and incorrect usage of Nt/Zw APIs when dealing with user-mode data. Alex wrote that calling NtUserGetThreadState or NtUserGetDCEx from Client Server Runtime Process (csrss.exe) can cause immediately BSoD. But there is another one function that dereferences Win32ThreadInfo->Desktop - NtUserGetWindowDC. I wrote three demonstration DoS exploits. One for NtUserGetDCEx, NtUserGetWindowDC and NtUserCloseWindowStation. In the last one I used different scenario then Alex Ionescu showed on his blog. Firstly we look for handle of WindowStation then set ProtectFromClose attribute and finally call NtUserCloseWindowStation. References: Black Hat 2008 Wrap-up Exploits: NtUserGetDCEx_DoS.zip - Local Denial of Service Exploit NtUserGetWindowDC_DoS.zip - Local Denial of Service Exploit NtUserCloseWindowStation_DoS.zip - Local Denial of Service Exploit Looking for vulnerabilities in different drivers I found a driver which allows any user to call ZwClose directly by supplying a specially crafted Irp to the IOCTL handler function.
...
.text:00012572 @@ioctl_close_handle:
.text:00012572 cmp dword ptr [eax+4], 210h ; OutputBufferLength
.text:00012579 jb @@invalid_buffer_size
.text:0001257F mov eax, [ebx+0Ch] ; SystemBuffer
.text:00012582 push dword ptr [eax+208h]
.text:00012588 call ds:ZwClose
...
2008-09-21 DESlock+ - 3.2.7 (vdlptokn.sys) - Local Denial of Service Exploit At the beginning of the year mu-b of digit-labs published information about few serious vulnerabilities he found in drivers distributed with DESlock+ - DESLock+ IOCTL Request Local Code Execution and Denial of Service Vulnerabilities. Yesterday he placed on digit-labs another exploits to prove that vulnerabilities in latest version of DESlock+ still exists. I decided to publish sample DoS exploit related with vdlptokn.sys device driver. I hope that this time Data Encryption Systems will correct all vulnerabilities. Exploit: Vdlptoken_DoS.zip - Local Denial of Service Exploit 2008-10-01 ESET SysInspector - 1.1.1.0 (esiadrv.sys) Proof of Concept Exploit ESET SysInspector is prone to a local privilege escalation vulnerability, which could be exploited by local users in order o execute arbitrary code with kernel privileges. The problem specifically exists within the IOCTL handling code in the esiadrv.sys (3.0.65535.0) device driver. The device driver fails to validate user supplied addresses passed to IOCTLs. All IOCTLs are generated as METHOD_NEITHER. Although this is not serious vulnerability because the device driver is loaded and unloaded dynamically with the GUI application.
...
.text:00012C3A @@ioctl_0x223C1F:
.text:00012C3A mov eax, [ebp+10h] ; InputBuffer
.text:00012C3D cmp eax, ebx
.text:00012C3F jz short @@jump
.text:00012C41 cmp [ebp+14h], edi ; InputBufferLength
.text:00012C44 jnz short @@jump
.text:00012C46 cmp dword ptr [eax], 12345678h ; InputBuffer[0] == 0x12345678 ?
.text:00012C4C jnz short @@jump
.text:00012C4E push offset aBsodCalled ; "BSOD called\n"
.text:00012C53 call DbgPrint
.text:00012C58 pop ecx
.text:00012C59 push 0DEADDEADh
.text:00012C5E call ds:KeBugCheck
.text:00012C64
.text:00012C64 @@jump:
.text:00012C64 mov esi, [ebp+18h] ; OutputBuffer
.text:00012C67 cmp esi, ebx
.text:00012C69 jz short @@invalid_parameter
.text:00012C6B cmp [ebp+1Ch], edi ; OutputBufferLength
.text:00012C6E jb short @@invalid_parameter
.text:00012C70 mov [ebp+10h], ebx
.text:00012C73 lea eax, [ebp+10h]
.text:00012C76 push eax
.text:00012C77 push dword ptr [ebp+28h] ; DeviceObject
.text:00012C7A call sub_148EC
.text:00012C7F mov [ebp-1Ch], eax
.text:00012C82 mov eax, [ebp+10h]
.text:00012C85 mov [esi], eax ; OutputBuffer[0] - ?x????????
.text:00012C87 mov [ebp-20h], edi
.text:00012C8A jmp short @@return
...
Exploit: Esiasdrv_DoS.zip - Local Denial of Service Exploit 2009-07-30 Windows XP SP2/SP3 (NtUserConsoleControl) - Local Privilege Escalation Several days ago Jonathan Ness added informational entries on Security Research & Defense blog concerning Windows XP kernel 0day claim in win32k!NtUserConsoleControl [1]. Jonathan explains that unchecked pointers in privileged services like NtUserConsoleControl are rather reliability issues, not security vulnerabilities. Some of the services provided by Multi-User Win32 Driver (win32k.sys) are intended to be called only by Client Server Runtime Process (csrss.exe). One of them is NtUserInitialize which is used for Win32 subsystem initialization. NtUserInitialize checks if global variable gpepCSRSS was initialized already, if so STATUS_UNSUCCESSFUL status is returned, otherwise the address of the caller's process object is stored in gpepCSRSS. Privileged services can be recognized by constant prologue of their body. Before the service will do its job, it checks that the caller's process object is equal to gpepCSRSS, if not service returns STATUS_ACCESS_DENIED. This is a list of privileged services: - NtUserRemoteConnect(x, x, x) - NtUserSetInformationThread(x, x, x, x) - NtUserConsoleControl(x, x, x) - NtUserSetInformationProcess(x, x, x, x) - NtUserNotifyProcessCreate(x, x, x, x) - NtUserRemoteRedrawScreen() - NtUserRemoteStopScreenUpdates() - NtUserCtxDisplayIOCtl(x, x, x) - NtUserHardErrorControl(x, x, x) - NtUserQueryInformationThread(x, x, x, x, x) - NtGdiFullscreenControl(x ,x ,x ,x ,x) Few internal functions are invoked by: - NtUserCallNoParam(x) - NtUserCallOneParam(x, x) - NtUserCallTwoParam(x, x, x) Only one service - NtGdiFullscreenControl - uses parameters validation, other services and internal functions trust to all passed parameters. It is true that only an administrator can play with this issue, but like in the case of access to \Device\PhysicalMemory [4][5][7] and some functionality provided by NtSystemDebugControl service [6][7], this functionality allows malicious software to get into the kernel of forbidden way (the only correct way of calling into the kernel is to invoke NtLoadDriver service), without paying attention to security software. Like in other cases this functionality was removed in Windows 2003 SP1.
.text:BF8E5400 ; __stdcall NtUserConsoleControl(x, x, x)
.text:BF8E5400 NtUserConsoleControl proc near
.text:BF8E5400
.text:BF8E5400 ConsoleCommand = dword ptr 8
.text:BF8E5400 ConsoleInformation = dword ptr 0Ch
.text:BF8E5400 ConsoleInformationLength = dword ptr 10h
.text:BF8E5400
.text:BF8E5400 mov edi, edi
.text:BF8E5402 push ebp
.text:BF8E5403 mov ebp, esp
.text:BF8E5405 push esi
.text:BF8E5406 call EnterCrit
.text:BF8E540B call ds:PsGetCurrentProcess
.text:BF8E5411 cmp eax, gpepCSRSS
.text:BF8E5417 jnz short @@status_access_denied
.text:BF8E5419 push [ebp+ConsoleInformationLength]
.text:BF8E541C push [ebp+ConsoleInformation]
.text:BF8E541F push [ebp+ConsoleCommand]
.text:BF8E5422 call xxxConsoleControl
.text:BF8E5427 mov esi, eax
.text:BF8E5429
.text:BF8E5429 @@return:
.text:BF8E5429 call LeaveCrit
.text:BF8E542E mov eax, esi
.text:BF8E5430 pop esi
.text:BF8E5431 pop ebp
.text:BF8E5432 retn 0Ch
.text:BF8E5435
.text:BF8E5435 @@status_access_denied:
.text:BF8E5435 mov esi, 0C0000022h
.text:BF8E543A jmp short @@return
.text:BF8E543A NtUserConsoleControl endp
The easiest way to exploit this issue is to call NtUserConsoleControl with control code equal seven. The malicious user doesn't even need to prepare and pass a valid buffer. If the buffer at index zero points to invalid desktop's object handle, invoked function ObReferenceObjectByHandle will return applied status which will cause immediate exit from the main function. But before calling ObReferenceObjectByHandle the main function overwrites the buffer at index three with zero. This allows to overwrite any address with zero value. The issue of privileged services was touch a couple of months ago [3], but ostentatious exploit was provided only on July 11 by Azy [2]. I prepared another ostentatious piece of code which exploiting this issue. Exploit: NtUserConsoleControl_Exp.zip - Local Privilege Escalation Exploit References: [1] - Latest Baidu public posting requires Adminisrator to elevate [2] - [0day] Windows kernel vulnerability [3] - Accessing memory in the context of csrss [4] - NT's "\dev\kmem" [5] - Playing with Windows /dev/(k)mem [6] - Multiple Windows XP Kernel Vulnerability Allow User Mode Programs To Gain Kernel Privileges [7] - Subverting Windows 2003 SP1 Kernel Integrity Protection 2009-10-22 Hidden Data Detection Softwares I've created the list of anti rootkit (and related to anti rootkit) software. I suppose, that this list is incomplete and contains out-of-date software. I'll be grateful for any information about latest versions of listed software and propositions of software not presented on this list. I admit that in the near future I'm going to use this software to comparative tests. 2009-10-30 Hidden Dynamic-Link Library Detection Test According to mentioned comparative tests I've published results of Hidden Dynamic-Link Library Detection Test. This article is a small introduction to test series I've begun. In the next part I will share results of hidden process/thread detection. 2009-12-02 Hidden Process Detection Test Today I've published results of Hidden Process Detection Test. This test includes short demonstrational movie of process hiding using the testing tool - Invisible Process 1.0. In this movie I show final results of process detection by the most advanced software. Next time I'll share results of Hidden Kernel Module Detection Test. 2010-01-23 Microsoft Windows NT #GP Trap Handler Allows Users to Switch Kernel Stack Few days ago, Tavis Ormandy has published (Microsoft Windows NT #GP Trap Handler Allows Users to Switch Kernel Stack) interesting vulnerability he found in Windows' support for Intel's hardware 8086 emulation support. This really old vulnerability is related to other vulnerability discovered by Derek Soeder - EEYE: Windows VDM #UD Local Privilege Escalation. Tavis Ormandy has published also a PoC exploit which can be downloaded here - KiTrap0D.zip. Few days earlier Matthew "j00ru" Jurczyk and Gynvael Coldwind have published a paper (GDT and LDT in Windows kernel vulnerability exploitation) which "describes some possible ways of exploiting kernel-mode write-what-where vulnerabilities in a stable manner, on Microsoft Windows NT-family systems". Technique described in this paper is suitable for situations where the attacker is able to overwrite only 1 byte of the protected memory. I decided to accelerate disclosure of a few advisories (NTIADV0805, NTIADV0808, NTIADV0902). I'm also going to introduce some changes in Vulnerability Disclosure Process. 2010-01-28 Is RISING Antivirus 2008/2009/2010 still vulnerable? Last Saturday I've published two advisories related to RISING Antivirus software. While checking latest version of this software I only checked software provided on http://www.rising-global.com/ where can be downloaded RISING Antivirus 2009 in version 21.67.14.00. Today I was noticed that there is available RISING Antivirus 2010 which certainly should contain fixed device drivers. I've checked this version (22.00.02.76 - it can be downloaded here - http://rsdownload.rising.com.cn/for_down/ravdver/risol.exe) and I confirm that this version is also vulnerable. As proof I'm providing sample exploit - RsNTGdi_Exp.zip. I'm also composing a new advisory since I found another vulnerability in RISING Antivirus 2010. 2010-02-14 Hidden Driver Detection Test It is high time to publish another part of Hidden Data Detection Software test series - Hidden Driver Detection Test. 2010-05-26 Dangerous Hot Patching feature of KingSoft software. Three days ago (Xuanyuan Smart) published a Proof of Concept which exploits Hot Patching feature of KAVSafe.sys device driver which is shipped with KingSoft WebShield. About two months earlier I've analyzed KingSoft software and found this vulnerability as well. I've observed that not only KAVSafe.sys shipped with KingSoft WebShield is vulnerable, there are other drivers (KAVBase.sys, KAVBootC.sys, BC.sys) shipped with almost all KingSoft products which have the same feature as KAVSafe.sys. All devices created by vulnerable drivers have default security descriptors, so they are accessible by all users including unprivileged/non-administrative users. Some of drivers have implementad a piece of code which is called during device handle oppening event (IRP_MJ_CREATE). This code checks if the image path of the process which trying to open handle of the device ("\Device\KAVSafe" in case of KAVSafe.sys driver) is located in a default installation folder of WebShield software. And because KAVSafe.sys compares data obtained from registry with data stored in PEB of the caller process, the caller process can manipulate PEB's data before trying to open device handle to fool this mechanism - exactly as in the PoC exploit.
.text:00012120 ; int __stdcall Ioctl_HotPatch_0x830020D4(int, int, int, int, int)
.text:00012120 Ioctl_HotPatch_0x830020D4 proc near
.text:00012120
.text:00012120 LocalInputBuffer = dword ptr -8
.text:00012120 ByteCounter = dword ptr -4
.text:00012120 InputBuffer = dword ptr 8
.text:00012120 InputBufferLength = dword ptr 0Ch
.text:00012120 OutputBuffer = dword ptr 10h
.text:00012120 OutputBufferLength = dword ptr 14h
.text:00012120 IoStatus = dword ptr 18h
.text:00012120
.text:00012120 push ebp
.text:00012121 mov ebp, esp
.text:00012123 sub esp, 8
.text:00012126 mov [ebp+ByteCounter], 0
.text:0001212D mov eax, [ebp+InputBuffer]
.text:00012130 mov [ebp+LocalInputBuffer], eax
.text:00012133 mov ecx, [ebp+IoStatus]
.text:00012136 mov dword ptr [ecx], 0C0000001h
.text:0001213C mov edx, [ebp+IoStatus]
.text:0001213F mov dword ptr [edx+4], 0
.text:00012146 cmp [ebp+InputBuffer], 0
.text:0001214A jz short __exit__enabple_wp_exit
.text:0001214C cmp [ebp+InputBufferLength], 4Ch
.text:00012150 jb short __exit__enabple_wp_exit
.text:00012152 mov eax, [ebp+LocalInputBuffer]
.text:00012155 mov ecx, [eax+44h] ; PatchSize
.text:00012158 push ecx ; HotPatchCodeSize
.text:00012159 mov edx, [ebp+LocalInputBuffer]
.text:0001215C add edx, 48h
.text:0001215F push edx ; HotPatchCode
.text:00012160 mov eax, [ebp+LocalInputBuffer]
.text:00012163 mov ecx, [eax+40h] ; FunctionAddress
.text:00012166 push ecx ; CodeAddressOffset
.text:00012167 mov edx, [ebp+LocalInputBuffer]
.text:0001216A push edx ; ModuleName
.text:0001216B mov ecx, offset unk_1C258
.text:00012170 call HotPatchKernelModule
.text:00012175 mov [ebp+ByteCounter], eax
.text:00012178 cmp [ebp+ByteCounter], 0
.text:0001217C jz short __exit__enabple_wp_exit
.text:0001217E mov eax, [ebp+IoStatus]
.text:00012181 mov ecx, [ebp+ByteCounter]
.text:00012184 mov [eax+4], ecx
.text:00012187 mov edx, [ebp+IoStatus]
.text:0001218A mov dword ptr [edx], 0
.text:00012190
.text:00012190 __exit__enabple_wp_exit:
.text:00012190 mov eax, [ebp+IoStatus]
.text:00012193 mov eax, [eax]
.text:00012195 mov esp, ebp
.text:00012197 pop ebp
.text:00012198 retn 14h
.text:00012198 Ioctl_HotPatch_0x830020D4 endp
Input buffer passed to the device dispatch routine contains four items: first item - contains name of the kernel module which will be patched, second - an offset of the function (code), third - size of the new code, and finally fourth item contains the new code. In a first phase of hot patching, the "GetModuleBaseByName" function walks through linked list of loaded kernel modules (DriverObject->DriverSection), looking for module which name is equal to name sent in a IOCTL request. If appropriate module will be found, function returns a module base which will be added to the offset (second item of the IOCTL buffer).
.text:0001B280 ; int __stdcall HotPatchKernelModule(int, int, int, int)
.text:0001B280 HotPatchKernelModule proc near
.text:0001B280
.text:0001B280 var_14 = dword ptr -14h
.text:0001B280 CodeSize = dword ptr -10h
.text:0001B280 var_C = dword ptr -0Ch
.text:0001B280 ModuleBase = dword ptr -8
.text:0001B280 LocalOffset = dword ptr -4
.text:0001B280 ModuleName = dword ptr 8
.text:0001B280 CodeAddressOffset = dword ptr 0Ch
.text:0001B280 HotPatchCode = dword ptr 10h
.text:0001B280 HotPatchCodeSize = dword ptr 14h
.text:0001B280
.text:0001B280 push ebp
.text:0001B281 mov ebp, esp
.text:0001B283 sub esp, 14h
.text:0001B286 mov [ebp+var_14], ecx
.text:0001B289 mov [ebp+CodeSize], 0
.text:0001B290 mov [ebp+var_C], 0
.text:0001B297 mov [ebp+ModuleBase], 0
.text:0001B29E mov [ebp+LocalOffset], 0
.text:0001B2A5 call DisableWriteProtect
.text:0001B2AA lea eax, [ebp+var_C]
.text:0001B2AD push eax
.text:0001B2AE mov ecx, [ebp+ModuleName]
.text:0001B2B1 push ecx
.text:0001B2B2 mov ecx, [ebp+var_14]
.text:0001B2B5 call GetModuleBaseByName
.text:0001B2BA mov [ebp+ModuleBase], eax
.text:0001B2BD cmp [ebp+ModuleBase], 0
.text:0001B2C1 jnz short __module_loaded
.text:0001B2C3 jmp short __enabple_wp_exit
.text:0001B2C5
.text:0001B2C5 jmp short __enabple_wp_exit
.text:0001B2C7
.text:0001B2C7
.text:0001B2C7 __module_loaded:
.text:0001B2C7 mov edx, [ebp+HotPatchCodeSize]
.text:0001B2CA cmp edx, [ebp+var_C]
.text:0001B2CD jbe short __save_code_size
.text:0001B2CF jmp short __enabple_wp_exit
.text:0001B2D1
.text:0001B2D1 jmp short __enabple_wp_exit
.text:0001B2D3
.text:0001B2D3
.text:0001B2D3 __save_code_size:
.text:0001B2D3 mov eax, [ebp+HotPatchCodeSize]
.text:0001B2D6 mov [ebp+CodeSize], eax
.text:0001B2D9 mov [ebp+LocalOffset], 0
.text:0001B2E0 jmp short __is_address_valid
.text:0001B2E2
.text:0001B2E2 __loop:
.text:0001B2E2 mov ecx, [ebp+LocalOffset]
.text:0001B2E5 add ecx, 1
.text:0001B2E8 mov [ebp+LocalOffset], ecx
.text:0001B2EB
.text:0001B2EB __is_address_valid:
.text:0001B2EB mov edx, [ebp+LocalOffset]
.text:0001B2EE cmp edx, [ebp+CodeSize]
.text:0001B2F1 jge short __enabple_wp_exit
.text:0001B2F3 mov eax, [ebp+ModuleBase]
.text:0001B2F6 add eax, [ebp+CodeAddressOffset]
.text:0001B2F9 add eax, [ebp+LocalOffset]
.text:0001B2FC push eax
.text:0001B2FD call ds:MmIsAddressValid
.text:0001B303 movzx ecx, al
.text:0001B306 test ecx, ecx
.text:0001B308 jnz short __patch_byte
.text:0001B30A jmp short __enabple_wp_exit
.text:0001B30C
.text:0001B30C __patch_byte:
.text:0001B30C mov edx, [ebp+ModuleBase]
.text:0001B30F add edx, [ebp+CodeAddressOffset]
.text:0001B312 mov eax, [ebp+HotPatchCode]
.text:0001B315 add eax, [ebp+LocalOffset]
.text:0001B318 mov ecx, [ebp+LocalOffset]
.text:0001B31B mov al, [eax]
.text:0001B31D mov [edx+ecx], al
.text:0001B320 jmp short __loop
.text:0001B322
.text:0001B322 __enabple_wp_exit:
.text:0001B322 call EnablaWriteProtect
.text:0001B327 mov eax, [ebp+LocalOffset]
.text:0001B32A mov esp, ebp
.text:0001B32C pop ebp
.text:0001B32D retn 10h
.text:0001B32D HotPatchKernelModule endp
Finally "HotPatchKernelModule" function checks if the address of code to patch "is valid" - wasn't paged out, and if so, it copies a new code (byte by byte) at specified address. Affected Software: Kingsoft WebShield KAVSafe.sys <= 2010.4.14.609 Kingsoft Internet Security 9 Plus KAVSafe.sys - Kingsoft Antivirus Defend Engine Safe Module <= 2009.8.10.138 KAVBase.sys - KAVBase Application <= 2009.6.17.160 KAVBootC.sys - Kingsoft Antivirus Defend Engine Bootclean Module <= 2009.8.10.138 Kingsoft Antivirus Security System BC.sys - Kingsoft Boot safe <= 2010.4.7.88 Kingsoft Antivirus Online KAVBootC.sys - Kingsoft Boot Clean <= 2008.4.28.85 Kingsoft Anti-Spyware KAVBootC.sys - Kingsoft Boot Clean <= 2008.4.28.85 Kingsoft Internet Security 2011 KAVSafe.sys - Kingsoft Antivirus Defend Engine Safe Module <= 2010.4.14.609 Kingsoft System Cleaner BC.sys - Kingsoft Boot safe <= 2010.4.7.88 KAVSafe.sys - Kingsoft Antivirus Defend Engine Safe Module <= 2010.4.14.609 Note: Other products and versions may also be affected. Non-Affected Software: Kingsoft KSafe Kingsoft Antivirus XEngine System |