Hi everybody!

Hate to say it, but Fahmida is right…Just take a look at that list ðŸ˜²ðŸ˜± You really got to give it to them!

In the last versions of Windows, Microsoft put security at the top of their concern.
In my opinion, Microsoft understands that vulnerabilities will never seize to exist,
so they changed their mindset from mitigation by never-ending patches to mitigation by eliminating every exploitation technique they can find.

They take every new exploitation technique and just light it up.
So without further ado, let’s Fry the Windows 10 Kernel 😈


Getting your code into ring 0

In the old days, everyone just could write their own drivers and just load them into the kernel.

The transition from x86 to x86_64 came and Microsoft had an opportunity to reshape things up, so they came up with a new security feature called Driver Signature Enforcement  (DSE\KMCS).

It’s caused, as the name implies, is to load signed drivers only.
(P.S. recently Microsoft took it one step up and now drivers can only be signed by Microsoft’s CA)

The technology applies to every Windows OS from XP to 10.
So these days there are four options to run arbitrary code in the Windows kernel.
1. Turn DSE off – loud as hell.
2. Patch winload.exe and ntoskrnl.exe – loud as hell.
3. Sign your driver/steal certificate – If you are a part of an intelligence organization.
4. Use an exploit – Sounds interesting.

The problem with signatures is that they’re pretty hard to be revoked unless there is a really good reason for it.

This fact creates a reality where you can find endless signed drivers with known vulnerabilities in them, which really good for us, and really bad for them.
In this post, we will use the notorious Capcom.sys exploit (which looks more like a backdoor) combined with a reflective driver loader.


Part 1 – Open Sesame 
The driver workflow goes like this:
1. DeviceIOControl (MAJOR_FUNCTION used to transfer buffers via IRPs) is called by the user.
2. The function (offset 0x590) validates the input buffer size from the IOStack (8 on x64 code):

3. It passes the buffer to another function (offset 0x528).

4. The functions perform another check, then disable SMEP, runs the code supplied, and enables it again:



Part 2 – Ghosts

But we are just getting warmed up because the real challenge is to load a fully functional PE and run it. We will do it by using a programming technique called “Reflected Programming”.
In our case, it means that we will reflect the OS part that in charge of loading programs (specifical drivers) into the kernel which surprisingly called the “OS loader”.
The flow goes like this:

  • PSCreateSystemThread or a bootstrap shellcode is called and passes execution to the driver’s ReflectiveLoader execution.
  • The driver will currently exist in an arbitrary location in memory.
    The ReflectiveLoader will first calculate its own image’s current location in memory.
    Then it would be able to parse its own headers for use later on.
  • The ReflectiveLoader will then use MmGetSystemRoutineAddress
    (assumed to be passed in as arg0) to calculate the addresses of functions required by the loader ExAllocatePoolWithTag, ExFreePoolWithTag, IoCreateDriver, etc…
  • The ReflectiveLoader will allocate memory and load its own image to it.
    The location is not important – the loader will correctly relocate the image later.
  • The driver’s headers and sections are loaded into their new locations in memory.
  • The ReflectiveLoader will then process the newly loaded copy of its image’s relocation table.
  • The ReflectiveLoader will then process the newly loaded copy of its image’s import table, resolving any module dependencies.
  • The ReflectiveLoader will then call IoCreateDriver passing the driver’s DriverEntry exported function as the second parameter.
  • Finally the ReflectiveLoader will return to the initial bootstrap shellcode which called it, or if it was called via PSCreateSystemThread, the thread will terminate.



Final Thoughts
There you have it – fully functional unsigned driver runing in ring 0.
As mentioned, this is the first post out if three, so there is a lot more coming, so stay tuned  🙂

adPPYba,  ,adPPYba,  ,adPPYba, 8b       d8  ,adP,PYba,  88       88  
I8[    "" a8P_____88 a8P_____88 `8b     d8' a8"     "8a 88       88  
 `"Y8ba,  8PP""""""" 8PP"""""""  `8b   d8'  8b       d8 88       88  
aa    ]8I "8b,   ,aa "8b,   ,aa   `8b,d8'   "8a,   ,a8" "8a,   ,a88  
`"YbbdP"'  `"Ybbd8"'  `"Ybbd8"'     Y88'     `"YbbdP"'   `"YbbdP'Y8  
                                    d8'                              
                                   d8'     

References:
https://blog.codinghorror.com/understanding-user-and-kernel-mode/
https://www.infoworld.com/article/2984602/security/why-windows-10-is-the-most-secure-windows-ever.html

Categories:

Tags:

Comments are closed