KRWX: Kernel Read Write Execute
github project: https://github.com/kiks7/KRWX
During the last few months/year I was studying and approaching the Kernel Exploitation subject and during this journey I developed few tools that assissted me (and currently assist) on better understanding specific topics. Today I want to release my favourine one: KRWX (Kernel Read Write Execute). It is a simple LKM (Linux Kernel Module) that lets you play with kernel memory, allocate and free kernel objects directly from user-land!
The main goal of this tool is to use kernel functions from userland (from C code) in order to avoid slower kernel debugging and developing of kernel modules to demostrate specific vulnerabilities (instead, you can emulate them with provided IOCTLs). Also, it can assist the exploitation phase. These are the project main features (all these features are accessible from a low level user from user-land):
- Read and write into kernel memory
- Read entire blocks of memory
- Arbitrary allocate objects directly calling
kfreeobjects (and also free arbitrary addresses, if you want)
- Allocate/free multiple objects
- Log every
kfreecalled by the KRWX module through hooking (readable from
Mainly, a more powerful read and write primitive :]
Initially I was writing this module to study the SLUB memory allocator in Linux by allocating, freeing and re-allocating arbitrary chunks easily from an userland process. That automatically leads to study also some exploitation techniques that, with this module, I found a lot easier to understand since you can easily play with kernel memory as you are the god of your system. Then I started to heavily use it for multiple purposes and that’s the reason why I’m sharing it.
These are some exported functions:
void* kmalloc(size_t arg_size, gfp_t flags)-> Allocate a chunk with specific
int kfree(void* address)-> Free arbitrary chunks by their
address(also, you can free arbitrary memory).
unsigned long int kread64(void* address)-> Read 8 bytes of memory at
int kwrite64(void* address, uint64_t value)-> Write 8 bytes specified by
void read_memory(void* start_address, size_t size)-> Read
sizeamount of memory starting from
And, since one of my favourite hobby is overengineer and I’m lazy enough to do not want to write loops everytime:
void multiple_kmalloc(void** array, uint32_t n_objs, uint32_t size)-> Allocate
n_objsnumber of objects with specified
sizeand return addresses in
void multiple_kfree(void** array, uint64_t to_free, uint64_t to_free_size)-> Free specified addresses in
to_free_sizeis the size of the
If you’re interested in the source code feel free to check out the github project.
# Allocate, free and read arbitrary chunks
You can find the full source code in
example/01.c. Here will follows some snippets and a little walkthrough.
First, include the external library and call its initialization function (
So, 10 chunks with size 256 are allocated using
multiple_kmalloc, and the memory of the 7th allocation is read using
read_memory after writing
0x4141414141414141 at its first bytes:
The indexes 3, 4 and 7 of the
chunks array are freed using
Once they are freed, new chunks with the same size are allocated and initialized with
0x4343434343434343, and the memory of the 7h freed chunk is displayed using
The result is:
With few lines of code has been demostrated how our 7th chunk has been replaced with a new one after it has been freed (the
read_memory targeted the
As simple as it is, it has been written for demonstration purposes.
To simulate a UAF scenario it’s simple as few lines of code:
For example, if we want to simulate an attack scenario where we want to replace our vulnerable freed chunk with a target object (for example an
iovec struct) we can allocate a chunk with
kmalloc and later
kfree it just before allocating the target structure:
read_memory we can show the block of memory in our interest and as you can see from the following output, our arbitrary allocated/freed object has been replaced with the target object:
Instead of just print the content, you can simulate a UAF read/write using
k[read|write] and play with it.
The full code of this example can be found in
To compile the module change the
K variable in the
Makefile with your compiled kernel root directory and compile with
Personally, I used it to study the SLUB allocator, understand UAF/Heap Overflows/Double Free/userfaultd and some hardening features in the kernel, but it can assist the exploitation phase too or more. Blog posts on some Kernel vulnerabilities and their attack methodologies will follow these months and this module will come useful to demonstrate them. So, stay tuned and enjoy !
PS. The “Execute” part of the name will be a future implementation to control