Monday, April 23, 2012

Sneaky Sneaky... PnkBstrK.sys's hidden code.

As you might recall from my last post I'm now in the process of determining what the IOCTLs do. There was however one thing that was really bugging me. I didn't allude to this yet because I figured I was doing something stupid and just didn't understand how the driver's code was being mapped into memory by Windows. It turns out PnkBstrK.sys is doing something a little bit sneaky. Before I get into showing what they are doing,  I want to describe the problem.

When attempting to determine what the IOCTLs are actually doing I was noticing the first IOCTL that was "attempted" was calling a function which after doing some oddness, was jumping into some memory location that wasn't showing up in IDA. The first IOCTL that is seen by our DeviceControlDispatchHandler function is 0x2261c0.
First function that is called from the 0x2261c0 IOCTL.
 This function clears out some addresses and moves the value 0x3f onto the stack. Then jumps into some unknown address.
A jmp into an unknown memory address.
This is where I was stuck. I had no idea where this memory location was coming from. So I figured they were jumping into a non .text section. If you aren't familiar with the various sections of a PE file I suggest reading the PECOFF document from Microsoft. So in IDA you can look at the various segments by hitting "Shift+F7" or View->Open Subview->Segments. Here's basically what I saw:
PnkBstrK.sys segments
You'll notice none of those addresses are within range of our 'unknown' jmp address. Ok so now what? I honestly had no idea. When debugging the driver and that ioctl is called, it jmps to the unknown address but magically a valid code block is there. But how? I can't see any of the data in the segments and I certainly can't see any data in the .text segment. I called shenanigans.

I totally reset my vmware image thinking that some how during installation it was doing something to create this page in memory without me catching it in time. My first suspicion was that code was being called before the DriverEntry method. I searched all over Microsoft documentation to see if there was any other way of calling a driver besides the DriverEntry function. While I found out there is, it's only if you rename the DriverEntry function to something else (which this driver is not doing).

So I decided to look at something else. I loaded up PEiD which is a tool for looking at the segments. My thought process here was that they were doing something to trick IDA Pro. Here's what PEiD reports:
PEiD section output
OK so, basically the same thing. So I went back to WinDBG to see if there were any other hints. You may remember from a long time ago, one of the methods I use in RE'ing (because I suck at it) is to use surrounding data as possible hints to what the code is doing. In this case I am looking at surrounding data to find hints as to where the code came from. So here's what I see at that address in the data output (instead of looking at the disassembly) of our "unknown" address:
The data at our unknown address. Note the VeriSign certificate information
OK so that is a pretty good hint. So going back to IDA I searched for the string VeriSign (alt+T to search for text) and guess what. Absolutely nothing. So I had one last thought. Maybe it's not really contained in a valid segment at all, maybe it's contained in the binary and they're doing a hardcoded jmp? So I want to look at the PECOFF structure. For that I use 010Editor with the PECOFF template. I load the file, open the template and run the template against PnkBstrK.sys. I notice the following bits of data:
Overlay? What the hell is that?
So there's this 'overlay' section, and the data?
There you are! You sneaky bastard!
So in the EXE template I looked at how 'overlay' data is generated and I found they simply check:

if(max < FileSize()) {
   BYTE Overlay[FileSize()-max];

That is all they are doing. PnkBstrK.sys isn't creating a section for it, they're just appending the data which will still get mapped into memory and then they are 'hardcoding' the jmp to the offset into this extra data area. Pretty sneaky.

It is almost like a magic trick, at first it seems like magic, then you realize you're just an idiot for not knowing how it worked to begin with.

NOW I can start to figure out what these IOCTLs do :>

1 comment: