Thursday, August 23, 2012

Auto GHAST

Wow crap, I've been slacking. Sorry about that. At the same time, I sort of haven't because I'm happy to release my really really alpha auto ghast tool. This is basically a framework that I will end up building out to trace punkbuster and any other driver I need to analyze. I plan on doing a more formal write up later but I figured some people who are semi-familiar with pykd will appreciate some of the stuff I'm working on :>.  Basically the idea is to have a method to set breakpoints with callbacks where I can record various registers, values, structures or whatever else I need over the course of running through the driver. In particular for pnkbstrk.sys I want to record all IOCTLs along with various IRP information. You can sort of see what I'm doing in my 'testing.py' script which I walk through later in this post.

I've also included a built winxp sys driver which is actually just the generic WinDDK ioctl sample driver + exe. If you use the ioctlapp.exe it will install/load the sioctl.sys driver and call it with 4 different IOCTLs. My auto ghast tool was built by repeatedly running/testing with this.

Anyways, here's auto ghast in action recording a single breakpoint:
auto ghast automatically setting breakpoints/recording data
What's nice is all I need to do is set a breakpoint on driver load then run !py testing.py and it does the following:

  1. It steps into the DriverEntry function
  2. Grabs the DriverObject ptr and creates a custom 'driver' object that we can use in the program.
  3. By calling driver.get_driver_by_address(esp) it will extract the pointer and give us access to the drivers properties
  4. Prints out the base/end/entry addresses
  5. Runs through the entire DriverEntry function
  6. Extracts the IRP_MJ_DEVICE_CONTROL address (driver.get_device_control_address())
  7. Creates a custom breakpoint object that I've designed. Set's up various information to record for the breakpoint when it's callback handler is called
  8. Sets the breakpoint
  9. Runs the program

What's nice about having a custom recorder is that we can extract/work with various registers, memory addresses or whatever we want for each time the breakpoint is hit. I'll fix up the documentation of it later but please consider this VERY ALPHA!

Finally, thanks to a blog post about pykdtrace which allowed me to figure out that I needed to return DEBUG_STATUS_GO from my debug handler (was banging my head!) to get the dang thing to continue to run.

Check out my ghast git repo for the code!