Friday, January 23, 2009

Registry Code Updates

I've found a couple bugs in the registry code I released recently, and at least one is significant enough that a new release is warranted. Teach me to release code I wrote in a couple hours on a plane ;)

The list of fixes is:
  • Fix a bug that prevented any volatile subkeys from appearing when using the subkeys() function.
  • Add a check for None when using lsadump (reported by Paul Bobby, thanks!)
  • Add appropriate license statements at the top of each file (thanks AAron!). For the record, the license is the GNU General Public License (GPL).
You can download the new version as a zip or tarball, and install it exactly as the previous version, by extracting it into your Volatility directory. If you have a previous version installed, this should just overwrite it (though you may have to tell your unzip program that's okay). As before, PyCrypto is required for the credential extraction modules.

One final note: I have seen some crashes when people attempt to use the hash extraction code, but pass the wrong address for the hive in memory. I'd like to fix this, but I don't yet have a good way of checking to make sure that a given hive is the SYSTEM or SAM or SECURITY hive. I'll try to find something that works, though, and release it with the next update.

Friday, January 16, 2009

Memory Registry Tools!

Hi everyone! I know it's a bit late, but I made you all a Christmas present: tools for accessing registry data in Windows memory dumps. This the work that I presented at DFRWS 2008; it took a while to release because I had to find time to port it to Volatility 1.3.

To use them, grab either the zip or the tarball and extract it to your Volatility directory. You'll get the following new plugins (along with some supporting files):
  • hivescan: finds the physical address of CMHIVE structures, which represent a registry hives in memory
  • hivelist: takes a physical address of one CMHIVE, returns the virtual address of all hives, and their names
  • printkey: takes a virtual address of a hive and a key name (e.g., 'ControlSet001\Control'), and display the key's timestamp, values and subkeys
  • hashdump: dump the LanMan and NT hashes from the registry (deobfuscated). See this post for more details on how this is accomplished.
  • lsadump: dump the LSA secrets (decrypted) from the registry. See this post for more information.
  • cachedump: dump any cached domain password hashes from the registry. This will obviously only work if the memory image comes from a machine that was part of a domain. See this post for more details.
In general, when you start working with an image you should:
  1. Use hivescan to find the physical address of a hive.
  2. Pass one of those (any of them should do) to hivelist using the -o option. This will give you the virtual address of each of the hives in memory.
  3. With this list in hand, you can now examine individual keys within a hive using printkey, or use hashdump, lsadump, or cachedump to extract credentials from the memory image. The latter three need the virtual addresses of specific hives (SYSTEM and SAM for hashdump, SYSTEM and SECURITY for lsadump and cachedump).
The full list of options available for each command can be obtained with --help. Note that hashdump, lsadump, and cachedump require PyCrypto in order to de-obfuscate the various credentials!

If you're curious how registry access works under the hood, you can read my DFRWS paper or presentation, or check out the blog posts I wrote while doing that research: Enumerating Registry Hives, Reading Open Keys, and Cell Index Translation. And, of course, you can always just look at the source code :)

Some final, closing thoughts. Harlan Carvey's RegRipper has been a huge sucess, and has shown a lot of people how much forensic information is stored in the registry. It would be awesome if this great tool could be applied to memory forensics, but unfortunately I have not yet figured out a way to integrate the two. However, this perl module looks promising; perhaps someone could write a Python wrapper around my registry code that would expose an interface compatible with Parse::Win32Registry, allowing RegRipper to run against a memory image with only slight modifications.

Of course, since RegRipper plugins are all written in Perl, you could also just see what they're doing and reimplement it as a Volatility plugin! To make that easier, here's a quick guide to using the new registry API in Volatility:
  1. Start by opening a hive and assigning it to an address space. The HiveAddressSpace represents a hive in memory, and takes a virtual address space and offset to a hive as a base. Also, because the registry types are not part of Volatility's standard types, you need to add them in.
    from forensics.win32.hive2 import HiveAddressSpace
    from forensics.win32.regtypes import regtypes
    syshive = HiveAddressSpace(addr_space, types, syshive_address)

  2. Next, use the get_root() function to find the root key of the hive. You need to pass in the current profile.
    from forensics.win32.rawreg import *
    from forensics.object2 import Profile
    theProfile = Profile()
    root = get_root(syshive, theProfile)

  3. To open a key, use open_key():
    key = open_key(root, ["ControlSet001", "Control", "Lsa"])
    print key.Name

  4. To get a list of subkeys of a key, use subkeys():
    for sk in subkeys(key):
    print sk.Name

  5. To get the values of a key, use values():
    for v in values(key):
    print v.Name

  6. To parse the value data and return it in a more meaningful representation, use value_data():

    for v in values(key):
    val_type, val_data = value_data(v)
    print v.Name, val_type, val_data

That's pretty much all you need to know! You can access other attributes of keys and values as members of the Python objects returned. The attributes available can be found in; keys are _CM_KEY_NODE objects and values are _CM_KEY_VALUE objects.

I don't have time to write any more, unfortunately, but I hope these will be useful to people! I'll try to post an example of a RegRipper plugin converted to a Volatility one soon so there's a concrete example to work with. Until then, enjoy and feel free to e-mail me (or leave comments) with any questions!

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/, and point it at the memory address of a kernel module.

Naturally, I've made a plugin that implements this: grab 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)

-h, --help show this help message and exit
(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!