1. Architecture of the Kernel-Mode Driver Framework
2. Architecture of the Windows Driver Foundation
3. I/O Flow and Dispatching in WDF Drivers
4. Handling IRPs: What Every Driver Writer Needs to Know
Since I have a little (and I mean very little) understanding of drivers, I do have a bit of a suspicion that the PnkBstrK.sys driver is simply reading in custom IOCTLs and acting upon them. However, I wanted to confirm this. I did a bit of reverse engineering of the PnkBstrK.sys DriverEntry function. You'll notice in my IDA output I renamed a lot of things (and added comments) to make understanding what was going on a bit easier. Remember ';' for adding comments and right click -> rename for renaming labels/functions whatever.
|PnkBstrK.sys DriverEntry function.|
Later on, you'll notice a call to IoCreateDevice with the "\\device\pnkbstrk" as the device name. Further down in the code a symbolic name "\\DosDevices\\pnkbstrk_link" is also created which the user-mode applications will most likely call. However, I have yet to verify this.
Which is actually my biggest problem, trying to figure out how user-mode code calls into this driver. After searching around I found a really good forum post on how to gain a bit of additional information when debugging drivers. From that post I learned if you are actively debugging PnkBstrK.sys there's a way you can determine what IRP handlers are mapped to. In WinDBG you run "!drvobj PnkBstrK 7" which gives the following output:
|PnkBstrK.sys IRP dispatch handlers|
Here's what the device control handler function looks like by itself:
|device control handler function with no comments/names.|
|Adding the IRP structure to IDA|
|DeviceControlDispatchHandler with comments.|
*After* reading that post, I tried running the commands he mentioned to see what the structures look like from WinDBG, but it went horribly wrong. Mainly because I wasn't referencing the value correctly.
|Attempting to display the IRP struct values using the wrong value.|
|_IRP.Tail (0x40) + CurrentStackLocation (0x20) => 0x60 = IO_STACK_LOCATION (I think?)|
Of course, next up is reversing what the different IOCTLs actually do. That might take me some time, but I'll keep at it, don't you worry.