Catching the Hacking Team’s System Access Token Thief Red-Handed
In their Youtube commercial, the infamous Hacking Team promises to their clients, who are typically government or law enforcement agencies, the ability to “look through [the customer’s] target’s eyes”. At the same time, they promise to do this by means of tools that are “stealth and untraceable, immune to any protection system […]”. Obviously, this attracted our attention…
Reading through the material that other security researchers have collected on the Hacking Team breach earlier this week, it comes at no surprise that we find many references to kernel exploits used by this group that injects their surveillance software into the kernel of a target system. In light of our recent blog series on kernel exploit analysis, we took a deeper look at one of these zero-day kernel exploits to see how our system behaves against it.
Raising Privileges and Bypassing SMEP
The internals of the kernel exploit have been covered in great detail by other blog-posts [1, 2], so we won’t repeat all of this here. In a nutshell, the exploit leverages a vulnerability in the Adobe Font Driver (atmfd.dll) allowing the attacker to overflow a data structure in kernel memory.
What is specifically interesting about the exploit discovered in the Hacking Team leak, is how the attackers (ab)use the vulnerability to elevate the privileges of their process. As we have explained in our previous blog post, most kernel-level exploits disable Supervisor Mode Execution Prevention (SMEP) to be able to call code in user memory with kernel (ring-0) privileges. The exploit we analyze in this post, on the other hand, has no need to execute shellcode in the context of the kernel.
Instead, the vulnerability allows the attacker to read and write arbitrary memory locations in kernel space, which is then used to steal the System access token and raise the privileges of the attacker’s process. This makes exploitation extremely stealthy, and works reliably even on systems with SMEP enabled, such as Windows 8 and later.
Stealing the System Access Token
Unfortunately (for the attacker) most structures in the operating system (OS) kernel are not well-documented, and they can change between different versions of the OS. Without the ability to call kernel code, which provides APIs and other utility methods for manipulating these structures in memory, it is essential to know the exact kernel memory layout as well as format of its data structures.
The Hacking Team exploit uses a very clever technique to overcome this problem, which is worth describing in a bit more detail:
Enumerating EPROCESS Structures: In a first step, the exploit code has to find a reference to the EPROCESS structure of its own process. To do this, the code calls NtQuerySystemInformation (passing SystemHandleInformation, 0x10), which returns information about all handles acquired by any process. The information is returned using the SYSTEM_HANDLE_INFORMATION structure
which reveals a structure’s address in kernel memory through the Object member.
To find the correct process handle, the code uses DuplicateHandle and then searches for the correct instance in the list of objects, obtaining the memory address of the EPROCESS object in kernel space.
Calculating Access Token Offset: Finding the locations of structures in kernel memory is only part of the story, however. To successfully steal another process’ privileges, the exploit needs to modify a few member variables of its EPROCESS structure, such as the PID (EPROCESS::UniqueProcessId) and access token (EPROCESS::Token).
However, as mentioned above, the layout of the structure and thus the position of these values within the structures (that is, their offsets in memory) may change arbitrarily between different OS versions.
To resolve these memory offsets, the attackers use another clever trick: they calculate the offsets from documented kernel interfaces. For example, PsGetProcessId is a well-documented, standardized API. This function takes a reference to an EPROCESS structure as argument, and returns the ProcessId. Clearly, this requires accessing the ProcessId member in the memory of the structure.
Thus, the exploit can use the PsGetProcessId function to find the required offsets: as one can see in the function disassembly:
In this case, the ProcessId is referenced at offset 0x84 inside the EPROCESS structure. To get this information, the exploit loads the kernel image from disk, finds the address of PsGetProcessId, and locates the offset inside the function by searching for the operand of the corresponding MOV opcode.
In the above assembly example, the offset can be easily found five bytes before the ret instruction (opcode 0xC2), which can also be seen in the assembly of the corresponding function from the exploit code, shown below:
Elevating Privileges: Once the memory layout (location of structures) as well as their format (offsets within the structures) are known, the exploit can elevate privileges of its own process. To do so, it traverses the ActiveProcessLinks, a doubly-linked list of EPROCESS structures of active processes, to find the System process entry (with PID 4):
From there, the exploit duplicates the access token into its own structure, essentially gaining the same (system) privileges.
Escaping Google Chrome
Over the last couple years, most browser vendors have improved their software’s security model by introducing various sandboxing mechanisms. For example, Google’s Chrome browser uses a multi-process architecture that restricts each browser component (e.g., rendering) to run within a separate process.
These processes are unable to directly access the file-system or other security-relevant system resources. As a result, a successful exploit against the browser (or one of its plugins) does not automatically allow execution of arbitrary code, because the attacker is still limited to the restricted privileges imposed by the OS kernel on the exploited process.
To enforce these restrictions, the Chrome security model makes use of kernel Job objects, which allows restricting a process in various ways, such as disallowing the spawning of child-processes or accessing handles outside the job context.
However, none of these restrictions prevent a compromised process from interacting with the kernel the way the Hacking Team exploit does: with the ability to manipulate the EPROCESS structure in the kernel, the attacker is able to completely disable the browser’s security restriction using any drive-by-download exploit allowing code execution in the (restricted) browser process.
More concretely, the attacker can simply find the EPROCESS structure in kernel memory (as described above) and clear the Job member structure. This resets any security restrictions and, in turn, allows full access to the target host.
Full-System Emulation Versus Zero-Day
Despite all the clever tricks and evasive maneuvers used in the exploit, this attack represents a perfect example of why full-system emulation, one of the key technologies behind the Lastline analysis solution, is so important: full-system emulation allows for visibility into every instruction executed during the analysis, regardless of the fact that the exploit calls functions in user- or kernel-mode.
Behavior Summary of Zero-Day Kernel Exploit
As described above, the exploit steals the System access token to raise its privileges, without calling any (hookable) API function, which is the level at which most sandboxes do their instrumentation. Nevertheless, our analysis shows a complete summary of all the behaviors of this zero-day exploit.
Every day, attackers are coming up with new and clever tricks to evade security solutions and system protection mechanisms. The Hacking Team leak provided us with insights into what is going on under the covers of the technology used by well-funded, sophisticated attackers.
But who knows what else lurks out there? Only if we use equally smart, state-of-the-art analysis systems, such as the Lastline solution, can we keep up with these attacks and protect our users.
Latest posts by Arunpreet Singh (see all)
- Building Static and Dynamic Analyses Using Lastline’s Process Snapshotting - September 16, 2016
- A Peek Behind the Cryptowall - January 28, 2016
- Defeating Darkhotel Just-In-Time Decryption - November 5, 2015