Volatility, my own cheatsheet (Part 1): Image Identification

In order to start a memory analysis with Volatility, the identification of the type of memory image is a mandatory step.
Here some usefull commands.

imageinfo

For a high level summary of the memory sample you’re analyzing, use the imageinfo command. Most often this command is used to identify the operating system, service pack, and hardware architecture (32 or 64 bit), but it also contains other useful information such as the DTB address and time the sample was collected.

$ vol.py -f ~/Desktop/win7_trial_64bit.raw imageinfo
Volatility Foundation Volatility Framework 2.4
Determining profile based on KDBG search...
Suggested Profile(s) : Win7SP0x64, Win7SP1x64, Win2008R2SP0x64, Win2008R2SP1x64
                     AS Layer1 : AMD64PagedMemory (Kernel AS)
                     AS Layer2 : FileAddressSpace (/Users/Michael/Desktop/win7_trial_64bit.raw)
                      PAE type : PAE
                           DTB : 0x187000L
                          KDBG : 0xf80002803070
          Number of Processors : 1
     Image Type (Service Pack) : 0
                KPCR for CPU 0 : 0xfffff80002804d00L
             KUSER_SHARED_DATA : 0xfffff78000000000L
           Image date and time : 2012-02-22 11:29:02 UTC+0000
     Image local date and time : 2012-02-22 03:29:02 -0800

The imageinfo output tells you the suggested profile that you should pass as the parameter to --profile=PROFILE when using other plugins. There may be more than one profile suggestion if profiles are closely related. It also prints the address of the KDBG (short for _KDDEBUGGER_DATA64) structure that will be used by plugins like pslist and modules to find the process and module list heads, respectively. In some cases, especially larger memory samples, there may be multiple KDBG structures. Similarly, if there are multiple processors, you’ll see the KPCR address and CPU number for each one.

Plugins automatically scan for the KPCR and KDBG values when they need them. However, you can specify the values directly for any plugin by providing --kpcr=ADDRESS or --kdbg=ADDRESS. By supplying the profile and KDBG (or failing that KPCR) to other Volatility commands, you’ll get the most accurate and fastest results possible.

Note: The imageinfo plugin will not work on hibernation files unless the correct profile is given in advance. This is because important structure definitions vary between different operating systems.


kdbgscan

As opposed to imageinfo which simply provides profile suggestions, kdbgscan is designed to positively identify the correct profile and the correct KDBG address (if there happen to be multiple). This plugin scans for the KDBGHeader signatures linked to Volatility profiles and applies sanity checks to reduce false positives. The verbosity of the output and number of sanity checks that can be performed depends on whether Volatility can find a DTB, so if you already know the correct profile (or if you have a profile suggestion from imageinfo), then make sure you use it.

Here’s an example scenario of when this plugin can be useful. You have a memory sample that you believe to be Windows 2003 SP2 x64, but pslist doesn’t show any processes. The pslist plugin relies on finding the process list head which is pointed to by KDBG. However, the plugin takes the first KDBG found in the memory sample, which is not always the best one. You may run into this problem if a KDBG with an invalid PsActiveProcessHead pointer is found earlier in a sample (i.e. at a lower physical offset) than the valid KDBG.

Notice below how kdbgscan picks up two KDBG structures: an invalid one (with 0 processes and 0 modules) is found first at 0xf80001172cb0and a valid one (with 37 processes and 116 modules) is found next at 0xf80001175cf0. In order to “fix” pslist for this sample, you would simply need to supply the --kdbg=0xf80001175cf0 to the plist plugin.

$ vol.py -f Win2K3SP2x64-6f1bedec.vmem --profile=Win2003SP2x64 kdbgscan
Volatility Foundation Volatility Framework 2.4
**************************************************
Instantiating KDBG using: Kernel AS Win2003SP2x64 (5.2.3791 64bit)
Offset (V)                    : 0xf80001172cb0
Offset (P)                    : 0x1172cb0
KDBG owner tag check          : True
Profile suggestion (KDBGHeader): Win2003SP2x64
Version64                     : 0xf80001172c70 (Major: 15, Minor: 3790)
Service Pack (CmNtCSDVersion) : 0
Build string (NtBuildLab)     : T?
PsActiveProcessHead           : 0xfffff800011947f0 (0 processes)
PsLoadedModuleList            : 0xfffff80001197ac0 (0 modules)
KernelBase                    : 0xfffff80001000000 (Matches MZ: True)
Major (OptionalHeader)        : 5
Minor (OptionalHeader)        : 2
**************************************************
Instantiating KDBG using: Kernel AS Win2003SP2x64 (5.2.3791 64bit)
Offset (V)                    : 0xf80001175cf0
Offset (P)                    : 0x1175cf0
KDBG owner tag check          : True
Profile suggestion (KDBGHeader): Win2003SP2x64
Version64                     : 0xf80001175cb0 (Major: 15, Minor: 3790)
Service Pack (CmNtCSDVersion) : 2
Build string (NtBuildLab)     : 3790.srv03_sp2_rtm.070216-1710
PsActiveProcessHead           : 0xfffff800011977f0 (37 processes)
PsLoadedModuleList            : 0xfffff8000119aae0 (116 modules)
KernelBase                    : 0xfffff80001000000 (Matches MZ: True)
Major (OptionalHeader)        : 5
Minor (OptionalHeader)        : 2
KPCR                          : 0xfffff80001177000 (CPU 0)

More info about KDBG:


kpcrscan

Use this command to scan for potential KPCR structures by checking for the self-referencing members as described by Finding Object Roots in Vista. On a multi-core system, each processor has its own KPCR. Therefore, you’ll see details for each processor, including IDT and GDT address; current, idle, and next threads; CPU number, vendor & speed; and CR3 value.

$ vol.py -f dang_win7_x64.raw --profile=Win7SP1x64 kpcrscan
Volatility Foundation Volatility Framework 2.4
**************************************************
Offset (V)                    : 0xf800029ead00
Offset (P)                    : 0x29ead00
KdVersionBlock                : 0x0
IDT                           : 0xfffff80000b95080
GDT                           : 0xfffff80000b95000
CurrentThread                 : 0xfffffa800cf694d0 TID 2148 (kd.exe:2964)
IdleThread                    : 0xfffff800029f8c40 TID 0 (Idle:0)
Details                       : CPU 0 (GenuineIntel @ 2128 MHz)
CR3/DTB                       : 0x1dcec000
**************************************************
Offset (V)                    : 0xf880009e7000
Offset (P)                    : 0x4d9e000
KdVersionBlock                : 0x0
IDT                           : 0xfffff880009f2540
GDT                           : 0xfffff880009f24c0
CurrentThread                 : 0xfffffa800cf694d0 TID 2148 (kd.exe:2964)
IdleThread                    : 0xfffff880009f1f40 TID 0 (Idle:0)
Details                       : CPU 1 (GenuineIntel @ 2220 MHz)
CR3/DTB                       : 0x1dcec000

If the KdVersionBlock is not null, then it may be possible to find the machine’s KDBG address via the KPCR. In fact, the backup method of finding KDBG used by plugins such as pslist is to leverage kpcrscan and then call the KPCR.get_kdbg() API function.


Comments