Anatomy of Turla exploits

2014-05-01

Wayne Low

F-Secure, Finland
Editor: Helen Martin

Abstract

Elevation of privilege (EoP) vulnerabilities can allow a program to run arbitrary code, regardless of that program’s current permission level – as a result, they draw a lot of attention from malware authors. Wayne Low describes two of the EoP vulnerabilities exploited by the Turla malware family.


Nowadays, most computer users are taught not to open executable files from an unknown source. They are also encouraged to log into their computer using a limited user account instead of the administrator account, because in the event of a malicious file unwittingly being run, the restricted permission settings of a user account would serve as a passive mitigation tactic to prevent unrestricted access to the system and/or data on the machine, thereby limiting the extent of any possible damage.

However, in some circumstances logging in as an administrator is unavoidable. To allow for this eventuality while still making a malware author’s life more challenging, Microsoft introduced the User Account Control (UAC) feature to its operating systems, starting with Windows Vista.

One way in which the UAC feature can be circumvented is to gain an elevation of privilege – which allows someone who only has access to a limited user account environment to perform actions that would otherwise be restricted to the administrator’s account. This is why an elevation of privilege (EoP) vulnerability draws a lot of attention from malware authors.

This article focuses on EoP vulnerabilities exploited by the Turla malware family, discovered by G Data [1], which is not only involved in cyber-espionage but is also used in the sphere of vulnerability exploitation.

What is an elevation of privilege vulnerability?

An EoP vulnerability is a flaw or loophole in a piece of software which, if successfully exploited, could allow a program to run arbitrary code, regardless of that program’s current permission level.

Typically, to gain an elevation of privilege for their malicious programs on the Windows OS, malware authors will exploit an EoP vulnerability in the Windows kernel. If the exploitation is successful, an exploit program running in the standard user account context may be escalated to the context of the system account – meaning that it can perform any operation on the computer at the highest permission level, even though security features such as UAC are present.

Microsoft has issued patches for various Windows kernel vulnerabilities that can be leveraged in this way. However, attacks using these vulnerabilities are still effective against users who have not yet patched their systems.

Types of Turla exploits

Generally, Turla targets three EoP vulnerabilities: two in Microsoft Windows and one in Oracle VirtualBox. The good news is that these vulnerabilities have been patched and in each case the latest versions of the products are not vulnerable.

There are two Windows kernel vulnerabilities that are manipulated by Turla, namely MS09-025 and MS10-015. Researchers first spotted the MS09-025 vulnerability in the notorious cyber-espionage malware Stuxnet/Flame [2], while MS10-015 was discovered by Tavis Ormandy in 2010 [3]. After analysing a sample of the malware, we realized that the author first deploys the simpler exploit, then moves on to the more complex one if the prior exploitation is not successful.

Having proof-of-concept (POC) code available for an exploit can help researchers to gain a better understanding of how the exploitation works. We checked the Metasploit Framework for available POC code – the Framework is a handy platform not just for malware authors looking to adopt an exploit for malicious purposes, but also for security researchers trying to understand an exploit.

Currently, POC code is available for MS10-015 but not for MS09-025. The MS10-015 exploit was implemented and ported to the Metasploit Framework by the Metasploit team [4] shortly after the vulnerability itself was discovered. (We will skip analysis of MS10-015 in this article since source code is publicly available.)

Even though the MS09-025 exploit code is not available on the Metasploit Framework, researchers can reverse engineer samples to try to understand how the exploit works. Based on our analysis, we consider that MS09 025 is a pretty interesting vulnerability and can easily be exploited by using two undocumented Win32k native API functions.

MS09-025

According to the Microsoft Security Bulletin description of MS09-025, the vulnerability was caused by a Windows Driver Class registration and Windows Kernel Pointer Validation issue [5]. As shown in Figure 1, the first issue can easily be identified when the exploit sample is opened with IDA Pro.

Wrapper Win32k function leads to MS09-025.

Figure 1. Wrapper Win32k function leads to MS09-025.

Take note of the code highlighted in yellow in Figure 1, indicating a wrapper for the Win32k function described in the Microsoft Security Bulletin that will lead to elevation of privilege. The details of how this function causes the EoP vulnerability will be discussed later.

The entire exploitation work flow consists of five steps:

  1. Create a ‘Button’ class Windows object with an arbitrary Windows name.

  2. Customize the shellcode and return the shellcode entry point virtual address to the caller.

  3. Call the win32k!NtUserRegisterClassExWOW function to modify the upper 16 bit function address found in the gpsi.mpFnidPfn function table over the shellcode entry point address obtained in Step 2.

  4. Call the win32k!NtUserRegisterClassExWOW again to modify the lower 16 bits of the same function address as modified in Step 3.

  5. At this point, the vulnerability can be triggered via the win32k!NtUserMessageCall Win32k native function, which in turn executes the shellcode entry point.

In short, there are two vulnerable functions that are responsible for triggering this EoP vulnerability. However, these functions are not exported by the Windows library (DLL), but even if the vulnerable functions cannot be retrieved via the Windows library, it is still possible to execute them directly via a system call or SYSENTER instruction.

Call to the win32k!NtUserMessageCall function via the SYSENTER instruction.

Figure 2. Call to the win32k!NtUserMessageCall function via the SYSENTER instruction.

For instance, g_dwSSINtUserRegisterClassExWOW is a system call number or system service number that is used to identify which Windows system function will be executed by the kernel when a function is invoked from user-mode. The system call number may vary depending on the OS version. On Windows XP SP2, the system call number for win32k!NtUserRegisterClassExWOW is 0x1E8 and the system call number for win32k!NtUserMessageCall is 0x1CC.

Both of these function entry points are defined in the nt!KeServiceDescriptorTableShadow data structure:

kd> lmvm win32k
start  end  module name
bf800000 bf9c2800 win32k (pdb symbols) \symbols\win32k.pdb\8F51F3B8BFB742E49E1C50FC54A9630F2\win32k.pdb
  Loaded symbol image file: win32k.sys
  Mapped memory image file: \symbols\win32k.sys\47E0E1061c2800\win32k.sys
  Image path: \SystemRoot\System32\win32k.sys
  Image name: win32k.sys
  Timestamp:  Wed Mar 19 17:46:46 2008 (47E0E106)
  CheckSum:   001D1603
  ImageSize:  001C2800
  File version:    5.1.2600.3335
  Product version: 5.1.2600.3335
  File flags: 0 (Mask 3F)
  File OS:    40004 NT Win32
  File type:  3.7 Driver
  File date:  00000000.00000000
  Translations: 0409.04b0
  CompanyName:  Microsoft Corporation
  ProductName:  Microsoft® Windows® Operating System
  InternalName: win32k.sys
  OriginalFilename: win32k.sys
  ProductVersion:   5.1.2600.3335
  FileVersion:      5.1.2600.3335 (xpsp_sp2_gdr.080319-1240)
  FileDescription:  Multi-User Win32 Driver
  LegalCopyright:   © Microsoft Corporation. All rights reserved.
kd> dds nt!KeServiceDescriptorTableShadow l8
8055b6a0  80503940 nt!KiServiceTable
8055b6a4  00000000
8055b6a8  0000011c
8055b6ac  80503db4 nt!KiArgumentTable
8055b6b0  bf999980 win32k!W32pServiceTable
8055b6b4  00000000
8055b6b8  0000029b
8055b6bc  bf99a690 win32k!W32pArgumentTable
kd> dds win32k!W32pServiceTable + 1e8 * 4 l1
bf99a120  bf81f3f8 win32k!NtUserRegisterClassExWOW
kd> dds win32k!W32pServiceTable + 1cc * 4 l1
bf99a0b0  bf80ef95 win32k!NtUserMessageCall

We will first look into the win32k!NtUserRegisterClassExWOW function, which allows some kernel pointers to be overwritten in the Windows GUI subsystem device driver, win32k.sys, which in turn could result in arbitrary code execution.

Before calling win32k!NtUserRegisterClassExWOW, there are certain prerequisites that need to be satisfied in order to exploit the vulnerability properly:

  • The function ID (fnID) value must be provided as a function argument.

  • The WNDCLASSEX.cbWndExtra value must be provided as a function argument.

The following section will explain how the bogus values mentioned above can cause vulnerability when the vulnerable function (with bogus parameters) is called directly from user-mode.

After analysing the function, we deduced that the vulnerable code is located in the internal function beneath win32k!NtUserRegisterClassExWOW (see Figure 3).

Functions lying under the vulnerable function win32k!NtUserRegisterClassExWOW.

Figure 3. Functions lying under the vulnerable function win32k!NtUserRegisterClassExWOW.

(Click here to view a larger version of Figure 3.)

Basically, the vulnerable win32k!NtUserRegisterClassExWOW function eventually calls the win32k!InternalRegisterClassEx function. When the bogus values are passed directly as function parameters, it is easy to alter the values in the mpFnidPfn (fnID) table stored in the global SERVERINFO structure (see Figure 4), because the Windows kernel does not properly validate the parameters passed to this function. Note that _gpsi is a pointer to this structure [6].

SERVERINFO data structure.

Figure 4. SERVERINFO data structure.

The assembly code in Listing 1 shows the vulnerable code in the win32k!InternalRegisterClassEx function that modifies the fnID table.

.text:BF81EF6A mov   cx, [ebx+3Ch]  ; cx = WNDCLASSEX.cbWndExtra value
.text:BF81EF6E add   cx, 0A4h  ; ShellcodeAddress = WNDCLASSEX.cbWndExtra + sizeof(WND)
.text:BF81EF73 movzx eax, ax   ; eax = fnID index
.text:BF81EF76 and   eax, 0FFFF3FFFh  ; fnID = fnID&0xFFFF3FFF
.text:BF81EF7B mov   edx, _gpsi  ; global gpsi SERVERINFO structure
.text:BF81EF81 mov   [edx+eax*2-48Ch], cx ; Write ShellcodeAddress to gpsi data structure according to fnID

Listing 1: Vulnerable code in the win32k!InternalRegisterClassEx function that modifies the fnID table.

Listing 2 shows a snapshot of the _gpsi structure before the vulnerable function is executed, while Listing 3 shows a snapshot of the original values in the fnID table.

kd> dc poi(win32k!gpsi)
bc5d0650  00480031 00000000 00000400 bf90b69e  1.H.............
bc5d0660  bf80eda0 bf8f3cef bf915e4d bf80eda0  .....<..M^......
bc5d0670  bf80eda0 bf8e82ae bf915e6c bf915e6c  ........l^..l^..
bc5d0680  bf915e6c bf915e6c bf915e6c bf915e6c  l^..l^..l^..l^..
bc5d0690  bf915e6c bf915e6c bf915e6c bf90bf5b  l^..l^..l^..[...
bc5d06a0  bf92fee1 bf915e6c bf915e6c bf915e6c  ....l^..l^..l^..
bc5d06b0  bf915e6c bf83b682 bf886b77 bf842e42  l^......wk..B...
bc5d06c0  bf885a59 bf87c831 bf915e6c bf915e6c  YZ..1...l^..l^..

Listing 2: Snapshot of the _gpsi structure before the vulnerable function is executed.
kd> dc poi(win32k!gpsi) + c
bc5d065c  bf90b69e bf80eda0 bf8f3cef bf915e4d  .........<..M^..
bc5d066c  bf80eda0 bf80eda0 bf8e82ae bf915e6c  ............l^..
bc5d067c  bf915e6c bf915e6c bf915e6c bf915e6c  l^..l^..l^..l^..
bc5d068c  bf915e6c bf915e6c bf915e6c bf915e6c  l^..l^..l^..l^..
bc5d069c  bf90bf5b bf92fee1 bf915e6c bf915e6c  [.......l^..l^..
bc5d06ac  bf915e6c bf915e6c bf83b682 bf886b77  l^..l^......wk..
bc5d06bc  bf842e42 bf885a59 bf87c831 bf915e6c  B...YZ..1...l^..
bc5d06cc  bf915e6c bf834789 bf866280 bf915e6c  l^...G...b..l^..
 
Listing 3: Snapshot of the original values in the fnID table.

A pseudo-code exploits the vulnerability (shown in Figure 5).

Snippet of the function definition code that alters the kernel pointer in the fnID table.

Figure 5. Snippet of the function definition code that alters the kernel pointer in the fnID table.

We specify the target function address that we want to modify in LOWORDFnIdIndex as an index to the fnID table during the first function call to win32k!NtUserRegisterClassExWOW:

1. WORD LOWORDFnidIndex = 0x256;  
2. Wrapped_NtUserRegisterClassExWOW(LOWORDFnidIndex, L”cls1”);

After the first function call, the lower 16-bit target function address will be changed in the fnID table:

eax=00000256 ebx=bc6883f0 ecx=0000409d edx=0000005c esi=f4b15ce0 edi=bc68844c
eip=bf81ee8a esp=f4b15c14 ebp=f4b15c6c iopl=0  nv up ei pl nz na pe nc
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000  efl=00000206
win32k!InternalRegisterClassEx+0x13f:
bf81ee8a 6681c1a400  add  cx,0A4h
kd> ? cx + A4
Evaluate expression: 16705 = 00004141 

eax=00000256 ebx=bc6883f0 ecx=00004141 edx=bc5d0650 esi=f4b15ce0 edi=bc68844c
eip=bf81ee9d esp=f4b15c14 ebp=f4b15c6c iopl=0  nv up ei pl nz na pe nc
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000 efl=00000206
win32k!InternalRegisterClassEx+0x152:
bf81ee9d 66898c4274fbffff mov  word ptr [edx+eax*2-48Ch],cx ds:0023:bc5d0670=eda0
kd> ? poi(win32k!gpsi) + eax*2 - 48Ch
Evaluate expression: -1134754192 = bc5d0670

As can be seen in Listing 4, the lower 16-bit address of the pointer at 0xbc5d0670 has been changed.

kd> dc poi(win32k!gpsi) + c
bc5d065c  bf90b69e bf80eda0 bf8f3cef bf915e4d  .........<..M^..
bc5d066c  bf80eda0 bf804141 bf8e82ae bf915e6c  ....AA......l^..
bc5d067c  bf915e6c bf915e6c bf915e6c bf915e6c  l^..l^..l^..l^..
bc5d068c  bf915e6c bf915e6c bf915e6c bf915e6c  l^..l^..l^..l^..
bc5d069c  bf90bf5b bf92fee1 bf915e6c bf915e6c  [.......l^..l^..
bc5d06ac  bf915e6c bf915e6c bf83b682 bf886b77  l^..l^......wk..
bc5d06bc  bf842e42 bf885a59 bf87c831 bf915e6c  B...YZ..1...l^..
bc5d06cc  bf915e6c bf834789 bf866280 bf915e6c  l^...G...b..l^.. 

Listing 4: The lower 16-bit address of the pointer at 0xbc5d0670 has been changed.

We pass HIWORDFnidIndex for the second function call to win32k!NtUserRegisterClassExWOW:

1. WORD HIWORDFnidIndex = 0x257;  
2. Wrapped_NtUserRegisterClassExWOW(HIWORDFnidIndex, L”cls2”);

After the second function call, the higher 16-bit target function address will be changed in the fnID table:

eax=00000257 ebx=bc689138 ecx=0000409d edx=0000005c esi=f4b15ce0 edi=bc689194
eip=bf81ee8a esp=f4b15c14 ebp=f4b15c6c iopl=0  nv up ei pl nz na po nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000202
win32k!InternalRegisterClassEx+0x13f:
bf81ee8a 6681c1a400 add cx,0A4h
kd> ? cx + A4
Evaluate expression: 16705 = 00004141

eax=00000257 ebx=bc689138 ecx=00004141 edx=bc5d0650 esi=f4b15ce0 edi=bc689194
eip=bf81ee9d esp=f4b15c14 ebp=f4b15c6c iopl=0 nv up ei pl nz na po nc
cs=0008  ss=0010 ds=0023 es=0023  fs=0030 gs=0000 efl=00000202
win32k!InternalRegisterClassEx+0x152:
bf81ee9d 66898c4274fbffff mov word ptr [edx+eax*2-48Ch],cx ds:0023:bc5d0672=bf80
kd> ? poi(win32k!gpsi) + eax*2 - 48Ch
Evaluate expression: -1134754190 = bc5d0672

Finally, Listing 5 shows the content of the modified fnID table.

kd> dc poi(win32k!gpsi) + c
bc5d065c  bf90b69e bf80eda0 bf8f3cef bf915e4d  .........<..M^..
bc5d066c  bf80eda0 41414141 bf8e82ae bf915e6c  ....AAAA....l^..
bc5d067c  bf915e6c bf915e6c bf915e6c bf915e6c  l^..l^..l^..l^..
bc5d068c  bf915e6c bf915e6c bf915e6c bf915e6c  l^..l^..l^..l^..
bc5d069c  bf90bf5b bf92fee1 bf915e6c bf915e6c  [.......l^..l^..
bc5d06ac  bf915e6c bf915e6c bf83b682 bf886b77  l^..l^......wk..
bc5d06bc  bf842e42 bf885a59 bf87c831 bf915e6c  B...YZ..1...l^..
bc5d06cc  bf915e6c bf834789 bf866280 bf915e6c  l^...G...b..l^..

Listing 5: The content of the modified fnID table.

At this point, we can clearly see that the 32-bit function address at 0xbc5d0670 has been modified. Therefore we can conclude that the fnID table can be modified directly by calling win32k!NtUserRegisterClassExWOW – which was not intended to be called by any ordinary user-mode program.

Afterwards, arbitrary code can be executed through the win32k!NtUserMessageCall function using the appropriate parameter.

Code snippet that triggers arbitrary code.

Figure 6. Code snippet that triggers arbitrary code.

NtUserMessageCall function prototype.

Figure 7. NtUserMessageCall function prototype.

Looking at the function prototype of win32k!NtUserMessageCall, there are two crucial arguments that determine the success of arbitrary code execution:

  • Msg – Message ID, this can be any value in the range of 0x400 – 0x1FFFF

  • dwType – FNID types, this must be a specific value and is dependent on the target address that we modified in the fnID table.

Finally, the assembly code of win32k!NtUserMessageCall shows the usage of these values in the case of arbitrary code execution:

NtUserMessageCall
.text:BF80EFA5 mov  edi, edi
.text:BF80EFA7 push ebp
.text:BF80EFA8 mov  ebp, esp
.text:BF80EFAA sub  esp, 0Ch
.text:BF80EFAD push esi
.text:BF80EFAE push edi
.text:BF80EFAF call _EnterCrit@0 ; EnterCrit()
.text:BF80EFB4 mov  ecx, [ebp+hWnd]
.text:BF80EFB7 call @ValidateHwnd@4 ; ValidateHwnd(x)
.text:BF80EFBC mov  ecx, [ebp+dwType] ; ecx = dwType = 0xFFFFFFFF
.text:BF80EFBF mov  esi, eax
.text:BF80EFC1 test esi, esi
.text:BF80EFC3 jz short loc_BF80EF8A
.text:BF80EFC5 mov  eax, _gptiCurrent
.text:BF80EFCA mov  edx, [eax+28h]
.text:BF80EFCD mov  [ebp+var_C], edx
.text:BF80EFD0 lea  edx, [ebp+var_C]
.text:BF80EFD3 mov  [eax+28h], edx
.text:BF80EFD6 mov  [ebp+var_8], esi
.text:BF80EFD9 inc  dword ptr [esi+4]
.text:BF80EFDC
.text:BF80EFDC loc_BF80EFDC:  ; CODE XREF: NtUserMessageCall(x,x,x,x,x,x,x)-7j
.text:BF80EFDC mov  eax, [ebp+MsgID] ; eax = MsgID = 0x1234
.text:BF80EFDF and  eax, 1FFFFh
.text:BF80EFE4 cmp  eax, 400h
.text:BF80EFE9 jnb  short loc_BF80F026   
.text:BF80F026 loc_BF80F026:  ; CODE XREF: NtUserMessageCall(x,x,x,x,x,x,x)+44j
.text:BF80F026 push [ebp+ResultInfo]
.text:BF80F029 mov  eax, _gpsi
.text:BF80F02E push ebp+lParam]
.text:BF80F031 add  ecx, 6 ; ecx = 0xFFFFFFFF + 6 = 5 
.text:BF80F034 push [ebp+wParam]
.text:BF80F037 and  ecx, 1FFFFh ; ecx <= 0x1FFFF
.text:BF80F03A push [ebp+MsgID]
.text:BF80F03D push esi
.text:BF80F03E call dword ptr [eax+ecx*4+0Ch] ; Call our desired pointer address in modified fnID table
kd> ? poi(win32k!gpsi) + ecx * 4 + 0c
Evaluate expression: -1134754192 = bc5d0670
kd> dd bc5d0670 l1
bc5d0670  41414141

VirtualBox driver EoP vulnerability – disabling driver signature enforcement

Turla also targets the Oracle VirtualBox software for exploitation. The EoP vulnerability Turla exploits only exists on VirtualBox versions 1.6.2 and 1.6.0, and was first disclosed by CoreSecurity in 2008; the vendor patched the vulnerability within a month [6].

Turla takes advantage of a vulnerable VirtualBox device driver (VBoxDrv.sys) in order to bypass a very important Windows security feature called Driver Signature Enforcement (DSE), which was first introduced in Windows Vista. Starting with the 64-bit version of Windows Vista, the driver code signing policy for the Windows OS requires all driver code to have a digital signature, to increase the platform’s safety and stability [7]. This means that malware authors are required to sign their device drivers if they want to load their malicious driver code on a victim’s machine; without a valid digital signature, they must get rid of DSE in order for their malicious products to work.

The vulnerable VBoxDrv.sys is digitally signed by innotek. Turla’s author discovered an interesting way to utilize the VBoxDrv.sys driver to avoid DSE, which could then allow Turla’s own unsigned rootkit driver to be run. Getting rid of DSE becomes almost trivial with a five-step exploitation process.

In comparison to the Turla exploit sample, the proof-of-concept code presented by CoreSecurity [6] against this same vulnerability is very simplistic. It differs in that the exploit sample attempts to get rid of DSE and then make the arbitrary kernel code execution work. We will look into the details of the exploit sample in the next section.

Before the exploitation process takes place, however, it is important to locate the nt!g_CiEnabled global variable found in notskrnl.exe, which is essentially used by Windows to determine whether the code integrity check is enabled. In other words, one can manipulate nt!g_CiEnabled to disable DSE.

Five steps to disable driver signature enforcement

We won’t discuss how to obtain the nt!g_CiEnabled address (in brief, it can be found using a byte-pattern search method). The actual exploitation process will commence once the nt!g_CiEnabled address has been located. The process is pretty straightforward: it merely involves multiple calls to the DeviceIoControl API with specially crafted parameters passed directly to the vulnerable VBoxDrv.sys.

Code snippet that exploits the vulnerable VBoxDrv.sys.

Figure 8. Code snippet that exploits the vulnerable VBoxDrv.sys.

  • Step 1: Set and initialize VBoxDrv’s cookie using the I/O control code SUP_IOCTL_COOKIE (see Figure 9). There are some parameter validations – for instance, the cookie’s magic word and interface version (SUPDRVIOC_VERSION) must be defined according to the specific VirtualBox version (Figure 10).

    Send SUP_IOCTL_COOKIE to VirtualBox driver (Step 1).

    Figure 9. Send SUP_IOCTL_COOKIE to VirtualBox driver (Step 1).

    Important variables for VirtualBox’s cookie session initialization.

    Figure 10. Important variables for VirtualBox’s cookie session initialization.

    The SUPLDROPEN structure stores VM image data.

    Figure 11. The SUPLDROPEN structure stores VM image data.

  • Step 2. Open or create an image with a random name. In this case, the exploit sample creates a fake image with the name ‘a’, using the I/O control code SUP_IOCTL_LDR_OPEN (see Figure 12). In the VirtualBox device driver, this I/O control code checks whether an instance of the faked image exists; if it does not, it tells the device driver to allocate a buffer of a size specified in OpenLdrReq.u.In.cbImage in kernel memory. The buffer is supposed to hold the actual VM image data, but in this case, it will be used to store the shellcode. The result of the operation will return an image address, known as VMMR0, which will hold the bogus image data stored in the OpenLdrReq.u.Out.pvImageBase pointer.

    Send SUP_IOCTL_LDR_OPEN to VirtualBox driver (Step 2).

    Figure 12. Send SUP_IOCTL_LDR_OPEN to VirtualBox driver (Step 2).

  • Step 3. Load the fake image created in Step 2 using the I/O control code SUP_IOCTL_LDR_LOAD (see Figure 13). The purpose of this I/O control code is to copy the shellcode buffer from SUPLDRLOAD.u.In.achIm into SUPLDRLOAD.u.In.pvImageBase, which is a pointer to the VMMR0 image buffer.

    Send SUP_IOCTL_LDR_LOAD to VirtualBox driver (Step 3).

    Figure 13. Send SUP_IOCTL_LDR_LOAD to VirtualBox driver (Step 3).

    It is compulsory to initialize the entry point for the Virtual Machine Monitor (VMM) by specifying the entry point type in SUPLDRLOAD.u.In.eEPType as SUPLDRLOADEP_VMMR0. Another purpose of this I/O control code is to initialize the following VMMR0 entry point pointers:

    • pvVMMR0EntryInt

    • pvVMMR0EntryFast

    • pvVMMR0EntryEx

    When the VMM is entering the guest OS, the entry point at VMMR0 will be invoked. We can, however, control when to trigger the VMMR0 entry point.

  • Step 4. VBoxDrv.sys provides another way to load the VMMR0 entry point, via the pvVMMR0EntryFast pointer initialized in Step 3. Before this fast VMMR0 entry point can be put to use, it must be switched on using the I/O control code SUP_IOCTL_SET_VM_FOR_FAST.

  • Step 5. Finally, the shellcode can be activated via the fast VMMR0 entry point by using one of the following control codes:

    • SUP_IOCTL_FAST_DO_RAW_RUN

    • SUP_IOCTL_FAST_DO_HWACC_RUN

    • SUP_IOCTL_FAST_DO_NOP.

Figure 17 shows the responsible function code when one of the I/O control codes listed above is sent to VBoxDrv.sys. At label (1), the driver code checks whether or not the fast I/O control code has been requested. If it has been requested, it will execute the supdrvIOCtlFast() function. Upon executing this function, the shellcode illustrated in Figure 14 will be executed at label (2). This means that rc contains the value zero after the shellcode execution. When it comes to label (3), pIrp >UserBuffer, which is equivalent to the nt!g_ciEnabled address that was passed as the third parameter in the DeviceIoControl API call shown in Figure 16, will be assigned the value of zero from the rc variable. This effectively disables DSE, meaning that an unsigned rootkit driver can be loaded into the Windows kernel with no obstacles.

Shellcode zeroing out the EAX register.

Figure 14. Shellcode zeroing out the EAX register.

Send SUP_IOCTL_SET_VM_FOR_FAST to the VirtualBox driver (Step 4).

Figure 15. Send SUP_IOCTL_SET_VM_FOR_FAST to the VirtualBox driver (Step 4).

Send SUP_IOCTL_FAST_DO_NOP to the VirtualBox driver (Step 5).

Figure 16. Send SUP_IOCTL_FAST_DO_NOP to the VirtualBox driver (Step 5).

Code snippet showing I/O control code function entry point where the vulnerable code can be found.

Figure 17. Code snippet showing I/O control code function entry point where the vulnerable code can be found.

Conclusion

We have explored two of the vulnerabilities used by Turla, namely a vulnerability in the Windows GUI subsystem kernel driver win32k.sys, and a vulnerability in the VirtualBox driver. Each vulnerability exploitation serves a different purpose – either gaining full privileges in Windows or bypassing the Driver Signature Enforcement (DSE) security feature. Fortunately, the vulnerabilities have already been patched by the respective software vendors, so users of the latest versions of the software should not be affected by attempted exploitations. These exploits serve as clear examples of how important it is to make sure that installed software is always up to date.

Software patching is not a completely effective remedy for addressing the vulnerability in the VirtualBox driver – at least not until the driver’s certificate signature has been revoked; until then it is possible that other malware authors will abuse the same vulnerable VirtualBox driver in the near future.

Bibliography

[2] Gostev, A. Back to Stuxnet: the missing link. http://www.securelist.com/en/blog/208193568/Back_to_Stuxnet_the_missing_link.

[3] Ormandy, T. Microsoft Windows NT #GP Trap Handler Allows Users to Switch Kernel Stack. Seclists.org. http://seclists.org/fulldisclosure/2010/Jan/341.

[5] Microsoft Security Bulletin MS11-025 – Important. http://technet.microsoft.com/en-us/security/bulletin/ms09-025.

[10] j00ru//vx tech blog. A quick insight into the Driver Signature Enforcement. http://j00ru.vexillium.org/?p=377.

[11] Download VirtualBox (Old Builds): VirtualBox 1.6. https://www.virtualbox.org/wiki/Download_Old_Builds_1_6.

twitter.png
fb.png
linkedin.png
hackernews.png
reddit.png

 

Latest articles:

Nexus Android banking botnet – compromising C&C panels and dissecting mobile AppInjects

Aditya Sood & Rohit Bansal provide details of a security vulnerability in the Nexus Android botnet C&C panel that was exploited to compromise the C&C panel in order to gather threat intelligence, and present a model of mobile AppInjects.

Cryptojacking on the fly: TeamTNT using NVIDIA drivers to mine cryptocurrency

TeamTNT is known for attacking insecure and vulnerable Kubernetes deployments in order to infiltrate organizations’ dedicated environments and transform them into attack launchpads. In this article Aditya Sood presents a new module introduced by…

Collector-stealer: a Russian origin credential and information extractor

Collector-stealer, a piece of malware of Russian origin, is heavily used on the Internet to exfiltrate sensitive data from end-user systems and store it in its C&C panels. In this article, researchers Aditya K Sood and Rohit Chaturvedi present a 360…

Fighting Fire with Fire

In 1989, Joe Wells encountered his first virus: Jerusalem. He disassembled the virus, and from that moment onward, was intrigued by the properties of these small pieces of self-replicating code. Joe Wells was an expert on computer viruses, was partly…

Run your malicious VBA macros anywhere!

Kurt Natvig wanted to understand whether it’s possible to recompile VBA macros to another language, which could then easily be ‘run’ on any gateway, thus revealing a sample’s true nature in a safe manner. In this article he explains how he recompiled…


Bulletin Archive

We have placed cookies on your device in order to improve the functionality of this site, as outlined in our cookies policy. However, you may delete and block all cookies from this site and your use of the site will be unaffected. By continuing to browse this site, you are agreeing to Virus Bulletin's use of data as outlined in our privacy policy.