What’s Different?

Technical Background

Vulnerability Research

Common and less common kernel bugs

Exploit Development

Examples: Use-after-free, DRM

Tips & Tricks

AFD.SYS: A simple kernel bug

Win32k.sys: A complex kernel bug

Windows 8 and the future

Questions

Why Kernel?

Used to be much harder

With the introduction of DEP, ASLR, UAC, Heap checks, Protected Mode, Sandboxes etc in User Mode, it’s now on par and sometimes even easier

In parallel to the securing of User Mode, a lot of OS functionality was moved from User to Kernel, and new User-to-Kernel interfaces were introduced, thus drastically increasing the attack surface in the Kernel

Why Kernel Cont’d

In 64bit systems, the Driver Signing Requirements prevent even an Administrator from running unsigned Kernel Code, making exploitation the only alternative.

This is already happening

Quoted from a November 4 article by Gregg Keizer’s on ComputerWorld:

“Microsoft has been extremely busy patching pieces of the Windows kernel this year.

So far during 2011, Microsoft has patched 56 different kernel vulnerabilities with updates issued in February, April, June, July, August and October. In April alone, the company fixed 30 bugs, then quashed 15 more in July.”

What’s different?

If something goes wrong, it goes REALLY wrong. That means that even the smallest glitch leads to a BSOD and a system reboot.

No need to worry about permissions 

You have to master a lot more technical knowledge.

No process boundaries. This means that you have a lot more to play with, but also a lot more to mess with

Required Technical Background Things you have to master before you even begin

Tips & Tricks – Cont’d

Non-fixed addresses that can be extracted:

New technique (thanks to Gil Dabah and Tarjei Mandt): The Window Handle Table is mapped to user address space and contains Kernel pointers to objects with function pointers in them (see http://www.mista.nu/research/mandt-win32k-paper.pdf)

So it’s possible to:

Create a kernel window (a window for which win32k created and registered a window class so the window procedure is in kernel, such as menu and tooltip)

Get the pointer to the kernel window object from the Handle Table

Overwrite the WndProc Pointer

Send a message to the window to trigger the WndProc Pointer

Tips & Tricks – Cont’d

Non-fixed addresses that can be extracted:

Other Kernel pointers that are passed to user space.

Some Win32k.sys syscalls are defined as VOID or USHORT and leak a full or partial kernel pointers in the return value (see http://j00ru.vexillium.org/?p=762)

Tips & Tricks – Cont’d

A BSOD is not the end:

There’s plenty of code that runs AFTER an exception, and many times that code calls callback functions that can be overwritten. Especially with ACCESS_VIOLATIONs, the flow goes to the page-fault handler first, so there are plenty of options for attack

Even inside KeBugCheck there are callbacks that can be overwritten

It’s a bit tricky to fix the context and resume normal execution afterwards – but it can be done.

Tips & Tricks – Cont’d

WOW64 processes:

When running in a 32bit process on a 64bit system, when you try to call NtQuerySystemInformation, all the returned pointers are truncated to 32bit – Very annoying!

This can be overcome by using the built-in call gate to temporarily switch to 64bit, call NtQuerySystemInformation, then return to your 32bit code. For more information see http://vxheavens.com/lib/vrg02.html (and thanks to Mark Dowd for the tip!)

The 64bit TEB can be accessed directly without all the switching to 64bit mess since it’s mapped at gs:0

From Kernel to User

Contrary to common logic that says the more power the better, launching user-mode code that runs with SYSTEM privileges from the Kernel can be very tricky (due to the lack of API and OS support to do so).

In the following slides we’ll go over the different techniques that can be used, and the pros and cons of each of them

From Kernel to User – Changing the process token

Method

Change the token of a process we already have control of (e.g. the process that launched the exploit) to a SYSTEM token

Pros

Cons

The user-mode code has to do all the nasty work (e.g. injecting code to a system process), making it vulnerable to AV and security programs that hook user APIs

From Kernel to User – User-mode APCs

Method

Queue a user-mode APC to a target thread already running in a system process.

Pros

Gets you directly to where you want to be

Allows injection to any process on the system

Cons

Only threads in Alertable state can be targeted, and there is no generic way to find them. An alternative is to force a thread into an Alertable state, but this breaks its waiting state, causing the wait function to return mid-way, and may lead to system instability or crash.

Very undocumented, and the relevant structures are different between OS versions.

Unless targeting a thread you have intimate knowledge of, this method may lead to deadlocks if the thread is holding some locks when it enters the wait state (e.g. the LoaderLock)

From Kernel to User – Thread Hijacking

Method

Change the context of an existing thread in a system process to execute injected code.

Pros

Gets you directly to where you want to be

Allows injection to any process on the system

Cons

Restoring the context can be very difficult.

Hijacking an arbitrary thread is extremely dangerous and may cause deadlocks, instability, or crashes

From Kernel to User – Creating a new thread

Method

Create a new user-mode thread in a system process

Pros

An almost perfect solution, gets you exactly to where you want without any dangers or context issues.

Allows injection to any process on the system

Cons

Extremely difficult to implement. In order for the new thread to function it has to be registered with CSRSS. The APIs and structures involved with that are complex, undocumented, and change constantly with Windows updates.

From Kernel to User – API hooking

Method

Hook a user-mode API that you know is going to be called or that you can cause to be called within a system process

Pros

Allows to inject directly into a system process

Very reliable

Cons

Finding a suitable API to hook may be difficult.

This method isn’t generic, and will only work on system processes that frequently call the targeted API.

ZwQueryIntervalProfile()

AFD.SYS - Demo

Demo

Walk-through of a complex Kernel PE Exploit

Thanks to my friend Gil Dabah (creator of diStorm Disassembler)

This bug was silently fixed by MS in February

Background

When registering a Window Class it’s possible to request the OS to store some extra bytes with the window object

The extra bytes are appended to the WND structure in the kernel:

Background - Continued

Some special window types (Menus, Tooltips, etc) also have some private data that can only be accessed by the kernel:

Background - Continued

To change the data on the extra bytes, applications call the SetWindowLongPtr function with the index into the extra bytes and a new value.

The function then checks if the index provided is within the private data or the user extra bytes. If the index is within the private bytes, the function fails, so normally it’s impossible to change the private kernel data.

Background - Continued

In order to check if the index is within the private data, SetWindowLongPtr uses a table of window types with their corresponding total allocated bytes size (WND struct + private).

“Window type” refers to FNID, which is the real identifier of a window type, from a list of hard-coded values (unlike its Class).

The pseudo code for the check is:

if (index < (int)(window_class_alloc_sizes[fnid]-sizeof(WND)))) FAIL;

The bug – part 1

By using the undocumented and unexported function RegisterClassExWOWW and supplying an internal window type and a negative number for the extra bytes, it’s possible to overwrite the table with our own value. The bug is that the extra bytes value isn’t verified:

The bug – part 1 - continued

With the table altered to have a negative number as the # of allocated bytes, the test code is tricked: