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.
Copyright © 2014 Virus Bulletin
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 , which is not only involved in cyber-espionage but is also used in the sphere of vulnerability exploitation.
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.
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 , while MS10-015 was discovered by Tavis Ormandy in 2010 . 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  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.
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 . As shown in Figure 1, the first issue can easily be identified when the exploit sample is opened with IDA Pro.
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:
Create a ‘Button’ class Windows object with an arbitrary Windows name.
Customize the shellcode and return the shellcode entry point virtual address to the caller.
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.
Call the win32k!NtUserRegisterClassExWOW again to modify the lower 16 bits of the same function address as modified in Step 3.
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.
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).
(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 .
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).
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.
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
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 .
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 . 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  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.
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.
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).
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.
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.
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:
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:
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.
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.
 Uroburos – highly complex espionage software with Russian roots. https://blog.gdatasoftware.com/blog/article/uroburos-highly-complex-espionage-software-with-russian-roots.html.
 Gostev, A. Back to Stuxnet: the missing link. http://www.securelist.com/en/blog/208193568/Back_to_Stuxnet_the_missing_link.
 Ormandy, T. Microsoft Windows NT #GP Trap Handler Allows Users to Switch Kernel Stack. Seclists.org. http://seclists.org/fulldisclosure/2010/Jan/341.
 Rapid7. Metasploit-framework. Github repository. https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/windows/local/ms10_015_kitrap0d.rb.
 Microsoft Security Bulletin MS11-025 – Important. http://technet.microsoft.com/en-us/security/bulletin/ms09-025.
 VirtualBox Privilege Escalation Vulnerability. http://www.coresecurity.com/content/virtualbox-privilege-escalation-vulnerability.
 Windows: Driver Signing Policy. http://msdn.microsoft.com/en-us/library/windows/hardware/ff548231%28v=vs.85%29.aspx.
 Windows: WNDCLASSEX structure. http://msdn.microsoft.com/en-us/library/windows/desktop/ms633577(v=vs.85).aspx.
 j00ru//vx tech blog. A quick insight into the Driver Signature Enforcement. http://j00ru.vexillium.org/?p=377.
 Download VirtualBox (Old Builds): VirtualBox 1.6. https://www.virtualbox.org/wiki/Download_Old_Builds_1_6.