- Published on
SekaiCTF 2024 – ProcessFlipper
- Authors
- Name
- nyancat0131
- Description
- 2.5D idols and gacha addict
Pwn/Process Flipper (458pts, 3 solves)
In SekaiCTF 2024, I made ProcessFlipper
challenge. The goal is to escalate privilege to NT AUTHORITY\SYSTEM
on a Windows VM with a vulnerable driver installed. This post will cover the background of the challenge, technical information on how we setup an automated exploit runner, as well as the solution for the challenge.
Background
I play gacha games. Normally they are mobile games, but some also have PC clients. Because you can do many things on a PC, cheating become a problem. Developers use a variety of way to prevent cheating, even using kernel drivers to monitor activities. Some companies use commercially available anti-cheat systems like Easy Anti Cheat, some develop their own system. One of the most famous example would be the anti-cheat system of Genshin Impact by HoYoVerse, where they use a kernel driver that has the ability to read and write memory in any process and do other interesting things. The driver is also signed so it became a BYOVD for threat actors.
Besides anti-cheat, companies also don't want people to reverse engineer their games, so anti-tamper methods like obfuscating, packing and crypting are also used. One day when fiddling around with Heaven Burns Red, I noted that the game executable is packed, and protected at runtime by a driver that prevent debuggers from attaching to it. Searching online for wfshbr64.sys
, I found out that an old version of the driver is available which allows manipulation of arbitrary bits in EPROCESS
structure of the calling process. Originally it is used for the anti-tamper to manipulate the Protection
field and the SignatureLevel
field of the EPROCESS
structure, but the offset check is incomplete, making it possible to manipulate other fields as well, therefore privilege escalation is possible.
I decided to reimplement it for this challenge, but with some modifications in the offset checking and remove other checks. It features 2 IOCTLs for turning on and off any bit in the EPROCESS
structure. Originally I intended to deploy this challenge on Windows 11 23H2, but NtQuerySystemInformation
would make it trivial to exploit. After confirming that it is indeed exploitable without the free information leak, I decided to use Windows 11 24H2. I even thought of making it harder by only providing an IOCTL to flip the bit (look at the challenge's name!) but I don't want my challenge to have 0 solves again (not because of it being too hard, but it would be really time consuming that teams wouldn't bother solving it).
Setting up the infrastructure
Unlike Linux, Windows kernel challenges are really hard to deploy. Some of the problems are:
- Long boot-up time (this can somewhat be solved by using VM snapshots)
- Not CLI-friendly, since even the core version of Windows Server technically still uses GUI subsystem, so cannot just do xinetd-like deployments
- The VM itself is heavy since we can't customize the roofs easily
- Heavy resource consumption even when idling
- etc..
In corCTF 2024, originally it would have a Windows kernel challenge, but it was dropped. This is the announcement by the organizers:
Unfortunately, the Windows kernel challenge will not be happening this year. After years of smoothly hosting Linux kernel challenges, we underestimated the difficulty and pain which hosting Windows kernel challenges would bring. :bsod:
Other CTFs, such as last year SECCON CTF final uses a manual approach where players would submit the exploit to the organizer and they will run it manually on the target machine. We could have gone with this approach, but hfz thought of a brilliant flow:
- Player submit their compiled exploit through a web front-end with captcha or PoW to prevent abuse
- These exploit will be put in a task queue, which will then be feed into a malware analysis framework
- The framework will spawn a VM from prepared snapshot, run the exploit and take screenshots with a timeout of 30 seconds
- The last screenshot taken will be returned to the player
With this flow, the exploits are expected to escalate the privilege to SYSTEM
and print the flag to the screen, so they can see it in the screenshot. We had to use a strong GCP instance in order to smoothly run (multiple) nested Windows VM(s). After some testing, we were confident enough to go with this flow. During the contest, we found out that some exploits could be caught by Windows Defender, which is really funny. However after the contest ends, a player informed us that we accidentally left the solution in %TEMP%
folder, but lucky for us they couldn't abuse it. Overall we were satisfied with how things went.
Solution
Because there are no read functionalities, I read through the EPROCESS
structure to find fields that satisfy these conditions in order to create arbitrary read-write primitives:
- Is a pointer pointing to somewhere in kernel memory space
- Possible to query and modify the content of the memory that it points to
- Modifying the pointer has low to no chance of BSOD
At first I thought of modifying the Token
pointer directly, but I was afraid that it would cause BSOD (turns out that would be true if we are unlucky, but r4kapig solved it this way). I also found some exploits used QuotaBlock
field, but I continued searching for other fields. Finally, I stumbled upon DiskCounters
field. This field was introduced in Windows 8. It is a pointer to a PROCESS_DISK_COUNTERS
object, and it is queryable from low privilege user process running on medium IL using NtQuerySystemInformation
with SystemProcessInformation
class. Furthermore, we can somewhat modify the object's fields by reading or writing to disk, that should be enough to flip some bits of some important field we can point to. Observing the pointer value in debugger, I noticed that it points to the same pool as the EPROCESS
structure, which I confirmed by reversing the process creation function of the kernel that the PROCESS_DISK_COUNTERS
object is hosted inside the EPROCESS
structure. This is huge because by changing some lower bits of the pointer, we can leak other fields of the EPROCESS
structure. I was able to leak Token
field of the current process. So the brifef exploitation flow is:
- Modify
DiskCounters
pointer so that theBytesWritten
field overlaps withToken
field of theEPROCESS
structure - Leak the
Token
pointer usingNtQuerySystemInformation
- Point
DiskCounters
to theTOKEN
object we leak before so that theBytesWritten
field overlaps withPrivileges.Present
field of theTOKEN
structure - Write something to disk to turn on
SeDebugPrivilege
flag - Repeat the above 2 steps but with
Privileges.Enabled
field of theTOKEN
structure - Spawn a shell with
winlogon.exe
as its parent since we now haveSeDebugPrivilege
privilege
Source code and solution code for the challenge are available here.