Tuesday, January 6, 2009

Plugin Post: Moddump

By now, you all probably know that you can dump running programs from memory using the procdump module in Volatility. But not all malware runs as a user-mode process. What about malicious kernel modules?


As it turns out, dumping these is also quite straightforward, and it's easy to write a plugin to do it. In fact, it's downright trivial -- kernel modules are just PE files mapped into kernel memory (in exactly the same way as normal programs are PE files mapped into user memory). So to dump a particular kernel module, we can use Volatility's built-in PE dumper (the source is in forensics/win32/executable.py, and point it at the memory address of a kernel module.


Naturally, I've made a plugin that implements this: grab moddump.py and put it in your memory_plugins directory, and you'll be good to go. Here's what it looks like in action:

$ python volatility moddump --help
Usage: moddump [options] (see --help)

Options:
-h, --help show this help message and exit
-f FILENAME, --file=FILENAME
(required) XP SP2 Image file
-b BASE, --base=BASE (optional, otherwise best guess is made)
Physical offset (in hex) of directory
table base
-t TYPE, --type=TYPE (optional, default="auto") Identify the
image type (pae, nopae, auto)
-m MODE, --mode=MODE strategy to use when saving executable.
Use "disk" to save using disk-based section
sizes, "mem" for memory-based sections.
(default: "mem")
-u, --unsafe do not perform sanity checks on sections
when dumping
-o OFFSET, --offset=OFFSET
dump module whose base address is OFFSET (hex)
-p REGEX, --pattern=REGEX
dump modules matching REGEX
-i, --ignore-case ignore case in pattern match


The "mode" and "unsafe" options do the same thing as in the procdump module. The other options are new though, so I'll go through them briefly here.


The -p option allows you to give a regular expression to specify which modules to dump. The -i option allows you to make this match case insensitive. If you don't give any way of specifying a module, it will simply dump all modules in the kernel's loaded module list.


Of course, if a driver is being stealthy, it could unlink itself from the kernel's list of loaded modules (just as processes can be hidden by removing from the systemwide process list). Often, these hidden drivers can be found by scanning memory for the data structure that represents a kernel module; Volatility's modscan and modscan2 are good for this. Once you've found the hidden module, you can pass its base address to moddump using the -o option.


Regardless of how you choose the modules to dump, they will be saved in a file called driver.BASE_ADDRESS.sys, where BASE_ADDRESS is the module's address im memory.


Anyway, I hope you'll get some good use out of this. It's also possible to create a similar plugin that dumps DLLs loaded in a process, but I haven't gotten around to writing it yet, so if anyone's looking to get their feet wet with writing plugins for Volatility it could be a fun first project.


Cheers and Happy New Year until next time!

6 comments:

JL said...

Cool! Keep up the good work! and Happy New Year :-)

echo6 said...

Nice Moyix, please find more time do the dll plugin ;-)

Keydet89 said...

Brendan,

Very nice! Always something good coming from your corner of the blogosphere.

What would it take to push the current Volatility capability beyond XP, to 2003 and Vista? I'd like to do what I can to help with that, even if it means learning Python (I really like what JL did w/ vol2html.pl and have some ideas for expanding that...)

Keep up the good work!

John Musbach said...

Hi, this looks like a very useful module...however with the latest version of volatility all I'm able to get is 0 byte files from this plugin. I'm using the command "python vol.py --profile -f moddump -D -o -u".

Where am I going wrong?

John Musbach said...

Sorry, for some reason part of my post got stripped...

For the "-f" parameter I use the image file name.

For "--profile" parameter I use the volatility profile name.

for "-D" I pass the destination directory.

For "-o" I pass the memory offset.

If you any ideas where I'm going wrong I'm all ears. Thanks!

John Musbach said...

My issue was resolved in volatility bug report 254 (http://code.google.com/p/volatility/issues/detail?id=254). Basically despite this blog post saying "-o" expects the offset being passed to it, you need to pass the value from the "modules" volatility command's base column to "-o" for moddump to work with a specific module.