The Windows kernel is a rich environment where countless drivers execute on a normal system, and in which thousands of factors containing global state are present. For advanced troubleshooting, IT specialists will typically utilize tools like the Windows Debugger (WinDbg), SysInternals Tools, or write their own. Unfortunately, usage of these tools is getting increasingly hard, and they are themselves restricted by their own access to Windows APIs and vulnerable attributes.
Some of today’s challenges include:
- Windows 8 and later support Secure Boot, which averts kernel debugging (including local debugging) and loading of test-signed driver code. This restricts troubleshooting tools to those that possess a signed kernel-mode driver.
- On systems without Secure Boot empowered, allowing local debugging or altering boot options which facilitate debugging capabilities will often trigger BitLocker’s retrieval manner.
- Windows 10 Anniversary Update and after include much stricter driver signature demands, which currently apply Microsoft EV Attestation Signing. This limits the freedom of software programmers as standard”read-write-everything” drivers are frowned upon.
- Windows 10 Spring Update now includes customer-facing options for enabling hypervisor Code Integrity (HVCI) which further limits allowable drivers and blacklists multiple 3rd party drivers who had”read-write-everything” capabilities because of badly written interfaces and safety risks.
- Technologies like Supervisor Mode Execution Prevention (SMEP), Kernel Control Flow Guard (KCFG) and HVCI with Second Level Address Translation (SLAT) are creating traditional Ring 0 execution tricks’ obsoleted, therefore a new strategy is necessary.
In such an environment, it was obvious that a simple tool which may be used as an emergency band-aid/hotfix and to quickly troubleshoot kernel/system-level problems that might be evident by analyzing kernel condition might be valuable for your community.
How it Works
R0ak works by redirecting the implementation flow of the window manager’s trustworthy font validation tests when attempting to load a new font, by substituting the trusted font table’s comparator pattern with another purpose which schedules an executive work thing (
WORK_QUEUE_ITEM) stored in the input node. Then, the font table’s right kid (that serves as the root node) is overwritten using a named pipe’s write buffer (
NP_DATA_ENTRY) in which a customized function item is saved. This item’s underlying worker work and its parameter is exactly what will eventually be executed by a committed in
PASSIVE_LEVELonce a ribbon load is attempted along with the comparator routine implements, receiving the title pipe-backed parent node as its input. A real-time Event Tracing for Windows (ETW) follow up occasion is used to receive an asynchronous notification which the work item has finished executing, making it secure to tear down the arrangements, free the kernel-mode buffers, and restore normal functioning.
While employing the option
--execute, this purpose and parameter are provided by the user.
--write a custom-made gadget is used to modify arbitrary 32-bit values anywhere in kernel memory.
--read the write gadget is used to modify the system’s HSTI buffer pointer and size (N.B.: This is destructive behavior in terms of any other software that will ask the HSTI data. As this can be optional Windows behavior, and this tool is intended for emergency debugging/experimentation, this reduction of data was considered suitable ). Then, the HSTI Query API can be used to copy back into the program’s user-mode address area, and a hex dump is revealed.
Because merely built-in, Microsoft-signed, Windows performance is utilized, and most of the called functions are part of their KCFG bitmap, there’s absolutely no breach of any safety checks, without any debugging flags are required, or use of 3rd party poorly-written drivers.
Due to the Use of the Windows Symbol Engine, you have to have either the Windows Software Development Kit (SDK) or Windows Driver Kit (WDK) installed using the Debugging Tools for Windows. The tool will lookup your setup route automatically, and leverage them
SymSrv.dll are found in that directory. Because these files are not re-distributable, they can’t be contained with the launch of this tool.
Alternatively, if you get these libraries on your own, you can alter the source code to use them.
Use of symbols requires an online connection unless you have pre-cached them locally. Additionally, you should set up the variable
_NT_SYMBOL_PATH pointing to an appropriate emblem server and cached location.
It is assumed that an IT Pro or another troubleshooter which apparently has a need to read/write/execute kernel memory (and has knowledge of the appropriate kernel variables to access) is already more than familiar with the above setup requirements. Please do not file issues inquiring what the SDK is or how to establish an environmental variable.
- Some driver leaked kernel pool? Why don’t you telephone and
ntoskrnl.exe!ExFreePoolpass in the kernel address that is leaking? What about an object reference? Go call and
ntoskrnl.exe!ObfDereferenceObjecthave that cleaned up.
- Wish to ditch the kernel DbgPrint log? Why not ditch the inner circular buffer at
- Wondering how large the kernel stacks are on your own device? Consider looking at
- Want to ditch the system call table to look for hooks? Go print out
These are just a few examples — all Ring 0 addresses are approved, either by syntax
module!symbol or straight passing the kernel pointer if known. The Windows Symbol Engine is used to look up these.
The application requires certain kernel variables and functions which are only known to exist in modern versions of Windows 10 and was only meant to work on 64-bit systems. These constraints are due to the fact that on older systems (or x86 systems), these more rigorous safety requirements don’t exist, and therefore, more traditional approaches may be used alternatively. This is a personal tool that I am making accessible, and that I had no requirement for these older systems, in which I really could use a very simple driver instead. That being said, this repository takes pull requests, if anyone is interested in porting it.
Secondly, because of the use cases and my needs, the following restrictions apply:
- Reads — Restricted to 4 GB of data at a time
- Writes — Limited to 32-bits of data at a time
- Executes — Restricted to functions that only require 1 scalar parameter
Evidently, these constraints could be mended by programmatically choosing a different approach, but they fit the requirements of a command line tool and my use cases. Again, pull requests are accepted if others wish to donate their particular developments.
Be aware that all execution (like the execution of the and
--write commands) occurs in the context of a System Worker Thread in.
PASSIVE_LEVEL Therefore, user-mode addresses shouldn’t be passed as parameters/arguments.
r0ak v1.0.0 -- Ring 0 Army Knife http://www.github.com/ionescu007/r0ak Copyright (c) 2018 Alex Ionescu [@aionescu] USAGE: r0ak.exe [--executemodule.ext!function> ] [–write module.ext!function> ] [–read module.ext!function> ]