Controlling RIP
In order to find the saved return address offset in a driver for exploitation, we follow a similar approach as with user mode stack-based overflows by submitting a pattern and observing the overwrite.
Last updated
In order to find the saved return address offset in a driver for exploitation, we follow a similar approach as with user mode stack-based overflows by submitting a pattern and observing the overwrite.
Last updated
Finding the saved return address offset is very similar to a user mode stack-based overflow. We submit a pattern to the driver and we examine rsp
when the ret
instruction is about to be executed in the vulnerable function.
How you decide to create a pattern is left up to you, I will use a slightly modified version of the script at
This script will not run using python 3; to fix it you must fix the print
statements, ensuring they use ()
brackets and references to long
must be changed to int
.
Run the tool to create a pattern of 250 characters:
Next we need to replace the fuzzer code in the else
statement. This will send our pattern to the driver:
Rebuild the executable and transfer it to the target host. Ensure your debugger is connect to the host and the target driver is running.
Break in to the system and examine the return address in the vulnerable function (we know this address from the fuzzing section):
Set a breakpoint at this address and submit the g
command in Windbg Preview:
On the target host it is time to run the exploit executable. This will break the kernel at the specified breakpoint. Allow Windbg Preview to run past the first break on the breakpoint with the g
command, when we hit it the second time we can look at the stack:
We need to step the add rsp, 78h
instruction, then we are presented with the ret
instruction:
Examine the value pointed to by rsp
; this is the return address that we have overwritten; we can use the da
command to show that our pattern is pointed to by rsp
:
We can submit the first 4 characters to the pattern tool, on our debugger, to find the correct offset of the overwrite:
It is time to test the overwrite of rip
, if this is successful then we most likely have control of the instruction pointer, and code execution.
In order to get arbitrary code execution in the context of the kernel, we need to control rip
. Change the code in our exploit to match the following (again this is in the else
block):
Compile the exploit code.
Copy the executable over to the target host, ensure the debugger is connected and ensure the target driver is running. This time we will not use a breakpoint and allow the Access Violation.
When the debugger breaks, we can examine the address pointed to by rsp
:
We can also confirm this by viewing the call stack with the k
command:
Excellent, we now have control over the saved return address, and subsequently rip
.