When creating Windows kernel exploits the goal is often to somehow gain higher privileges, often SYSTEM. This part of the exploit writing is normally the very last part, and often not very discussed since so many steps come before it. The most common ways I’ve seen that done is either by stealing a process token of a privileged process or by removing the ACL of a privileged process. In essence the techniques I normally come across and use myself are derived and often referenced from the Black Hat presentation by Cesar Cerrudo in 2012. It is a great presentation and white paper and should definitely be read. There are however two issues when trying to use the methods from the white paper; firstly, it does not supply the actual shellcode only the technique in theory and secondly it was written prior to the release of Windows 8.1 much less Windows 10.
Since this is an area which is often not given much attention, I wanted to explore it in-depth and discover whether the three methods described by Cesar Cerrudo still work on Windows 10 Anniversary Edition. Furthermore, I wanted to develop the actual shellcode to run for each of them and document any changes which might be needed for each of them on Windows 10.
To recap the highlight of the whitepaper, Cesar describes three methods:
- Replacing process token.
- Nulling out ACLs.
- Enabling privileges.
In this blog post I will explore how to replace the process token and gain SYSTEM privileges, the other two methods will be explored in upcoming blog posts.
Replacing the process token is one of the two methods I see most often, as Cesar explains the idea is to find a privileged process and copy the token of that process to the current process. There are a lot of dangers of causing a bug check with this method if any privileged process is chosen, hence the system process is normally used since the reference counter on that is so high it most likely will not cause any problems. The method described in the whitepaper is still valid if the exploited process is not running in a sandbox, which is sadly often the case. Because of this some changes need to be made, the main idea is still valid however.
To iterate the idea is as follows:
- Find the EPROCESS address of the current process.
- Find the EPROCESS address of the SYSTEM process.
- Copy token of SYSTEM process to current process.
- Perform actions requiring SYSTEM privileges.
Since I most often develop my kernel exploits for proof of concept and not weaponization I compile them to EXE’s and launch them directly from cmd.exe on the target instead of through the browser. I still like to make sure they would work from Low Integrity or AppContainer however. But since the exploit normally exits after performing its duties I would like the cmd.exe process to gain the elevated rights instead of the process the actual exploits runs in.
The following assumes that the exploit as gained arbitrary kernel mode code execution and we can handcraft the assembly code to run. Although this might sound unlikely to some, it isn’t. Even on the upcoming Creators Edition of Windows 10, there are multiple ways to achieve this if a write-what-where vulnerability is found. I hope to be able to present several new techniques at Black Hat USA myself.
With all of the preconditions out of the way, let us tackle the four problems listed earlier. First we need to locate the EPROCESS of the current process, we can do this by first finding the KTHREAD of the process, since this is located at offset 0x188 in the GS segment. Then we can find a pointer to the KPROCESS at offset 0x220 of the KTHREAD as shown below:
Which means the address of the EPROCESS for the current process may be found through the following assembly instructuions:
Since I like to transfer the permissions to cmd.exe an additional step actually arises, finding the EPROCESS of cmd.exe. To do this we use the process ID, since it is the parent process of the exploit application it can be found through:
Which means that offset 0x3EO in the current process’ EPROCESS is the PID of cmd.exe, this is captured through:
Now to find the EPROCESS address of another process we notice the following structure:
This means that the PID of the process is at offset 0x2E8 of the EPROCESS and that at offset 0x2F0 we have a linked list of all the EPROCESS’s, it is then possible to loop though them looking for the PID of cmd.exe:
Once this is done we want to find the address of the token, since this is what we want to replace. It is located at offset 0x358 as seen below:
So, we make sure to store that address before going onwards:
Now we have found the EPROCESS of cmd.exe, the process we want to gain SYSTEM privileges. Now we need to find the EPROCESS of the System process. Since the System process always has a PID of 4 we can find it in the same way:
This gives us the address of the EPROCESS for the System process. The next step is to replace the token of the cmd.exe process. This is simply done by overwriting the existing token:
Remembering that RDX contains offset 0x358 of the EPROCESS address of the System process and RCX contains offset 0x358 of the EPROCESS address of cmd.exe. Executing the actual shellcode looks like:
With the expected result:
This shellcode is 100% stable and grants the parent process, or if modified the executing process, SYSTEM privileges. That concludes the first blog post, the shellcode may be found at the following Github: https://github.com/MortenSchenk/Token-Stealing-Shellcode