The Wonderful Null Dereference

So a Null Dereference bug may sound pretty intense if you have never heard of it but I can assure you it is not. The most interesting thing about it is how easy it actually is to exploit; however, it is a dead bug class. Still interesting to exploit though.

What exactly is this? A null pointer dereference takes place when a pointer with a value of NULL is used to point at a valid memory area. If we can control it, we are good to go! Let’s kick some ass…

Read the Source, Luke!

If we take a look at the source, it is nicely commented for us to follow along. I had shortened the code to get what really matters to us because it is kinda long… ┴┬┴┤( ͡° ͜ʖ├┬┴┬

You can find the full code here.

The magic value here is 0xBAD0B0B0. If our user data is equal to the magic value, then all is well and nothing happens. If it’s not, then our wonderful NULL gets set and all the fun starts to begin. The beauty of this code is that its wrapped in a try/except statement. What’s that mean for you? No BSoD’s and constant reboots 🙂 Yeaaa, boiiiiiiii

As a side note, keep in mind that this will only be for this driver. Other drivers might BSoD and others will not!

Now on to Ida!

The Analysis!

To trigger this vulnerability, we will need to use an IOCTL code that reaches that vulnerable function, which is “0x22202b”. How do we get this?? Let’s dive in…

The initial check starts with “0x22201f”. Continuing the path, we hit our next check.

So some value gets moved into EAX and then subtracted by 0x222023. If our value is zero, it’ll continue on to the right; otherwise, we head to the left. Keep note of the difference being 0x4. Since our vulnerability leads us to the left, we’ll slide on over to the left and hit our next stop.

ECX now contains the value 0x4. If some value is subtracted by ECX and the result is zero, we will head on to the right; otherwise, we continue to the left. Keep note of our new value of 0x4. Since our vulnerability leads us to the left, we’ll continue to our next stop.

Lastly, if some value is subtracted by ECX (which is 0x4) and the result is 0, we continue to the right and we land on our function.

With our new information, we can just add these new values to the original starting code and there you have it! The code to reach this vulnerable function.

What I’m most interested in is our if statement that we looked over in the source code. The starting point begins at 00014c86 by cleaning up the stack to prep for our conditional. If the result of that comparison is not zero, meaning if our values don’t match, it will lead you to the right and THAT folks….is where all the magic happens!

Let’s start crafting the PoC…

All this is doing is grabbing a handle to the driver and sending the IOCTL with the value “0xBAD0B0B0”.

If we place a breakpoint on 0x00014c89, we can see the comparison go through and do its thang and all is well. If you send the wrong value, 0xBAD0B00B in my case, we can see more action happen…

We can see EAX (bad0b0b0) being compared to our value (bad0b00b). 

We reach our block here where it’s doing a couple print statements and most importantly at our last line, setting ESI to 0. I can place a breakpoint on 0x00014cE7 and see what is going on when it hits our next function that is shown below:

At address 0x00014CF4, it is calling the NULL page and you can see how it looks when stepping through the instructions.

You can see the ESI register get zeroed and looking for something at 0x00000004. Can we control this?? We have to figure out if we can and how to get shellcode at this address if so.

Let the Fun Begin!

You can allocate a page with VirtualAlloc but you will soon find out that it can’t allocate anything under 0x1000. Luckily for us, we have undocumented functions to save the day…NtAllocateVirtualMemory. You can look up undocumented functions on MSDN (kinda sorta), Process Hacker and NTinternals. A couple resources to get you started, but here is how this function goes:

So I need to allocate my NULL page and write dummy shellcode at 0x4. The interesting thing about allocating a NULL page is you can’t just allocate at 0x00; you would need to allocate by 0x01 so it could round off to zero. Interesting, huh?

As a side note, my code is kind of big to pull the address and use NtAllocateVirtualMemory from Ntdll but you can reference in the complete PoC

To test the waters, we can add 0x41’s at the start of 0x4.

If all goes well, we SHOULD be able to see our 0x41’s…

We can see that our four 0x41’s are chillin right there at 0x4. Awesome! 🙂

FINISH HIM!!!

Now that I have full control of everything, it’s time for the privesc! We can use the same shellcode we used for the stack overflow. The only difference is that we can leave out the code that recovers a BSoD.

After compiling and running…what do we get?? System shell!!

Come get some!!

As always, I would encourage everyone that comes across this to try it for yourself! It is pretty fun to do and besides…who doesn’t want to make their very own privesc?!

The full PoC is below:

 

 

Leave a Reply

Your email address will not be published. Required fields are marked *