Welcome to the second part of Windows Kernel Exploitation series. In the second part, we are taking a detour from usual memory corruption vulnerabilities (which are a majority in case of the driver we are exploiting). I was quite confused whether to make it the first part because how easy it is to exploit, but here we are, once we have tasted blood in kernel land.
What is Type Confusion?
Type confusion is a vulnerability where the application doesn’t verify the type of an object (function, data type, etc.) and then processes it as it expects but the passed object is some other object.
Now we have got it cleared, let us have a look at the vulnerable code (function TriggerTypeConfusion located in TypeConfusion.c).
The kernel first checks if the buffer resides in user land and then it allocates memory for it in Non-Paged Pool. Once that has been done, the kernel assigns ObjectID from user mode buffer to kernel mode buffer and does the same for object type.
After done that, the kernel calls TypeConfusionInitializer function on the object (kernel mode and not on the user mode).
Let us have a look at the function:
This function receives the object and calls a function pointer present inside the object.
Let us have a look at the structure of KERNEL_TYPE_CONFUSION_OBJECT (which is essentially a structure), present in TypeConfusion.h header file. This header file contains definitions for user mode object as well as kernel mode object, which makes exploitation of this exploit easier than that of stack overflow.
First, let us see what the user mode object contains. The user mode object is a structure that holds 2 members:
- Object ID
- Object Type
In case of kernel mode object, it is also a structure that holds 2 members:
- Object ID
- The second member is a UNION which can either hold:
- Object Type
- Callback (A function pointer)
Now, if you remember, a UNION can hold one member at a time, and here it can either be an Object Type or a pointer to a function which will be called by TypeConfusionInitializer function.
The confusion occurs when the function TriggerTypeConfusion function does not validate whether the second member is ObjectType or Callback.
Exploiting the Confusion
To exploit this confusion, all we need to do is to pass a structure whose second member is the address of the function we want to call from kernel land.
In case of our exploit, it is going to be the address of our Token Stealing Shellcode and replace the token of our process so when a new process is created, it will be created with that token.
But there is a problem, the shellcode provided with the HEVD (TokenStealingPayloadWin7 does not work and crashes the machine).
Modifying the shellcode
Since the function TypeConfusionInitializer calls the Callback pointer as it is a function, we need to setup function prologue and epilogue, and change the ret 8 to ret.
Note: I compiled my shellcode functions as naked but if you don’t do that, the provided shellcode can be used as it is. I just don’t like extra code to be added to my shellcode by the compiler.
My code for the exploit is located here
Getting the Shell
Let us first verify whether I am a regular user or not.
As it can be seen, I am just a regular user.
After we run our exploit, I become nt authority/system
That’s for this this part folks, see you in next part.