In this series of articles, we will learn about kernel exploitation using the HackSysExtremeVulnerableDriver created by Ashfaq Ansari. The driver has many vulnerabilities built into it and we will try to exploit all of them in this series. In this section, we will work to identify the buffer overflow vulnerability present in the driver and attempt to exploit it.
Assumptions for Kernel Exploitation
- Win7 x64 VM.
- Visual Studio 15.
- HackSysExtremeVulnerableDriver from this Github location.
- Process Explorer
- OSR driver loader
- Win Dbg
Compilation of source code
Download the code and create a controller project in my Visual Studio.
- Open Visual Studio and create a new project.
- File>New>Project>Visual c++>Windows Driver>KMDF
- Import all header files (.h) and source files (.c) from the extracted zip. I’m focusing on Win7 x64 in this series, so make sure you compile the driver code for the same environment. After successful compilation, a sys file is created (w.r.t to the name of the compiled project).
- When compiling the code, I made sure to configure the project parameters below so that the project compiles successfully.
- On the right, click Project > Properties.
- Configure “Treat warnings as errors” to No (/WX-)
- Configure Security Check to “Disable Security Check (/GS-)”
- The target OS also remained Windows 7 and the target platform was Desktop.
- Click Build > Build Solution.
Loading the driver
Now we need to load the driver and we will load it using OSRloader, but before that, since Microsoft can’t let unsigned drivers be loaded into the system, we need to enable test signing as shown below.
Open the elevate command prompt and type the command below.
And reboot the system. After a successful reboot, you should see the test mode as below
Now let’s load the driver using OSRloader.
Open OSRloader and point to the location of the compiled driver .sys file.
First register the service and then start the service. Click on Active Services to quickly check if the driver is running or not.
To confirm that the driver is running, we can look at the Process Explorer output as shown below
We can also check the driver status using driverquery.exe as below
Since we’re doing the exploit at the kernel level, let’s do some remote debugging.
Open WinDBG > File > Kernel Debug
I connect my debugger from my Windows 10 host and connect to the pipeline of the VM I named Demo.
When configuring COM to connect the debugger mentioned .pipeDemo and then it can go into waiting phase so you have to restart your Win7 machine. Once the target computer is restarted, WinDbg will connect to the computer as shown below. Crl+Break to break into a session on Win7,
Now that we have our environment ready, let’s explore the exploit.
Since this driver is opensource, we have the code for it, but in the real world, we don’t, and we also analyze the driver without looking directly into the source code. Below is just a glimpse of all the vulnerabilities found in this driver.
Open the project created above and navigate to the code section below.
To interact with the driver, the user-mode code calls the DeviceIoControl API in kernel32.dll. It provides a handle to the device it wants to communicate with and an I/O control code. This I/O control code tells the driver what function the code wants to perform.
Create a new driver project. File>New>Project>Visual c++>Windows Driver>KMDF.
First we get the handle of the created device. We can do this with a simple call to the CreateFile API. The following is a screenshot with the required parameters. Note that the API call is used to create a new file and also to open an existing file (for both read and write operations). In this case, since the driver is already running, it tries to read it and get a handle for it.
This code gets the driver for the device, which is necessary for the next step when we need to tell the driver what function we want it to perform.
Note: After rebooting, make sure the compiled driver is still running.
Loading the driver in IDA PRO
We need to get the IOCTL for this drive function. So let’s look at this code in IDA pro. Below is what is listed in the Names window. Let’s look at the IrpDeviceIoCtlHandler function.
Double click on the function and it will take us to the code below.
Now we need to look at all possible combinations of positive and negative conditional jump instructions. Follow the negative side of ja loc_4042F2 and repeat the above procedure. After executing a few jmp commands, we get to the stack overflow function. Note that 0x222003h is the IOCTL code for this function call because it leads to the appropriate function.
Below is the StackOverflow function. We will follow with the call to StackOverflowIoctlHandler function.
- Below is the StackOverflowIoctlHandler function and from where will follow to TriggerStackOverflow. Click on TriggerStackOverflow
- Below is the code that handles the buffer passed to the driver. We see below that the parameters passed to the memcpy function do not check the input supplied by the user and directly copy the size of the user buffer to the kernel buffer. So we can go through a large user buffer and see if we can control some registers.
- Also note that the kernel buffer size is 0x800. If the function is limited to this size, then a stack overflow is not possible, but since it directly copies the input supplied by the user, we can take advantage of this. Also, it will be useful for us to set the buffer from the user size.
- Below is a code snippet where it has a big string “A” and then passing the appropriate parameters to the DeviceIOControl function.
- After we run the script, the above code will cause a BSOD on the target machine and we can see that our buffer A in the screenshot below in WindDBG
- In this article, we saw how we can find a vulnerability in a driver and then perform reverse analysis to get different elements to start conversations with the driver and trigger vulnerabilities like buffer overflows. In the next article, we will see how we can control the buffer length and use it to further exploit the vulnerability.