This article is more of a my own notes and it may profit to others.
This is a DRAFT for the moment.
Recently, I followed a course on developement on Offensive Driver Developpement from zeropointsecurity (link here).
I recommend following it, it’s not too expensive and it helped me learn a lot of new stuff.
The end goal is to be able to understand more how things are working and how some people can find signed vulnerable drivers.
I’m only at the beginning of this journey so if you are an expert, this is probably is not the right blog.
I would highly recommand to use a test VM for your experiment. Device drivers tools are not stable and you are playing with fire, so you could easily get a BSOD. So best not to do it on your normal machine (you have been warned).
So in this blogpost I’m using my driver that got provided by the course I’ve followed.
it’s called RedOctober.
I copied my driver in C:\temp, created the service manually and started it.
Autostart is not set, so if you reboot the machine don’t forget to restart the service.
The first step after downloading one and installing it, is to find the device entry name
You could in the past download DeviceTree v.2.3 from OSR but somehow probably due to instabilities on newer OS, it has been removed. You can nevertheless get a copy from my Github repo here : https://github.com/k4nfr3/ioctl_tools
Another easier way to find the driver entry, is to check for the string “\Device\xxx” in the binary file.
If you are running under Linux, a strings normal command will miss it, because it’s a utf16 string.
So either you use something like
grep -a '\\.D.e.v.i.c.e.\\' *.sys
or you can use Radare2 which provides a powerfull set of tools
C:\temp>C:\temp\radare2-5.7.8-w64\bin\rabin2.exe -zz RedOctober.sys | findstr "\\Device\\" 82 0x00001750 0x140003150 18 38 .rdata utf16le \Device\RedOctober
IOCTL / CTL_CODE structure
How are IOCTL codes structured ?
Official documentation here : https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/defining-i-o-control-codes
But in a nutshell :
N.B. In the official doc we have a field called ControlCode, this is also referred as Function.
#define CTL_CODE ( DeviceType, Function, Method, Access )
( (DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))
DeviceType – identifies a type of device, this is mostly used for hardware based drivers. For Software drivers microsofts specifies than 3rd parties should start not lower than 0x8000.
Function – an ascending number indicating a specific operation. Any number will do, but official documentation says 3rd party drivers should start not lower than 0x800.
Method – it indicates how the input and output buffers provided by the client pass to the driver. The simplest value is METHOD_NEITHER.
Access – indicates whether this operation is to the driver, from the driver of both ways (FILE_ANY_ACCESS) which is most cases.
From my source code. I have the following.
DeviceType = 0x8000, Access = FILE_ANY_ACCESS = 0, Function= 0x800, Method = METHOD_BUFFERED = 0x3
So I try to calculate by hand :
DeviceType = 0x8000 << 16 = 0x80000000
Required Access= FILE_ANY_ACCESS = 0x0000 << 14 = 0x0
Function = 0x800 << 2 = 0x2000
TranferType = METHOD_NEITHER = 0x3
Final value = 0x80002003
IOCTL_translator from Mateo Malvica : https://gist.github.com/uf0o/c74adbc7f274014da9f1772b2a8b294b helps by automating this calculation.
And if i look at my source code :
I realise that after a few days, I stumbled on some other source code from the well known nccgroup.
They released a set of tools called DIBF.
Now another tool I’ve been using is ioctlplus written by T.Jackson and source code can be found on his github here : https://github.com/jthuraisamy/ioctlpus
I know the ioctls are after 0x8000000 as it is following microsoft recommendation to have a device ID above 0x8000
Let’s try to fuzz the IOCTLs with using the google code ioctlbf which you can download here : https://code.google.com/archive/p/ioctlbf/
So starting to fuzz the IOCTL numbers, and redirecting the output to a file in case of BSOD
ioctlbf.exe -d RedOctober -i 8000000 -e > toto.txt
-e is to get an output and I redirect it to a file toto.txt
=> I hit a BSOD. Meaning my driver is vulnerable to a buffer overflow or something like that.
When I look at the text file I see the following (i was hoping to find the culprit ioctl code, but seems there is a lag to sync the files to disk before the BSOD )
I realise as I know exactly the IOCTL codes, that my text file doens’t log the latest output to the file but we are getting closer.
I decided to modify the C# app from T. Jackson which was already great but didn’t allow to do scanning. It’s probably not the best scanner out there but it did the job for me.
I’ve added a button for scanning and I analyse the error code. If it is 0x7A then the try is a correct IOCTL but wrong parameters.
In Cyan, the existing IOCTL codes found.
0x80002003, 0x80002007, 0x8000200B, 0x80002043, 0x80002047, 0x8000204B, 0x80002083, 0x80002087, 0x8000208B
This offensive driver, isn’t checking for buffer overflows, so I started scanning and ended up on the correct IOCTL, the default value in ioctlplus was to have 20 bytes as Input and 20 bytes as Output which led to a beautifull BSOD. So now in he scan code, will scan with a zero as input & output buffer size as to try to avoid producing BSODs.
References / Acknowledgments
Windows Kernel Programming from Pavel Yosifovich (ISBN 9781977493375)