Jingle BOFs, Jingle ROPs, Sploiting all the things… with Mona v2 !!
Ho Ho Ho friends,
It has been a while since we posted something on the Corelan Team blog, I guess we all have been busy doing … stuff and things, here and there. Nevertheless, as the year is close to filling up 100%, it’s probably a good time to start thinking about finding some convincing New Year’s resolutions and tracking down a useless habit that we can "promise" to give up in 2013.
I have done quite some travelling this year and I’m sure my family will be happy to find me at home for a change in the next 10 days. For those of you who know me well, that also means I should have *some* time to catch up with some old and new projects, do some research, etc.
One of the things that has been on my wish list for a long time is to have the ability to run mona.py from inside WinDBG. I think, aside from "world peace" and "justice for all", this would be the next best thing for mankind… sorta. No ? Ok, ok - maybe it’s not that important, but let’s be honest, wouldn’t it be just awesome to be able to do something like this :
Maybe, maybe not. Yeah I know, Photoshop skills FTW ! :)
I kind of like the Olly/Immunity GUI, but I also use Windbg for specific tasks and bugs. After all, WinDBG is fast and simply more reliable in certain scenario’s.
About 2 weeks ago, I was working on adding some functionality to mona.py, and was struggling with finding a way to clear all breakpoints from within mona. I couldn’t find how to do it and decided to post my question on twitter. I immediately got a couple of replies, including this one from @jduck1337 :
Then @WanderingGlitch commented :
That got me thinking … what if it was possible to take mona.py and run it under WinDBG… Wouldn’t that be great ?
It was time to do some research. I figured I would need to find a way to run python scripts from within WinDBG, and I would also need to find a solution for immlib, which is the library exposed by Immunity Debugger.
To run python scripts from inside WinDBG, we need a WinDBG extension. After binging Google around for a bit, I came across PyKD (http://pykd.codeplex.com). According to the PyKD project site:
This project can help to automate debugging and crash dump analysis using Python. It allows one to take the best from both worlds: the expressiveness and convenience of Python with the power of WinDbg! Additionally, pykd can work in two ways:
- It’s a Python module and can be used in any Python script
- Also it can be loaded as a WinDbg extension and provide service to control the debugger from a Python script
On top of that, the project is open source, so this looked exactly what I wanted & needed.
The PyKD documentation/API reference seemed very interesting, but I also noticed that some important functionality was missing. So I decided to give it a shot and contacted the PyKD author(s) to see if they would be open to add the desired functionality while I’m porting immlib into a library that is based on PyKD.
Honestly … I didn’t really expect any feedback.
About 5 minutes later, I got an email back, stating that they were interested and wanted to help.
Wow, I was amazed and excited. All of a sudden, it wasn’t just a crazy idea anymore. I realized that maybe, with some teamwork, it can be done after all…
So I started porting over parts of the immlib logic into a new python library file, which basically wraps around the PyKD functions. I sent emails back and forth with the PyKD folks, tested new versions and functionality… and this is where we are today !
Before we continue, I really have to thank the PyKD dev… I was pleasantly surprised by his reaction speed and level of support. Hat tip to you ! Keep up the good work.
Corelan Team is very pleased to be able to announce the public availability of mona.py v2, which will run under Immunity Debugger and WinDBG. Yep, that’s one debugger plugin, 2 debuggers. Of course, we worked on mona v2 offline for a while, but those of you that have been paying attention might have seen some "interesting" changes to mona.py in the last few weeks; and might have noticed that mona.py already made a first appearance on the Metasploit blog.
In case you have missed my tweet earlier today, you can still watch the release video here:
Anyways, back to work. To get the latest version of mona, simply run !mona update from within Immunity Debugger, or download it from the project page: http://redmine.corelan.be/projects/mona.
This is also the file that you will need for WinDBG, but of course, it won’t run without a little help. Maybe you don’t even have WinDBG installed yet. In short, we need 4 step procedure to get everything installed before we can run mona.py under WinDBG.
- Install WinDBG
- Install Python
- Install PyKD
- Install windbglib.py & mona.py
Current versions of WinDBG are part of the Windows 8 Software Development Kit or Windows Driver Kit packages. You can download the SDK or WDK here : http://msdn.microsoft.com/en-us/windows/hardware/gg463009.aspx. Note that the installation of the SDK and WDK is only supported under Windows Vista and up. To install WinDBG (v7), simply select the "Debugging Tools" in the setup wizard.
To install a more or less up-to-date version of WinDBG that still runs on Windows XP, you can grab a copy of the Windows 7 version of the Debugging Tools here: http://www.microsoft.com/en-us/download/details.aspx?id=8279. This package includes WinDBG v6.2.
In both cases, you will need to run the 32bit version of WinDBG. On Windows 7/8, you should find the 32 bit version in an x86 folder, probably at one of these location (or something similar):
C:\Program Files\Windows Kits\8.0\Debuggers\x86 C:\Program Files (x86)\Windows Kits\8.0\Debuggers\x86
Python & PyKD for WinDBG
In order to be able to run mona under WinDBG, you’ll need a bit of preparation. First of all, you will need python 2.7. If you have Immunity Debugger 1.8x installed, you should have python 2.7 installed as well. If not, grab a copy of python 2.7 from http://www.python.org/download/releases/2.7.3/. For the record, I recommend installing Immunity Debugger and the python distribution that comes with it, as that is the version I’m using to develop against. If you prefer to just install python and something breaks, you’re on your own.
WinDBG will only run python scripts using the PyKD extension. Head over to the http://pykd.codeplex.com website, open the "Downloads" section and go to the download page for the latest 0.2.x version (listed under "Other Downloads" on the right hand side of the page). Make sure to use the latest 0.2.x version, as mona.py won’t work with anything different than PyKD 0.2.0.11. In fact, mona will check what version you have installed and will complain if you are using the wrong version.
From the download page, you will need to download the pykd-0.2.0.11-python.2.7.zip file. Inside the zip file, you should find an x86 and x64 folder. You should find the following 2 files inside the x86 folder:
Copy the pykd.pyd file into the "winext" folder, which can be found inside the WinDBG application folder. The screenshot below was taken on my older XP machine, so the folder may be in a different location if you are using a different OS. In either case, locate the winext folder and put the pykd.pyd file in that directory.
Next, run vcredist_x86.exe and following the wizard to install the Visual Studio 2008 runtime.
Finally, find msdia90.dll on your system (the file should be placed somewhere under C:\Program Files\Common Files\Microsoft Shared\VC) and register it using regsvr32:
Note : If mona.py ever throws errors such as the one below, simply register msdia90.dll and you should be all set :
File "C:\Program Files\Windows Kits\8.0\Debuggers\x86\windbglib.py", line 53, in getPEBInfo return typedVar( "ntdll!_PEB", getCurrentProcess()) SymbolException: failed to load symbol file
To make things easy for you, I will host the latest compatible version of pykd.pyd (x86) and vcredist_x86.exe at this location: http://redmine.corelan.be/projects/windbglib/repository/raw/pykd/pykd.zip.
We’re almost done. We can now run python scripts from within WinDBG, but we still need the immlib logic before we can run mona.
I had to port the immlib logic that I needed for mona.py. I didn’t port all of immlib (yet), which means my library is not a one-to-one port … but I will add more functionality… and… hey, I accept patches.
You can find the library project page here : http://redmine.corelan.be/projects/windbglib. Again, you may or may not be able to use windbglib to run your own pycommands under WinDBG… If something is missing, feel free to port it, add it to windbglib.py and send me a diff file :)
Anyways, download windbglib.py from the project page and place it inside the WinDBG folder. To complete the setup, put a copy of mona.py inside that WinDBG folder as well:
That’s it. You are now ready to run mona.py.
Because we <3 automation, Lincoln wrote a small script that will grab all the necessary files, install dependencies and put everything in the right place. The only thing you need to do yourself is make sure you have python 2.7 available, and make sure WinDBG is installed.
You can download the install script here : http://redmine.corelan.be/projects/windbglib/files
Open an administrator command prompt and run the script:
C:\tmp>python install_windbglib.py [+] Downloading PYKD zip file from Corelan, this may take a few moments (4mb) [+] Unzipping download [+] Download complete, downloading mona.py & windbglib.py from Corelan [+] Installing VC redistributable [+] Locating msdia90.dll in C:\ [+] Registering 'msdia90.dll' with system located in: [*] C:\Program Files\Common Files\Microsoft Shared\VC [+] Locating windbg.exe in C:\ [+] Copy pykd.pyd & windbglib.py & mona.py into Windbg folder: [*] C:\Program Files\Debugging Tools for Windows (x86) [+] Complete. Open Windbg and test
Some of the PyKD features rely on proper symbol configuration in WinDBG. To configure WinDBG to retrieve and use the symbols for the OS, go to "File" – "Symbol File Path" and ensure the following configuration is set :
(of course, feel free to replace c:\windbgsymbols with a different folder. Make sure there are no spaces or newlines at the end of the symbol configuration). Close the dialog, close WinDBG and accept to save the workspace settings when prompted.
To make things easier for you, mona v2 will attempt to set the symbol path automatically, when it detects that the symbol path field is empty.
Running mona.py under WinDBG
Unlike Immunity Debugger, WinDBG needs to be attached to a process before you can run commands. After opening an executable in WinDBG (or attaching to a process), you should be able to see the command prompt at the bottom of the WinDBG "Command" window.
First of all, you need to load the PyKD extension. You need to do this every time you open a new WinDBG instance. To load the extension, run
You won’t get any feedback from WinDBG if the extension was loaded correctly. If you rename pykd.pyd to pykd.dll, you can also load PyKD without providing the .pyd file extension:
Again, you only need to do this one time, each time you open WinDBG.
If you want to automate this, you could create a shortcut to windbg.exe, and use the -c parameter to specify what command to execute when windbg launches.
windbg.exe -c ".load pykd.pyd"
To run a python script, you have to use the new !py command. So, in order to run mona, simply run
That’s it. From this point forward, mona should behave exactly the same as under Immunity Debugger. As a good practice, don’t forget to use the mona config option to set a workingfolder, and you’re all set.
I have noticed a little issue with the Command log output window. If large amounts of text are written to the window, then WinDBG doesn’t seem to automatically/correctly update the window. In other words, you may see something like this from time to time :
Although the indicator in the lower left corner doesn’t indicate that WinDBG is *BUSY* anymore, nothing seems to be written to the screen. To solve this, simply scroll the output window up and down. This will refresh the window and show the output on the screen. If anyone knows of a way to do this programmatically, let me know.
Updating mona & windbglib
The current version of windbglib might still be buggy. If you find bugs, please create an account on redmine, send me an email so I can approve your account, and open a ticket.
You can update both mona and windbglib using the following command:
!py mona update
Again, the mona.py file for Immunity Debugger and WinDBG is exactly the same. Running the update routine will only update the one used by a specific debugger though. It’s easier to keep the mona.py files separate. Trying to use just one mona.py file for both debuggers might cause issues as mona.py under WinDBG expects that it’s unable to load immlib.
Things you might notice
Certain features are faster, others are slower. Especially any assemble/disassemble related operation, and the use of MemoryPages within WinDBG/PyKD might be slightly slower. In an attempt to minimize the impact, I have reviewed and optimized certain mona.py routines and added some caching functionality. In other words, in general the performance shouldn’t be all that bad. Virtual Process Memory-wide searches (!mona suggest, !mona find without using -m, !mona findwild without using -m) will still be somewhat slower in WinDBG. There’s not much I can do about it now, but if I manage to find a better and generic way, I’ll implement it.
If you still believe mona on WinDBG is too slow to be productive, please go ahead and fix the script. Or fix WinDBG. Or PyKD. Or do things manually if that is more convenient and faster.
I also removed support for deferbp and calltrace under WinDBG. Deferred breakpoints is built-in into WinDBG, and I might put calltrace back when I have more time.
At the same time, I also added a couple of new functions:
- sehbp : will set breakpoints on all SE Handler function pointers
- pageacl : will show all pages, the access level, the module a page belongs to and the section in that module
- fillchunk (WinDBG only) : will fill a heap chunk, referenced by a register, with a character. Imagine you have a breakpoint set on a free of a heap chunk, and the pointer to the chunk is at ESP+4, you can run !py mona fillchunk -r [ESP+4] to find the heap chunk and fill it with A’s. Guess what happens if the app tries to use the freed chunk later on :)
Finally, I still need to implement a lot of things to make windbglib fully immlib-compliant, including porting the heap class and writing the heap.getChunks() method. I basically need to figure out how to get the allocated chunks for a given heap. Since you can do this directly within windbg, this is not a showstopper for now. Maybe I’ll just wrap around the windbg functionality and parse the output.
Whenever you have finished debugging an app, you may want to close WinDBG entirely. If you simply stop debugging and attach to a new process, you will most likely get an extension error.
IDA Pro ?
I guess it should be possible to write a similar library for IDA Pro, taking advantage of IDA libraries. In fact, it might actually be quite easy to do. I’m fortunate enough to have an IDA Pro license, but I also know a large part of the community doesn’t have IDA. That’s why I decided to focus on WinDBG first.
If someone is interested in working with me on porting the logic over to IDA, please get in touch. There will be beer in the end.
Special thanks to Fancy, Lincoln and Matt Molinyawe for test-driving the new library, Ange Albertini for his great work on documenting the PE file format, Wir3Gh0st for putting together the release video, the PyKD dev for being extremely responsive and implementing everything I needed in a very short amount of time, and @dualcoremusic for producing awesome music !
Of course, thanks to the entire Corelan Team for your support, and my family for allowing me the time to work on this.
Finally, thank YOU, the community !!
Merry Christmas & Happy New Year !!
Hack all the things !
If you want to tell us how much you like or dislike mona.py, or just want to hang out with us, by all means, feel free to join the #corelan IRC channel on Freenode. If you like our New Year present, don’t forget to let the world know (and use the #monav2 hashtag, so we can hear you)
If you have any questions about the use of mona.py, in Immunity Debugger or WinDBG, feel free to post your question in the forum.
© 2012 – 2015, Corelan Team (corelanc0d3r). All rights reserved.