MindshaRE: An Introduction to PyKD

July 19, 2018 | Abdul-Aziz Hariri

In our previous MindshaRE blogs, we discussed ways to find variants while bug hunting. In this blog, we decided to talk about something a little bit different, which is dynamic analysis. Specifically, we’ll look at scripting PyKD to achieve certain tasks.

PyKD helps in automating debugging tasks and crash dump analysis using python. The nice thing about PyKD is that it can be used in a standalone script or from inside WinDBG.

Installing PyKD

Installation of PyKD is straight forward - especially if we want to use it from inside WinDBG. To start, download the bootstrapper from https://githomelab.ru/pykd/pykd, then extract the DLL for the desired architecture (x86 or x64) to the winext directory of your WinDBG installation.

Once you have it copied, you can verify that it’s functioning correctly by loading pykd then executing “!help”:

You can also get an interactive console through the “!py” command in windbg:

0:008> !pip install pykd
Collecting pykd
   Downloading https://files.pythonhosted.org/packages/16/cb/712c6e3e77985f625875130d 0f0fb3426ee39aa3fc0369ce36bcf0bff8d9/pykd-0.3.3.4-cp27-none-win32.whl (8.9MB)
Installing collected packages: pykd
Successfully installed pykd-0.3.3.4

Executing Python scripts from inside WinDBG

PyKD has a rich API that allows us to do most of the functionalities that we do from inside WinDBG but from a python script.

One of the easiest functions to get started with is dbgCommand, which allows us to execute windbg commands from inside python.

For example:

Something a little bit more meaningful

Let’s do something more meaningful using the actual PyKD API. For this blog, I’ll write a small PyKD script that sets a breakpoint and dumps Javascript code that’s being executed.

In order to achieve this task, I’ll be using the following PyKD APIs:

pykd.module(mod_name): Takes the name of a loaded module as an argument. pykd.module(mod_name).begin(): Returns the base address of a loaded module. pykd.setBp(addr,handler): Takes two arguments the address of where to set the breakpoint and a function handler that handles the breakpoint when it gets hit. pykd.reg(register): Returns the value of a specific register. pykd.loadPtrs(addr,num): Dereferences an address and returns pointers in a list. pykd.loadWStr(addr): Load a unicode string from addr. pykd.go(): Continues execution. pykd.dprintln(str): Outputs a string in windbg window.

The idea is pretty simple. Set a breakpoint at a specific function and dump the JavaScript that is going to be executed:

The breakpoint handler would dereference one of the addresses on the stack and then dump the JavaScript statement that is being executed.

Output:

That’s it for today. In our next PyKD-related MindshaRE blog, we’ll dig deeper in PyKD and show how to write a small script that detects and records crashes for fuzzing purposes.

Until then, you can find me on Twitter at @AbdHariri and follow the team for the latest in exploit techniques and security patches.