Kernel Exploitation: Introduction
In this article series, we will learn about kernel exploitation using a driver HackSysExtremeVulnerableDriver built by Ashfaq Ansari. The driver has many vulnerabilities built into it, and we will try and exploit all of them in this series. In this part, we will work on identifying the buffer overflow vulnerability present in the driver and try to exploit it.
- Win7 x64 VM.
- Visual Studio 15.
- Vulnerable HackSysExtremeVulnerableDriver from this Github location.
- Process Explorer
- OSR Driver loader
- Win Dbg
Source Code Compilation
Download the code and build a driver project in my Visual Studio.
- Open Visual Studio and create a new Project.
- File>New>Project>Visual c++ >Windows Driver>KMDF
- Import all the header (.h) files and source files (.c) from the extracted zip. In this series, I am targeting Win7 x64, so make sure to compile the driver code for the same environment. After successful compilation, a sys file(w.r.t to compiled project name) will be created.
- While compiling the code, I made sure to configure below project parameters so that the project gets compiled successfully.
- Right, click on Project > Properties.
Configure “Treat Warning as Errors” to No(/WX-)
Configure the Security Check to “Disable Security Check (/GS-)”
Also kept the Target OS as Windows 7 and target Platform to be Desktop.
- Click Build >Build Solution.
Loading the Driver
- Now we must load the driver, and we will load it using OSRloader, but before that, since Microsoft cannot let unsigned drivers load to the system we must enable test signing like below.
Open the elevate command prompt and type below command.
And restart the system. After successful reboot, you should see the Test Mode like below
- Now let’s load the driver using OSRloader.
Open OSRloader and point to the location of compiled driver .sys file.
First, register the service and then start the service. Click on Active Services to quickly check whether the driver is running or not.
- To confirm the that the driver is running we can look into process explorer output like below
- We can also check the driver status via driverquery.exe like below
- Since we are performing kernel level exploit, let’s perform remote debugging.
- Open WinDBG > File>kernel Debug
I am attaching my debugger from my Windows 10 host and connect to the pipe of the VM which I named as Demo.
While configuring the COM to attach debugger mentioned .pipeDemo and then it might go to waiting stage, so you need to restart the Win7 machine. Once target machine is restarted, WinDbg will connect to the machine like below. Crl+Break to break into the session on Win7,
Now since we have the environment ready, let’s explore the exploit.
Since this driver is opensource, we have the code available for it but in the real world this is not the case, and we will also analyze the driver without looking directly at the source code. Below is just a glimpse of all the vulnerabilities which are present in this driver.
Open Project Created above and scroll to below code portion.
To interact with the Driver, the User Mode code calls into the DeviceIoControl API in kernel32.dll. It provides a handle to the device with which it wants to interact and 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, let’s obtain a handle to the device created. We can do it with a simple CreateFile API call. Following is the screenshot with required parameters. Note that the API call is used to create a new File as well as open an existing file (for Read as well as write operations). In this case, since the driver is already running, it is trying to read it and obtain a handle on it.
This is code will get a handle to the device which is necessary for the next step when we need to tell the driver what function we want it to perform.
Note: Make sure after the restart, 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 this code in IDA pro.Below is what is listed in the Names window. Let’s follow IrpDeviceIoCtlHandler function.
Double click the function, and it will take us to below code.
- Now we must look into all the possible combinations of a positive and negative conditional jump instructions. Follow the negative side of ja loc_4042F2, repeat the above process. After following a couple of jmp statements, we will reach the stack overflow function. Please note that 0x222003h is the IOCTL code for this function call since it leads to the respective 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 which is handling the buffer passed to the driver. We can see below the parameters passed to the memcpy function has no check on the user-supplied input and it directly copies the size of user buffer to the kernel buffer. So, we can pass a large user buffer and see if we can control some of the registers.
Also, note that the size of the kernel buffer is 0x800. If the function has restricted to that size, then the stack overflow is not possible, but since it directly copies user-supplied input, we can exploit this. Also, this will be useful for us when to set the buffer from user size.
Below is the code snippet where it has a large string of ‘A’ and then passing the appropriate parameters to the DeviceIOControl function.
After we run the script, the code above causes a BSOD on the target machine, and we can see that our buffer of A’s in below screenshot in WindDBG
In this article, we have seen as to how we can find a vulnerability in a driver and then reverse engineer to get different elements to initiate talks with driver and trigger vulnerabilities like a buffer overflow. In the next article, we will see how we can control the buffer length and use it to exploit the vulnerability further.