After having obtained a memory image using FireWire (or other methods), I eventually wanted to actually examine what was going on as the image was taken.
Installing Volatility
Volatility is a framework that helps ripping interesting information out of a Windows XP memory dump. Although “strings” and “dd” are good tools, analysing 1GB of binary crap is not really a fun thing to do. Volatility knows how to parse the memory and allows to do fancy stuff on the memory.
Installation of Volatility is a bit weird because it is obviously written for Windows and they hardcode the path of a Windows Python interpreter. Also, their module system is a bit weird, but in fairness works at least alrightish. The application itself is funnily packaged. They don’t really make use of namespaces and depend on modules being locally available.
That made it painful produce a Debian/Ubuntu package, but I made it and you can find it in my PPA. To install volatility through that PPA, you might want to do a:
sudo add-apt-repository ppa:ubuntu-bugs-auftrags-killer/muelli && sudo apt-get update && sudo apt-get install volatility
I think I packaged every available module so that you don’t need to go through 13 stupid^W very helpful but funny pages. You can see the available commands via plugins here:
muelli@xbox:/tmp$ volatility
/usr/lib/pymodules/python2.6/forensics/win32/crashdump.py:31: DeprecationWarning: the sha module is deprecated; use the hashlib module instead
import sha
*** Unable to load module kernel_hooks: No module named pefile
*** Unable to load module usermode_hooks2: No module named pefile
*** Unable to load module malfind2: No module named pydasm
*** Unable to load module kernel_hooks: No module named pefile
*** Unable to load module usermode_hooks2: No module named pefile
*** Unable to load module malfind2: No module named pydasm
Volatile Systems Volatility Framework v1.3
Copyright (C) 2007,2008 Volatile Systems
Copyright (C) 2007 Komoku, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
usage: volatility cmd [cmd_opts]
Run command cmd with options cmd_opts
For help on a specific command, run 'volatility cmd --help'
Supported Internal Commands:
connections Print list of open connections
connscan Scan for connection objects
connscan2 Scan for connection objects (New)
datetime Get date/time information for image
dlllist Print list of loaded dlls for each process
dmp2raw Convert a crash dump to a raw dump
dmpchk Dump crash dump information
files Print list of open files for each process
hibinfo Convert hibernation file to linear raw image
ident Identify image properties
memdmp Dump the addressable memory for a process
memmap Print the memory map
modscan Scan for modules
modscan2 Scan for module objects (New)
modules Print list of loaded modules
procdump Dump a process to an executable sample
pslist Print list of running processes
psscan Scan for EPROCESS objects
psscan2 Scan for process objects (New)
raw2dmp Convert a raw dump to a crash dump
regobjkeys Print list of open regkeys for each process
sockets Print list of open sockets
sockscan Scan for socket objects
sockscan2 Scan for socket objects (New)
strings Match physical offsets to virtual addresses (may take a while, VERY verbose)
thrdscan Scan for ETHREAD objects
thrdscan2 Scan for thread objects (New)
vaddump Dump the Vad sections to files
vadinfo Dump the VAD info
vadwalk Walk the vad tree
Supported Plugin Commands:
cachedump Dump (decrypted) domain hashes from the registry
cryptoscan Find TrueCrypt passphrases
driverirp Print driver IRP function addresses
driverscan Scan for driver objects
fileobjscan Scan for file objects
getsids Print the SIDs owning each process
hashdump Dump (decrypted) LM and NT hashes from the registry
hivedump Dump registry hives to CSV
hivelist Print list of registry hives
hivescan Scan for _CMHIVE objects (registry hives)
idt Print Interrupt Descriptor Table (IDT) entries
intobjscan Scan for interrupt handler registrations
keyboardbuffer Print BIOS keyboard buffer
lsadump Dump (decrypted) LSA secrets from the registry
memmap_ex_2 Print the memory map
moddump Dump loaded kernel modules to disk.
mutantscan Scan for mutant (mutex) objects
objtypescan Scan for object type objects
orphan_threads Find kernel threads that don't map back to loaded modules
printkey Print a registry key, and its subkeys and values
pslist_ex_1 Print list running processes
pslist_ex_3 Print list running processes
pstree
ssdt Display SSDT entries
suspicious Find suspicious command lines and display them
symlinkobjscan Scan for symbolic link objects
thread_queues Print message queues for each thread
usrdmp_ex_2 Dump the address space for a process
Example: volatility pslist -f /path/to/my/file
muelli@xbox:/tmp$
So yeah, some warnings are due to missing dependencies. But it’s all packaged with the exception of pydasm. So if you have enough time at your hands, please do that 😉
If you have another module that you want to have added or if anything doesn’t work, please give me a shout.
Using Volatility
An interesting question might be whether someone has viewed a given picture. We know that the physical address space contains many 4kB sized pages. This is a problem for analysing the memory because we usually expect data to be larger than 4kB and this data is most likely fragmented in physical memory. So extracting a picture from the raw memory dump, while possible would be problematic. Our approach was to create a contiguous dump of a processes virtual memory address space and to search our target image in that memory dump. Fortunately, volatility is already able to dump a process’ virtual memory address space, which leaves us with the admittedly not too hard task of finding and extracting binary data of that picture.
We started by generating a list of running processes from the RAM image to identify the process ID of our target process (firefox in our case):
$ volatility pslist -f memorydump
Name Pid PPid Thds Hnds Time
firefox.exe 2212 2720 22 320 Sat Mar 20 14:33:29 2010
Afterwards, we dump the processes virtual memory, using the PID of that process, into a file. Using this we can start searching for our target picture in the process memory dump:
$ volatility memdmp -p 2212 -f memorydump
If we knew that the picture file that is being searched for was a JPEG and we found that these files have a start and end byte sequence 0xffd8 and 0xffd9 respectively. While this was helpful information we still need to narrow down our search. Using xxd we can take small byte sequences from the body of original picture and search for this sequence in the process’ ID image file. Using this method we are able to find the start of the JPEG picture, in the firefox process memory dump. Here, we can see that the start of the JPEG image marker (0xffd8) occurs at address 0x4e20008 in the image dump:
4e20000: 120e 0200 120e 0200 ffd8 ffe0 0010 4a46 ..............JF
4e20010: 4946 0001 0200 0064 0064 0000 ffec 0011 IF.....d.d......
4e20020: 4475 636b 7900 0100 0400 0000 3c00 00ff Ducky.......<...
Then from this point forwards in the file, a search for the JPEG end of file byte sequence (0xffd9) gives us the address of the end of the JPEG picture in the memory image file. Here we can see that the JPEG picture ends at address 0x4e40e19:
4e40e00: d5c2 5047 3401 82c7 b75c 5638 2624 461d ..PG4....\V8&$F.
4e40e10: 4c54 f6b1 3d3c 4b3f ffd9 6500 2800 2700 LT..=<K?..e.(.'.
4e40e20: 7000 7800 2700 2c00 2700 2700 2900 3b00 p.x.'.,.'.'.).;.
Then using dd with a block size of one byte, and knowing the start and end addresses of our picture image obtained above, we can get python to work out the decimal number of bytes to skip into the file and also the decimal number of bytes to count or read from that position.
$ dd if=2212.dmp bs=1 skip=$(python -c 'print 0x4e20008')
count=$(python -c 'print 0x4e40e20 - 0x4e20008') > recovered.jpg
134674+0 records in
134674+0 records out
134674 bytes (135 kB) copied, 0.812532 s, 166 kB/s
To verify that the picture extracted from RAM is the same as original picture we can get as hash of both files:
$ sha256sum Goofy\ Finger.jpg recovered.jpg
e87db764d0f2baccdd5b68dd0324c31ee2281a787d27de38c48e6e9c300b2349 Goofy Finger.jpg
e87db764d0f2baccdd5b68dd0324c31ee2281a787d27de38c48e6e9c300b2349 recovered.jpg
$ display recovered.jpg
Collecting Password Hashes
For password recovery purposes one might be interested in obtaining the hashed passwords of a running (Windows) system. As a nice side effect, we will gain all existing users on that system. Fortunately, a plugin for volatilty exists which allows dumping the password hashes. The process, however, is a bit cumbersome and could be more automated in the future. We start off finding Registry data in the memory using the hivescan command which will give us the offset of the data in memory. We scan two of these memory locations to make sure that we identify the Security and the System hive whichs addresses we have to remember (in our case 0xe1035b60 and 0xe16bdb60). With these addresses, we run the volatility hashdump tool which happily prints all the password hashes.
$ python volatility hivescan -f memorydump
/tmp/volatility-1.3b/forensics/win32/crashdump.py:31: DeprecationWarning: the sha module is deprecated; use the hashlib module instead
import sha
Offset (hex)
58175496 0x377b008
58202976 0x3781b60
63080280 0x3c28758
118954848 0x7171b60
268880736 0x1006cb60
292773896 0x11736008
294130688 0x11881400
414687240 0x18b7a008
421538656 0x19202b60
424552368 0x194e27b0
425945952 0x19636b60
436572168 0x1a059008
705187848 0x2a085008
$ python volatility hivelist -f memorydump -o 0x377b008
/tmp/volatility-1.3b/forensics/win32/crashdump.py:31: DeprecationWarning: the sha module is deprecated; use the hashlib module instead
import sha
Address Name
0xe1e8cb60 \DaS\joe\LS\AD\Microsoft\Windows\UsrClass.dat
0xe261f008 \DaS\joe\NTUSER.DAT
0xe1e65b60 \DaS\LocalService\LS\AD\Microsoft\Windows\UsrClass.dat
0xe1f14008 \DaS\LocalService\NTUSER.DAT
0xe1e797b0 \DaS\NetworkService\LS\AD\Microsoft\Windows\UsrClass.dat
0xe1e03008 \DaS\NetworkService\NTUSER.DAT
0xe1776008 \WINDOWS\system32\config\software
0xe1756400 \WINDOWS\system32\config\default
0xe16e3b60 \WINDOWS\system32\config\SECURITY
0xe16bdb60 \WINDOWS\system32\config\SAM
0xe14b8758 [no name]
0xe1035b60 \WINDOWS\system32\config\system
0xe102e008 [no name]
$ python volatility hivelist -f memorydump -o 0x1a059008
/tmp/volatility-1.3b/forensics/win32/crashdump.py:31: DeprecationWarning: the sha module is deprecated; use the hashlib module instead
import sha
Address Name
0xe1e03008 \Documents and Settings\NetworkService\NTUSER.DAT
0xe1776008 \WINDOWS\system32\config\software
0xe1756400 \WINDOWS\system32\config\default
0xe16e3b60 \WINDOWS\system32\config\SECURITY <-- Security Hive
0xe16bdb60 \WINDOWS\system32\config\SAM
0xe14b8758 [no name]
0xe1035b60 \WINDOWS\system32\config\system <-- System Hive
0xe102e008 [no name]
0xe1e8cb60 \DaS\joe\LS\AD\Microsoft\Windows\UsrClass.dat
0xe261f008 \DaS\joe\NTUSER.DAT
0xe1e65b60 \DaS\LocalService\LS\AD\Microsoft\Windows\UsrClass.dat
0xe1f14008 \DaS\LocalService\NTUSER.DAT
0xe1e797b0 \DaS\NetworkService\LS\AD\Microsoft\Windows\UsrClass.dat
$ python volatility hashdump -f memorydump -y 0xe1035b60 -s 0xe16bdb60
/tmp/volatility-1.3b/forensics/win32/crashdump.py:31: DeprecationWarning: the sha module is deprecated; use the hashlib module instead
import sha
Administrator:500:2637e35bf0422b90aad3b435b51404ee:48ff5741a4f96d75a9dc23432a6c2fb6:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
HelpAssistant:1000:69d67a492c3dd902282b6be852ba02cf:4672a0174e4f2400bb0fd10d50b9868c:::
SUPPORT_388945a0:1002:aad3b435b51404eeaad3b435b51404ee:c0e2f264bd5be499af3d7b9740579aa7:::
joe:1005:fb62f624fe735986aad3b435b51404ee:c025e7fccfbccc90b057725ef909f4e2:::
mary:1006:758cd98ba77b7ff8aad3b435b51404ee:67f301368e34e8d7a3e5def3d74dbbf2:::
$
Having obtained these hashes, one could use, i.e. Ophcrack to recover the password. A web based interface is available and successfully recovered each and every password (i.e.: empty, BLOGGS, MARY123, SMITH, KO*5VUMOWUKGAD). Advanced attacks such as Pass-The-Hash might also be possible.
It would be interesting to know, how to obtain password hashes from a running Linux or Mac system. The technique should be straight forward: Obtain RAM, get your own hash and search for this well known hash in memory. The harder work will then be to identify the data structures in which the hashes are embedded to reliably identify the hash storage for generality.