Volatility, my own cheatsheet (Part 4): Kernel Memory and Objects

Let’s go down a bit more deeply in the system, and let’s go to find kernel modules into the memory dump.


To view the list of kernel drivers loaded on the system, use the modules command. This walks the doubly-linked list of LDR_DATA_TABLE_ENTRY structures pointed to by PsLoadedModuleList.
Similar to the pslist command, this relies on finding the KDBG structure. In rare cases, you may need to use kdbgscan to find the most appropriate KDBG structure address and then supply it to this plugin like — kdbg=ADDRESS.

It cannot find hidden/unlinked kernel drivers, however modscan serves that purpose. Also, since this plugin uses list walking techniques, you typically can assume that the order the modules are displayed in the output is the order they were loaded on the system. For example, below, ntoskrnl.exe was first to load, followed by hal.dll, etc.

$ vol.py -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 modules
Volatility Foundation Volatility Framework 2.4
Offset(V)          Name                 Base                             Size File
------------------ -------------------- ------------------ ------------------ ----
0xfffffa80004a11a0 ntoskrnl.exe         0xfffff8000261a000           0x5dd000 \SystemRoot\system32\ntoskrnl.exe
0xfffffa80004a10b0 hal.dll              0xfffff80002bf7000            0x49000 \SystemRoot\system32\hal.dll
0xfffffa80004a7950 kdcom.dll            0xfffff80000bb4000             0xa000 \SystemRoot\system32\kdcom.dll
0xfffffa80004a7860 mcupdate.dll         0xfffff88000c3a000            0x44000 \SystemRoot\system32\mcupdate_GenuineIntel.dll
0xfffffa80004a7780 PSHED.dll            0xfffff88000c7e000            0x14000 \SystemRoot\system32\PSHED.dll
0xfffffa80004a7690 CLFS.SYS             0xfffff88000c92000            0x5e000 \SystemRoot\system32\CLFS.SYS
0xfffffa80004a8010 CI.dll               0xfffff88000cf0000            0xc0000 \SystemRoot\system32\CI.dll

The output shows the offset of the LDR_DATA_TABLE_ENTRYstructure, which is a virtual address by default but can be specified as a physical address with the -P switch as shown below. In either case, the Base column is the virtual address of the module’s base in kernel memory (where you’d expect to find the PE header).

$ vol.py -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 modules -P
Volatility Foundation Volatility Framework 2.4
Offset(P)          Name                 Base                             Size File
------------------ -------------------- ------------------ ------------------ ----
0x0000000017fe01a0 ntoskrnl.exe         0xfffff8000261a000           0x5dd000 \SystemRoot\system32\ntoskrnl.exe
0x0000000017fe00b0 hal.dll              0xfffff80002bf7000            0x49000 \SystemRoot\system32\hal.dll
0x0000000017fe6950 kdcom.dll            0xfffff80000bb4000             0xa000 \SystemRoot\system32\kdcom.dll
0x0000000017fe6860 mcupdate.dll         0xfffff88000c3a000            0x44000 \SystemRoot\system32\mcupdate_GenuineIntel.dll
0x0000000017fe6780 PSHED.dll            0xfffff88000c7e000            0x14000 \SystemRoot\system32\PSHED.dll
0x0000000017fe6690 CLFS.SYS             0xfffff88000c92000            0x5e000 \SystemRoot\system32\CLFS.SYS
0x0000000017fe7010 CI.dll               0xfffff88000cf0000            0xc0000 \SystemRoot\system32\CI.dll


The modscan command finds LDR_DATA_TABLE_ENTRYstructures by scanning physical memory for pool tags. This can pick up previously unloaded drivers and drivers that have been hidden/unlinked by rootkits. Unlike modules the order of results has no relationship with the order in which the drivers loaded. As you can see below, DumpIt.sys was found at the lowest physical offset, but it was probably one of the last drivers to load (since it was used to acquire memory).

$ vol.py -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 modscan
Volatility Foundation Volatility Framework 2.4
Offset(P)          Name                 Base                             Size File
------------------ -------------------- ------------------ ------------------ ----
0x00000000173b90b0 DumpIt.sys           0xfffff88003980000            0x11000 \??\C:\Windows\SysWOW64\Drivers\DumpIt.sys
0x000000001745b180 mouhid.sys           0xfffff880037e9000             0xd000 \SystemRoot\system32\DRIVERS\mouhid.sys
0x0000000017473010 lltdio.sys           0xfffff88002585000            0x15000 \SystemRoot\system32\DRIVERS\lltdio.sys
0x000000001747f010 rspndr.sys           0xfffff8800259a000            0x18000 \SystemRoot\system32\DRIVERS\rspndr.sys
0x00000000174cac40 dxg.sys              0xfffff96000440000            0x1e000 \SystemRoot\System32\drivers\dxg.sys
0x0000000017600190 monitor.sys          0xfffff8800360c000             0xe000 \SystemRoot\system32\DRIVERS\monitor.sys
0x0000000017601170 HIDPARSE.SYS         0xfffff880037de000             0x9000 \SystemRoot\system32\DRIVERS\HIDPARSE.SYS
0x0000000017604180 USBD.SYS             0xfffff880037e7000             0x2000 \SystemRoot\system32\DRIVERS\USBD.SYS
0x0000000017611d70 cdrom.sys            0xfffff88001944000            0x2a000 \SystemRoot\system32\DRIVERS\cdrom.sys


To extract a kernel driver to a file, use the moddump command. Supply the output directory with -D or — dump-dir=DIR. Without any additional parameters, all drivers identified by modlist will be dumped. If you want a specific driver, supply a regular expression of the driver’s name with — regex=REGEX or the module’s base address with — base=BASE.

$ vol.py -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 moddump -D drivers/
Volatility Foundation Volatility Framework 2.4
Module Base        Module Name          Result
------------------ -------------------- ------
0xfffff8000261a000 ntoskrnl.exe         OK: driver.fffff8000261a000.sys
0xfffff80002bf7000 hal.dll              OK: driver.fffff80002bf7000.sys
0xfffff88000e5c000 intelide.sys         OK: driver.fffff88000e5c000.sys
0xfffff8800349b000 mouclass.sys         OK: driver.fffff8800349b000.sys
0xfffff88000f7c000 msisadrv.sys         OK: driver.fffff88000f7c000.sys
0xfffff880035c3000 ndistapi.sys         OK: driver.fffff880035c3000.sys
0xfffff88002c5d000 pacer.sys            OK: driver.fffff88002c5d000.sys

For more information:

Similar to dlldump, if critical parts of the PE header are not memory resident, then rebuilding/extracting the driver may fail. Additionally, for drivers that are mapped in different sessions (like win32k.sys), there is currently no way to specify which session to use when acquiring the driver sample.


To list the functions in the Native and GUI SSDTs, use the ssdt command. This displays the index, function name, and owning driver for each entry in the SSDT. Please note the following:

  • Windows has 4 SSDTs by default (you can add more with KeAddSystemServiceTable), but only 2 of them are used — one for Native functions in the NT module, and one for GUI functions in the win32k.sys module.
  • There are multiple ways to locate the SSDTs in memory. Most tools do it by finding the exported KeServiceDescriptorTable symbol in the NT module, but this is not the way Volatility works.
  • For x86 systems, Volatility scans for ETHREAD objects and gathers all unique ETHREAD.Tcb.ServiceTable pointers. This method is more robust and complete, because it can detect when rootkits make copies of the existing SSDTs and assign them to particular threads. Also see the threads command.
  • For x64 systems (which do not have an ETHREAD.Tcb.ServiceTable member) Volatility disassembles code in ntKeAddSystemServiceTable and finds its references to the KeServiceDescriptorTable and KeServiceDescriptorTableShadow symbols.
  • The order and total number of functions in the SSDTs differ across operating system versions. Thus, Volatility stores the information in a per-profile (OS) dictionary which is auto-generated and cross-referenced using the ntoskrnl.exe, ntdll.dll, win32k.sys, user32.dll and gdi32.dll modules from the respective systems.
$ vol.py -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 ssdt
    Volatility Foundation Volatility Framework 2.4
    [x64] Gathering all referenced SSDTs from KeAddSystemServiceTable...
    Finding appropriate address space for tables...
    SSDT[0] at fffff8000268cb00 with 401 entries
      Entry 0x0000: 0xfffff80002a9d190 (NtMapUserPhysicalPagesScatter) owned by ntoskrnl.exe
      Entry 0x0001: 0xfffff80002983a00 (NtWaitForSingleObject) owned by ntoskrnl.exe
      Entry 0x0002: 0xfffff80002683dd0 (NtCallbackReturn) owned by ntoskrnl.exe
      Entry 0x0003: 0xfffff800029a6b10 (NtReadFile) owned by ntoskrnl.exe
      Entry 0x0004: 0xfffff800029a4bb0 (NtDeviceIoControlFile) owned by ntoskrnl.exe
      Entry 0x0005: 0xfffff8000299fee0 (NtWriteFile) owned by ntoskrnl.exe
      Entry 0x0006: 0xfffff80002945dc0 (NtRemoveIoCompletion) owned by ntoskrnl.exe
      Entry 0x0007: 0xfffff80002942f10 (NtReleaseSemaphore) owned by ntoskrnl.exe
      Entry 0x0008: 0xfffff8000299ada0 (NtReplyWaitReceivePort) owned by ntoskrnl.exe
      Entry 0x0009: 0xfffff80002a6ce20 (NtReplyPort) owned by ntoskrnl.exe
    SSDT[1] at fffff96000101c00 with 827 entries
      Entry 0x1000: 0xfffff960000f5580 (NtUserGetThreadState) owned by win32k.sys
      Entry 0x1001: 0xfffff960000f2630 (NtUserPeekMessage) owned by win32k.sys
      Entry 0x1002: 0xfffff96000103c6c (NtUserCallOneParam) owned by win32k.sys
      Entry 0x1003: 0xfffff96000111dd0 (NtUserGetKeyState) owned by win32k.sys
      Entry 0x1004: 0xfffff9600010b1ac (NtUserInvalidateRect) owned by win32k.sys
      Entry 0x1005: 0xfffff96000103e70 (NtUserCallNoParam) owned by win32k.sys
      Entry 0x1006: 0xfffff960000fb5a0 (NtUserGetMessage) owned by win32k.sys
      Entry 0x1007: 0xfffff960000dfbec (NtUserMessageCall) owned by win32k.sys
      Entry 0x1008: 0xfffff960001056c4 (NtGdiBitBlt) owned by win32k.sys
      Entry 0x1009: 0xfffff960001fd750 (NtGdiGetCharSet) owned by win32k.sys

For more information:

To filter all functions which point to ntoskrnl.exe and win32k.sys, you can use egrep on command-line. This will only show hooked SSDT functions.

$ vol.py -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 ssdt | egrep -v '(ntos|win32k)'

Note that the NT module on your system may be ntkrnlpa.exe or ntkrnlmp.exe — so check that before using egrep of you’ll be filtering the wrong module name. Also be aware that this isn’t a hardened technique for finding hooks, as malware can load a driver named win32ktesting.sys and bypass your filter.


To find DRIVER_OBJECTs in physical memory using pool tag scanning, use the driverscan command. This is another way to locate kernel modules, although not all kernel modules have an associated DRIVER_OBJECT. The DRIVER_OBJECT is what contains the 28 IRP (Major Function) tables, thus the driverirp command is based on the methodology used by driverscan.

$ vol.py -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 driverscan
Volatility Foundation Volatility Framework 2.4
Offset(P)          #Ptr #Hnd Start                            Size Service Key          Name         Driver Name
------------------ ---- ---- ------------------ ------------------ -------------------- ------------ -----------
0x00000000174c6350    3    0 0xfffff880037e9000             0xd000 mouhid               mouhid       \Driver\mouhid
0x0000000017660cb0    3    0 0xfffff8800259a000            0x18000 rspndr               rspndr       \Driver\rspndr
0x0000000017663e70    3    0 0xfffff88002585000            0x15000 lltdio               lltdio       \Driver\lltdio
0x0000000017691d70    3    0 0xfffff88001944000            0x2a000 cdrom                cdrom        \Driver\cdrom
0x0000000017692a50    3    0 0xfffff8800196e000             0x9000 Null                 Null         \Driver\Null
0x0000000017695e70    3    0 0xfffff88001977000             0x7000 Beep                 Beep         \Driver\Beep
0x00000000176965c0    3    0 0xfffff8800197e000             0xe000 VgaSave              VgaSave      \Driver\VgaSave
0x000000001769fb00    4    0 0xfffff880019c1000             0x9000 RDPCDD               RDPCDD       \Driver\RDPCDD
0x00000000176a1720    3    0 0xfffff880019ca000             0x9000 RDPENCDD             RDPENCDD     \Driver\RDPENCDD
0x00000000176a2230    3    0 0xfffff880019d3000             0x9000 RDPREFMP             RDPREFMP     \Driver\RDPREFMP

For more information:


To find FILE_OBJECTs in physical memory using pool tag scanning, use the filescan command. This will find open files even if a rootkit is hiding the files on disk and if the rootkit hooks some API functions to hide the open handles on a live system. The output shows the physical offset of the FILE_OBJECT, file name, number of pointers to the object, number of handles to the object, and the effective permissions granted to the object.

$ vol.py -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 filescan
Volatility Foundation Volatility Framework 2.4
Offset(P)            #Ptr   #Hnd Access Name
------------------ ------ ------ ------ ----
0x000000000126f3a0     14      0 R--r-d \Windows\System32\mswsock.dll
0x000000000126fdc0     11      0 R--r-d \Windows\System32\ssdpsrv.dll
0x000000000468f7e0      6      0 R--r-d \Windows\System32\cryptsp.dll
0x000000000468fdc0     16      0 R--r-d \Windows\System32\Apphlpdm.dll
0x00000000048223a0      1      1 ------ \Endpoint
0x0000000004822a30     16      0 R--r-d \Windows\System32\kerberos.dll
0x0000000004906070     13      0 R--r-d \Windows\System32\wbem\repdrvfs.dll
0x0000000004906580      9      0 R--r-d \Windows\SysWOW64\netprofm.dll
0x0000000004906bf0      9      0 R--r-d \Windows\System32\wbem\wmiutils.dll
0x00000000049ce8e0      2      1 R--rwd \$Extend\$ObjId
0x00000000049cedd0      1      1 R--r-d \Windows\System32\en-US\vsstrace.dll.mui
0x0000000004a71070     17      1 R--r-d \Windows\System32\en-US\pnidui.dll.mui
0x0000000004a71440     11      0 R--r-d \Windows\System32\nci.dll
0x0000000004a719c0      1      1 ------ \srvsvc

For more information


To scan physical memory for KMUTANT objects with pool tag scanning, use the mutantscan command. By default, it displays all objects, but you can pass -s or — silent to only show named mutexes. The CID column contains the process ID and thread ID of the mutex owner if one exists.

$ vol.py -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 mutantscan --silent
Volatility Foundation Volatility Framework 2.4
Offset(P)          #Ptr #Hnd Signal Thread                   CID Name
------------------ ---- ---- ------ ------------------ --------- ----
0x000000000f702630    2    1      1 0x0000000000000000           {A3BD3259-3E4F-428a-84C8-F0463A9D3EB5}
0x00000000102fd930    2    1      1 0x0000000000000000           Feed Arbitration Shared Memory Mutex [ User : S-1-5-21-2628989162-3383567662-1028919141-1000 ]
0x00000000104e5e60    3    2      1 0x0000000000000000           ZoneAttributeCacheCounterMutex
0x0000000010c29e40    2    1      1 0x0000000000000000           _MSFTHISTORY_LOW_
0x0000000013035080    2    1      1 0x0000000000000000           c:userstestingappdatalocalmicrosoftfeeds cache
0x000000001722dfc0    2    1      1 0x0000000000000000           c:userstestingappdataroamingmicrosoftwindowsietldcachelow
0x00000000172497f0    2    1      1 0x0000000000000000           LRIEElevationPolicyMutex
0x000000001724bfc0    3    2      1 0x0000000000000000           BrowserEmulationSharedMemoryMutex
0x000000001724f400    2    1      1 0x0000000000000000           c:userstestingappdatalocalmicrosoftwindowshistorylowhistory.ie5mshist012012022220120223
0x000000001724f4c0    4    3      1 0x0000000000000000           _SHMSFTHISTORY_
0x00000000172517c0    2    1      1 0x0000000000000000           __DDrawExclMode__
0x00000000172783a0    2    1      1 0x0000000000000000           Lowhttp://sourceforge.net/
0x00000000172db840    4    3      1 0x0000000000000000           ConnHashTable<1892>_HashTable_Mutex
0x00000000172de1d0    2    1      1 0x0000000000000000           Feeds Store Mutex S-1-5-21-2628989162-3383567662-1028919141-1000
0x00000000173b8080    2    1      1 0x0000000000000000           DDrawDriverObjectListMutex
0x00000000173bd340    2    1      0 0xfffffa8000a216d0 1652:2000 ALTTAB_RUNNING_MUTEX
0x0000000017449c40    2    1      1 0x0000000000000000           DDrawWindowListMutex

For more information:


This plugin scans for symbolic link objects and outputs their information. In the past, this has been used to link drive letters (i.e. D:, E:, F:, etc) to true crypt volumes (i.e. \Device\TrueCryptVolume).

$ vol.py -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 symlinkscan
Volatility Foundation Volatility Framework 2.4
Offset(P)            #Ptr   #Hnd Creation time            From                 To                                                          
------------------ ------ ------ ------------------------ -------------------- ------------------------------------------------------------
0x0000000000469780      1      0 2012-02-22 20:03:13      UMB#UMB#1...e1ba19f} \Device\00000048                                            
0x0000000000754560      1      0 2012-02-22 20:03:15      ASYNCMAC             \Device\ASYNCMAC                                            
0x0000000000ef6cf0      2      1 2012-02-22 19:58:24      0                    \BaseNamedObjects                                           
0x00000000014b2a10      1      0 2012-02-22 20:02:10      LanmanRedirector     \Device\Mup\;LanmanRedirector                               
0x00000000053e56f0      1      0 2012-02-22 20:03:15      SW#{eeab7...abac361} \Device\KSENUM#00000001                                     
0x0000000005cc0770      1      0 2012-02-22 19:58:20      WanArpV6             \Device\WANARPV6                                            
0x0000000005cc0820      1      0 2012-02-22 19:58:20      WanArp               \Device\WANARP                                              
0x0000000008ffa680      1      0 2012-02-22 19:58:24      Global               \BaseNamedObjects                                           
0x0000000009594810      1      0 2012-02-22 19:58:24      KnownDllPath         C:\Windows\syswow64                                         
0x000000000968f5f0      1      0 2012-02-22 19:58:23      KnownDllPath         C:\Windows\system32                                         
0x000000000ab24060      1      0 2012-02-22 19:58:20      Volume{3b...f6e6963} \Device\CdRom0                                              
0x000000000ab24220      1      0 2012-02-22 19:58:21      {EE0434CC...863ACC2} \Device\NDMP2                                               
0x000000000abd3460      1      0 2012-02-22 19:58:21      ACPI#PNP0...91405dd} \Device\00000041                                            
0x000000000abd36f0      1      0 2012-02-22 19:58:21      {802389A0...A90C31A} \Device\NDMP3 

For more information:


To find ETHREAD objects in physical memory with pool tag scanning, use the thrdscan command. Since an ETHREAD contains fields that identify its parent process, you can use this technique to find hidden processes. One such use case is documented in the psxview command. Also, for verbose details, try the threads plugin.

$ vol.py -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 thrdscan
Volatility Foundation Volatility Framework 2.4
Offset(P)             PID    TID      Start Address Create Time               Exit Time                
------------------ ------ ------ ------------------ ------------------------- -------------------------
0x0000000008df68d0    280    392         0x77943260 2012-02-22 19:08:18                                
0x000000000eac3850   2040    144         0x76d73260 2012-02-22 11:28:59       2012-02-22 11:29:04      
0x000000000fd82590    880   1944         0x76d73260 2012-02-22 20:02:29       2012-02-22 20:02:29      
0x00000000103d15f0    880    884         0x76d73260 2012-02-22 19:58:43                                
0x00000000103e5480   1652   1788 0xfffff8a0010ed490 2012-02-22 20:03:44                                
0x00000000105a3940    916    324         0x76d73260 2012-02-22 20:02:07       2012-02-22 20:02:09      
0x00000000105b3560    816    824         0x76d73260 2012-02-22 19:58:42                                
0x00000000106d1710    916   1228         0x76d73260 2012-02-22 20:02:11                                
0x0000000010a349a0    816    820         0x76d73260 2012-02-22 19:58:41                                
0x0000000010bd1060   1892   2280         0x76d73260 2012-02-22 11:26:13                                
0x0000000010f24230    628    660         0x76d73260 2012-02-22 19:58:34                                
0x0000000010f27060    568    648 0xfffff8a0017c6650 2012-02-22 19:58:34


An important concept that every computer scientist, especially those who have spent time doing operating system research, is intimately familiar with is that of caching. Files are cached in memory for system performance as they are accessed and used. This makes the cache a valuable source from a forensic perspective since we are able to retrieve files that were in use correctly, instead of file carving which does not make use of how items are mapped in memory. Files may not be completely mapped in memory (also for performance), so missing sections are zero padded. Files dumped from memory can then be processed with external tools.

For more information:

There are several options in the dumpfiles plugin, for example:

-r REGEX, --regex=REGEX
                        Dump files matching REGEX
  -i, --ignore-case     Ignore case in pattern match
  -o OFFSET, --offset=OFFSET
                        Dump files for Process with physical address OFFSET
                        Dump File Object at physical address PHYSOFFSET
  -D DUMP_DIR, --dump-dir=DUMP_DIR
                        Directory in which to dump extracted files
  -S SUMMARY_FILE, --summary-file=SUMMARY_FILE
                        File where to store summary information
  -p PID, --pid=PID     Operate on these Process IDs (comma-separated)
  -n, --name            Include extracted filename in output file path
  -u, --unsafe          Relax safety constraints for more data
  -F FILTER, --filter=FILTER
                        Filters to apply (comma-separated)

By default, dumpfiles iterates through the VAD and extracts all files that are mapped as DataSectionObject, ImageSectionObject or SharedCacheMap. As an investigator, however, you may want to perform a more targeted search. You can use the -r and -i flags to specify a case-insensitive regex of a filename. In the output below, you can see where the file was dumped from (DataSectionObject, ImageSectionObject or SharedCacheMap), the offset of the _FILE_OBJECT, the PID of the process whose VAD contained the file and the file path on disk:

$ vol.py -f mebromi.raw dumpfiles -D output/ -r evt$ -i -S summary.txt
Volatility Foundation Volatility Framework 2.4
DataSectionObject 0x81ed6240   684    \Device\HarddiskVolume1\WINDOWS\system32\config\AppEvent.Evt
SharedCacheMap 0x81ed6240   684    \Device\HarddiskVolume1\WINDOWS\system32\config\AppEvent.Evt
DataSectionObject 0x8217beb0   684    \Device\HarddiskVolume1\WINDOWS\system32\config\SecEvent.Evt
DataSectionObject 0x8217bd78   684    \Device\HarddiskVolume1\WINDOWS\system32\config\SysEvent.Evt
SharedCacheMap 0x8217bd78   684    \Device\HarddiskVolume1\WINDOWS\system32\config\SysEvent.Evt
$ ls output/
file.684.0x81fc6ed0.vacb    file.684.0x82256a48.dat     file.684.0x82256e48.dat     file.None.0x82339cd8.vacb
file.684.0x8217b720.vacb    file.684.0x82256c50.dat     file.None.0x82339c70.dat

The dumped filename is in the format of:


The OFFSET is the offset of the SharedCacheMap or the _CONTROL_AREA, not the _FILE_OBJECT.

The extension (EXT) can be:

  • img — ImageSectionObject
  • dat — DataSectionObject
  • vacb — SharedCacheMap

You can look at the -S/--summary-file in order to map the file back to its original filename:

{"name": "\\Device\\HarddiskVolume1\\WINDOWS\\system32\\config\\AppEvent.Evt", "ofpath": "dumpfiles/file.684.0x82256e48.dat", "pid": 684,...

You can also use the parsesummary.py script to parse out the json output of the summary file. The following shows an example of using this script. In addition to the original file name, PID of the process that had the file open and size, you can see which pages were present and which pages were missing and padded with zeros in the parsed summary output:

$ vol.py -f grrcon.img dumpfiles --summary=grrcon_summary.json -D output/ 
Volatility Foundation Volatility Framework 2.4
$ python parsesummary.py grrcon_summary.json |less
File: \Device\HarddiskVolume1\Documents and Settings\administrator\NTUSER.DAT -> output/file.4.0x82245008.vacb
        PID: 4
        _FILE_OBJECT offset: 0x821cd9e8
        Type: SharedCacheMap
        Size: 262144
        Present Pages:
                Offset(V): 0xde5c0000, Length: 4096
                Offset(V): 0xde5c1000, Length: 4096
                Offset(V): 0xde5c2000, Length: 4096
                Offset(V): 0xde5c3000, Length: 4096
                FileOffset: 0xde62e000 x 0x1000
                FileOffset: 0xde62f000 x 0x1000
                FileOffset: 0xde630000 x 0x1000
                FileOffset: 0xde631000 x 0x1000
                FileOffset: 0xde632000 x 0x1000

Or you can use the -n/--name option in order to dump file the files with the original filename.

Not every file will be currently active or in the VAD, and such files will not be dumped when using the -r/--regex option. For these files you can first scan for a _FILE_OBJECT and then use the -Q/--physoffset flag to extract the file. Special NTFS files are examples of files that must be dumped specifically:

$ vol.py -f mebromi.raw filescan |grep -i mft
Volatility Foundation Volatility Framework 2.4
0x02410900      3      0 RWD--- \Device\HarddiskVolume1\$Mft
0x02539e30      3      0 RWD--- \Device\HarddiskVolume1\$Mft
0x025ac868      3      0 RWD--- \Device\HarddiskVolume1\$MftMirr
$ vol.py -f mebromi.raw dumpfiles -D output/ -Q 0x02539e30
Volatility Foundation Volatility Framework 2.4
DataSectionObject 0x02539e30   None   \Device\HarddiskVolume1\$Mft
SharedCacheMap 0x02539e30   None   \Device\HarddiskVolume1\$Mft

The -f/--filter option allows you to specify which view of the file you would like to dump (DataSectionObject, ImageSectionObject or SharedCacheMap). For example, if you wanted to only see the state information for an executable file, you could specify --filter=ImageSectionObject.


Windows stores information on recently unloaded drivers for debugging purposes. This gives you an alternative way to determine what happened on a system, besides the well known modules and modscan plugins.

$ vol.py -f win7_trial_64bit.raw unloadedmodules --profile=Win7SP0x64
Volatility Foundation Volatility Framework 2.4
Name                 StartAddress       EndAddress         Time
-------------------- ------------------ ------------------ ----
dump_dumpfve.sys     0xfffff88001931000 0xfffff88001944000 2012-02-22 19:58:21 
dump_atapi.sys       0xfffff88001928000 0xfffff88001931000 2012-02-22 19:58:21 
dump_ataport.sys     0xfffff8800191c000 0xfffff88001928000 2012-02-22 19:58:21 
crashdmp.sys         0xfffff8800190e000 0xfffff8800191c000 2012-02-22 19:58:21

Bitscout — The Free Remote Digital Forensics Tool Builder

Kaspersky Releases an Open Source Digital Forensics Tool

Bitscout initially started as a hobby project a few years ago (version 1.0 was never released to the public), and it has been continually improved based on the requirements that arose in Kaspersky investigations involving digital forensics.

Bitscout 2.0 enables forensic investigators to remotely analyze a system, and allow the system’s owner to monitor the expert’s activities and ensure that their access is limited to the targeted disks.

The owner of the system on which forensic analysis will be conducted simply must boot the system from a CD/USBDongle provided by the investigator, allowing the analyst to connect remotely to Bitscout over SSH using a VPN.

Bitscout includes several popular tools designed for forensic analysis and uses a text-based user interface in order to make it easy to operate:

Bitscout relies on 3 roles in the process of remote forensics:
1. The Owner
 The owner is a user who has physical access to the target system and owns it.
 The owner’s role is to download, verify and burn Live ISO image file to a
 removable storage. After that the target system must be started from this
 bootable media. In case of LAN DHCP network configuration everything shall 
 work automatically. In case of other setup, the owner has to configure
 network access using management utility that is available on the Live system
 (starts automatically on the TTY1 on boot).
2. The Expert
 The expert is a remote user that connects to the target system over SSH using
 VPN link through the expert’s server. Bitscout shall be built with VPN server
 certificates, configuration and SSH keys placed on the disk image.
3. Expert’s Server
 The expert’s server shall be located in the internet and is used to run a VPN
 server as well as chat server for communication.


1. Transparent

a. You build your own Live disk instead of using someone else’s. The build
 process is straightforward and verbose. There is no place for mistrust, given
 that the OS repositories are trusted.
 b. Live disk image is built using bash scripts only and standard Ubuntu tools
 and packages, making it both transparent and customizable for all.
 c. Owner can monitor what is going on in expert’s container. It’s possible to
 attach and monitor changes in the expert’s container as root.

2. Forensically sound

a. We have tested that Bitscout doesn’t modify hard drive data or other storage media attached to the system. This is essential base for forensic operations.
b. Bitscout contains most popular tools to acquire and analyze harddrive disk images on site.
c. The owner of the system has to manually authorize which disk devices to be accessible by the expert in read-only (or read-write) mode.
d. While running as root the expert cannot modify or reset access to the provided devices, which prevents potential data loss from the source disk.

3. Customizable

a. The set of tools available on Bitscout can be easily customized by editing respective text files in the script directory before building. You can add standard packages or your own tools to it. Make it available to expert, system owner or both.
b. Both system owner and expert can install additional software packages on already running system. All changes will be done indepently (expert can’t change owner’s environment) and only in memory.
c. If certain operations require more memory or large disk which is not available on the system, the owner may attach writable external storage device (such as fast USB flash memory) to be used for storage or swap.

4. Compact

a. Bitscout project is designed to be minimal yet universal tool to access remote storage device. It contains minimal set of packages, libraries and tools to start the system and provide most common forensic tools to the expert immediately. Certain optimizations yet to be added to reduce size even further. All suggestions and contributions are welcome!
b. The system uses no graphical interface on purpose. This reduces disk image size and used RAM.
c. The expert’s environment runs as unprivileged LXC container, which saves from overhead of full virtualization. The container relies on the same kernel as the host system.
d. The container spawns from overlayed source rootfs. This allows to avoid duplication of system binaries and configuration. Yet, mapped with copy-on-write access it provides almost unlimited modification of the whole OS. The real limit is just the size of available memory and swap.
As a matter of fact fully running OS with a child OS inside the container used less than 32Mb of RAM in our tests.

More information and downloads


Volatility, my own cheatsheet (Part 3): Process Memory

Let’s try to analyze the memory in more detail…

If we try to analyze the memory more thoroughly, without focusing only on the processes, we can find other interesting information.


The memmap command shows you exactly which pages are memory resident, given a specific process DTB (or kernel DTB if you use this plugin on the Idle or System process). It shows you the virtual address of the page, the corresponding physical offset of the page, and the size of the page. The map information generated by this plugin comes from the underlying address space’s get_available_addresses method.

As of 2.1, the new column DumpFileOffset helps you correlate the output of memmap with the dump file produced by the memdump plugin. For example, according to the output below, the page at virtual address 0x0000000000058000 in the System process’s memory can be found at offset 0x00000000162ed000 of the win7_trial_64bit.raw file. After using memdump to extract the addressable memory of the System process to an individual file, you can find this page at offset 0x8000.

$ vol.py -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 memmap -p 4 
Volatility Foundation Volatility Framework 2.4
System pid:      4
Virtual            Physical                         Size     DumpFileOffset
------------------ ------------------ ------------------ ------------------
0x0000000000050000 0x0000000000cbc000             0x1000                0x0
0x0000000000051000 0x0000000015ec6000             0x1000             0x1000
0x0000000000052000 0x000000000f5e7000             0x1000             0x2000
0x0000000000053000 0x0000000005e28000             0x1000             0x3000
0x0000000000054000 0x0000000008b29000             0x1000             0x4000
0x0000000000055000 0x00000000155b8000             0x1000             0x5000
0x0000000000056000 0x000000000926e000             0x1000             0x6000
0x0000000000057000 0x0000000002dac000             0x1000             0x7000
0x0000000000058000 0x00000000162ed000             0x1000             0x8000


To extract all memory resident pages in a process (see memmap for details) into an individual file, use the memdump command.

Supply the output directory with -D or — dump-dir=DIR.

$ vol.py -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 memdump -p 4 -D dump/
Volatility Foundation Volatility Framework 2.4
Writing System [     4] to 4.dmp
$ ls -alh dump/4.dmp 
-rw-r--r--  1 Michael  staff   111M Jun 24 15:47 dump/4.dmp

To conclude the demonstration we began in the memmap discussion, we should now be able to make an assertion regarding the relationship of the mapped and extracted pages:

$ vol.py -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 volshell
Volatility Foundation Volatility Framework 2.4
Current context: process System, pid=4, ppid=0 DTB=0x187000
Welcome to volshell Current memory image is:
To get help, type 'hh()'
>>> PAGE_SIZE = 0x1000
>>> assert addrspace().read(0x0000000000058000, PAGE_SIZE) == 
...        addrspace().base.read(0x00000000162ed000, PAGE_SIZE) == 
...        open("dump/4.dmp", "rb").read()[0x8000:0x8000 + PAGE_SIZE]


To dump a process’s executable, use the procdump command. Optionally, pass the --unsafe or -u flags to bypass certain sanity checks used when parsing the PE header. Some malware will intentionally forge size fields in the PE header so that memory dumping tools fail.

Use --memory to include slack space between the PE sections that aren’t page aligned. Without --memory you’ll get a file that more closely resembles the file on disk, before sections expanded.

More information:


$ vol.py -f win7_trial_64bit.raw --profile=Win7SP0x64 procdump -D dump/ -p 296
Volatility Foundation Volatility Framework 2.4
Dumping csrss.exe, pid:    296 output: executable.296.exe
$ file dump/executable.296.exe 
dump/executable.296.exe: PE32+ executable for MS Windows (native) Mono/.Net assembly


The vadinfo command displays extended information about a process’s VAD nodes. In particular, it shows:

  • The address of the MMVAD structure in kernel memory
  • The starting and ending virtual addresses in process memory that the MMVAD structure pertains to
  • The VAD Tag
  • The VAD flags, control flags, etc
  • The name of the memory mapped file (if one exists)
  • The memory protection constant (permissions). Note there is a difference between the original protection and current protection. The original protection is derived from the flProtect parameter to VirtualAlloc. For example you can reserve memory (MEM_RESERVE) with protection PAGE_NOACCESS (original protection). Later, you can call VirtualAlloc again to commit (MEM_COMMIT) and specify PAGE_READWRITE (becomes current protection). The vadinfo command shows the original protection only. Thus, just because you see PAGE_NOACCESS here, it doesn’t mean code in the region cannot be read, written, or executed.
$ vol.py -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 vadinfo -p 296
    Volatility Foundation Volatility Framework 2.4
    Pid:    296
    VAD node @ 0xfffffa8000c00620 Start 0x000000007f0e0000 End 0x000000007ffdffff Tag VadS
    Flags: PrivateMemory: 1, Protection: 1
    Protection: PAGE_READONLY
    Vad Type: VadNone


    VAD node @ 0xfffffa8000c04ce0 Start 0x000007fefcd00000 End 0x000007fefcd10fff Tag Vad 
    Flags: CommitCharge: 2, Protection: 7, VadType: 2
    Vad Type: VadImageMap
    ControlArea @fffffa8000c04d70 Segment fffff8a000c45c10
    Dereference list: Flink 00000000, Blink 00000000
    NumberOfSectionReferences:          0 NumberOfPfnReferences:          13
    NumberOfMappedViews:                2 NumberOfUserReferences:          2
    WaitingForDeletion Event:  00000000
    Control Flags: Accessed: 1, File: 1, Image: 1
    FileObject @fffffa8000c074d0, Name: WindowsSystem32basesrv.dll
    First prototype PTE: fffff8a000c45c58 Last contiguous PTE: fffffffffffffffc
    Flags2: Inherit: 1

More information on the VAD:



To inspect a process’s VAD nodes in table form, use the vadwalk command.

$ vol.py -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 vadwalk -p 296
Volatility Foundation Volatility Framework 2.4
Pid:    296
Address            Parent             Left               Right              Start              End                Tag 
------------------ ------------------ ------------------ ------------------ ------------------ ------------------ ----
0xfffffa8000c00620 0x0000000000000000 0xfffffa8000deaa40 0xfffffa8000c043d0 0x000000007f0e0000 0x000000007ffdffff VadS
0xfffffa8000deaa40 0xfffffa8000c00620 0xfffffa8000bc4660 0xfffffa80011b8d80 0x0000000000ae0000 0x0000000000b1ffff VadS
0xfffffa8000bc4660 0xfffffa8000deaa40 0xfffffa8000c04260 0xfffffa8000c91010 0x00000000004d0000 0x0000000000650fff Vadm
0xfffffa8000c04260 0xfffffa8000bc4660 0xfffffa8000c82010 0xfffffa80012acce0 0x00000000002a0000 0x000000000039ffff VadS
0xfffffa8000c82010 0xfffffa8000c04260 0xfffffa8000cbce80 0xfffffa8000c00330 0x00000000001f0000 0x00000000001f0fff Vadm
0xfffffa8000cbce80 0xfffffa8000c82010 0xfffffa8000bc4790 0xfffffa8000d9bb80 0x0000000000180000 0x0000000000181fff Vad 
0xfffffa8000bc4790 0xfffffa8000cbce80 0xfffffa8000c00380 0xfffffa8000e673a0 0x0000000000100000 0x0000000000166fff Vad 
0xfffffa8000c00380 0xfffffa8000bc4790 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x00000000000fffff VadS


To display the VAD nodes in a visual tree form, use the vadtree command.

$ vol.py -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 vadtree -p 296
Volatility Foundation Volatility Framework 2.4
Pid:    296
 0x000000007f0e0000 - 0x000000007ffdffff
  0x0000000000ae0000 - 0x0000000000b1ffff
   0x00000000004d0000 - 0x0000000000650fff
    0x00000000002a0000 - 0x000000000039ffff
     0x00000000001f0000 - 0x00000000001f0fff
      0x0000000000180000 - 0x0000000000181fff
       0x0000000000100000 - 0x0000000000166fff
        0x0000000000000000 - 0x00000000000fffff
        0x0000000000170000 - 0x0000000000170fff
       0x00000000001a0000 - 0x00000000001a1fff
        0x0000000000190000 - 0x0000000000190fff
        0x00000000001b0000 - 0x00000000001effff
      0x0000000000240000 - 0x000000000024ffff
       0x0000000000210000 - 0x0000000000216fff
        0x0000000000200000 - 0x000000000020ffff

If you want to view the balanced binary tree in Graphviz format, just add --output=dot --output-file=graph.dot to your command. Then you can open graph.dot in any Graphviz-compatible viewer. This plugin also supports color coding the output based on the regions that contain stacks, heaps, mapped files, DLLs, etc. A partial example is shown below using Omnigraffle:

Fillcolor Legend:

  • Red: Heaps
  • Gray: DLLs
  • Green: Stacks
  • Yellow: Mapped Files


To extract the range of pages described by a VAD node, use the vaddump command. This is similar to memdump, except the pages belonging to each VAD node are placed in separate files (named according to the starting and ending addresses) instead of one large conglomerate file. If any pages in the range are not memory resident, they’re padded with 0’s using the address space’s zread() method.

$ vol.py -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 vaddump -D vads
Volatility Foundation Volatility Framework 2.4
Pid        Process              Start              End                Result
---------- -------------------- ------------------ ------------------ ------
         4 System               0x0000000076d40000 0x0000000076eeafff vads/System.17fef9e0.0x0000000076d40000-0x0000000076eeafff.dmp
         4 System               0x0000000000040000 0x0000000000040fff vads/System.17fef9e0.0x0000000000040000-0x0000000000040fff.dmp
         4 System               0x0000000000010000 0x0000000000032fff vads/System.17fef9e0.0x0000000000010000-0x0000000000032fff.dmp
         4 System               0x000000007ffe0000 0x000000007ffeffff vads/System.17fef9e0.0x000000007ffe0000-0x000000007ffeffff.dmp
         4 System               0x0000000076f20000 0x000000007709ffff vads/System.17fef9e0.0x0000000076f20000-0x000000007709ffff.dmp
       208 smss.exe             0x000000007efe0000 0x000000007ffdffff vads/smss.exe.176e97f0.0x000000007efe0000-0x000000007ffdffff.dmp
       208 smss.exe             0x00000000003d0000 0x00000000004cffff vads/smss.exe.176e97f0.0x00000000003d0000-0x00000000004cffff.dmp
       208 smss.exe             0x0000000000100000 0x0000000000100fff vads/smss.exe.176e97f0.0x0000000000100000-0x0000000000100fff.dmp
       208 smss.exe             0x0000000000000000 0x00000000000fffff vads/smss.exe.176e97f0.0x0000000000000000-0x00000000000fffff.dmp
       208 smss.exe             0x0000000000190000 0x000000000020ffff vads/smss.exe.176e97f0.0x0000000000190000-0x000000000020ffff.dmp
       208 smss.exe             0x0000000047a90000 0x0000000047aaffff vads/smss.exe.176e97f0.0x0000000047a90000-0x0000000047aaffff.dmp
       208 smss.exe             0x00000000005e0000 0x000000000065ffff vads/smss.exe.176e97f0.0x00000000005e0000-0x000000000065ffff.dmp
$ ls -al vads/
total 123720
drwxr-xr-x  69 michaelligh  staff      2346 Apr  6 13:12 .
drwxr-xr-x  37 michaelligh  staff      1258 Apr  6 13:11 ..
-rw-r--r--   1 michaelligh  staff    143360 Apr  6 13:12 System.17fef9e0.0x0000000000010000-0x0000000000032fff.dmp
-rw-r--r--   1 michaelligh  staff      4096 Apr  6 13:12 System.17fef9e0.0x0000000000040000-0x0000000000040fff.dmp
-rw-r--r--   1 michaelligh  staff   1748992 Apr  6 13:12 System.17fef9e0.0x0000000076d40000-0x0000000076eeafff.dmp
-rw-r--r--   1 michaelligh  staff   1572864 Apr  6 13:12 System.17fef9e0.0x0000000076f20000-0x000000007709ffff.dmp
-rw-r--r--   1 michaelligh  staff     65536 Apr  6 13:12 System.17fef9e0.0x000000007ffe0000-0x000000007ffeffff.dmp
-rw-r--r--   1 michaelligh  staff   1048576 Apr  6 13:12 csrss.exe.176006c0.0x0000000000000000-0x00000000000fffff.dmp
-rw-r--r--   1 michaelligh  staff    421888 Apr  6 13:12 csrss.exe.176006c0.0x0000000000100000-0x0000000000166fff.dmp
-rw-r--r--   1 michaelligh  staff      4096 Apr  6 13:12 csrss.exe.176006c0.0x0000000000170000-0x0000000000170fff.dmp
-rw-r--r--   1 michaelligh  staff      8192 Apr  6 13:12 csrss.exe.176006c0.0x0000000000180000-0x0000000000181fff.dmp

The files are named like this:


The reason the PhysicalOffset field exists is so you can distinguish between two processes with the same name.


The evtlogs command extracts and parses binary event logs from memory. Binary event logs are found on Windows XP and 2003 machines, therefore this plugin only works on these architectures. These files are extracted from VAD of the services.exe process, parsed and dumped to a specified location.

$ vol.py -f WinXPSP1x64.vmem --profile=WinXPSP2x64 evtlogs -D output
Volatility Foundation Volatility Framework 2.4
Parsed data sent to appevent.txt
Parsed data sent to secevent.txt
Parsed data sent to sysevent.txt

There is also an option (--save-evt) to dump raw event logs for parsing with external tools:

$ vol.py -f WinXPSP1x64.vmem --profile=WinXPSP2x64 evtlogs
--save-evt -D output
Volatility Foundation Volatility Framework 2.4
Saved raw .evt file to appevent.evt
Parsed data sent to appevent.txt
Saved raw .evt file to secevent.evt
Parsed data sent to secevent.txt
Saved raw .evt file to sysevent.evt
Parsed data sent to sysevent.txt

Parsed output is pipe delimited to make it easier to import into excel files and the “messages” are separated by semicolons:

$ cat output/secevent.txt
2012-01-17 12:01:27|secevent.evt|MACHINENAME|S-1-5-18 (Local System)|Security|612|Success|-;-;+;-;-;-;-;-;-;-;-;-;-;-;-;-;+;-;MACHINENAME$;;(0x0,0x3E7)
2012-01-17 17:06:18|secevent.evt|MACHINENAME|S-1-5-19 (NT Authority)|Security|528|Success|LOCAL SERVICE;NT AUTHORITY;(0x0,0x3E5);5;Advapi;Negotiate;;-;MACHINENAME$(0x0,0x3E7);252;-;-;-
2012-01-17 17:06:18|secevent.evt|MACHINENAME|S-1-5-19 (NT Authority)|Security|576|Success|LOCAL SERVICE;NT AUTHORITY;(0x0,0x3E5);SeAuditPrivilege            SeAssignPrimaryTokenPrivilege                   SeImpersonatePrivilege
2012-01-17 17:06:19|secevent.evt|MACHINENAME|S-1-5-20 (NT Authority)|Security|528|Success|NETWORK SERVICE;NT AUTHORITY;(0x0,0x3E4);5;Advapi;Negotiate;;-;MACHINENAME$(0x0,0x3E7);252;-;-;-
2012-01-17 17:06:19|secevent.evt|MACHINENAME|S-1-5-20 (NT Authority)|Security|576|Success|NETWORK SERVICE;NTAUTHORITY;(0x0,0x3E4);SeAuditPrivilege                  SeAssignPrimaryTokenPrivilege                   SeImpersonatePrivilege

If the --verbose flag is used, SIDs are also evaluated and placed in the parsed output instead of the defaulting raw SID. This action takes longer to run, since the plugin has to calculate each of the service SID and user SID from registry entries.


This plugin recovers fragments of IE history index.dat cache files. It can find basic accessed links (via FTP or HTTP), redirected links ( — REDR), and deleted entries ( — LEAK). It applies to any process which loads and uses the wininet.dll library, not just Internet Explorer. Typically that includes Windows Explorer and even malware samples.

More information:


$ vol.py -f exemplar17_1.vmem iehistory
Volatility Foundation Volatility Framework 2.4
Process: 1928 explorer.exe
Cache type "URL " at 0xf25100
Record length: 0x100
Location: Visited: [email protected]://
Last modified: 2009-01-08 01:52:09 
Last accessed: 2009-01-08 01:52:09 
File Offset: 0x100, Data Offset: 0x0, Data Length: 0xa0
Process: 1928 explorer.exe
Cache type "URL " at 0xf25300
Record length: 0x180
Location: Visited: [email protected]://www.abcjmp.com/jump1/?affiliate=mu1&subid=88037&terms=eminem&sid=Z605044303%40%40wMfNTNxkTM1EzX5QzNy81My8lM18FN4gTM2gzNzITM&a=zh5&mr=1&rc=0
Last modified: 2009-01-08 01:52:44 
Last accessed: 2009-01-08 01:52:44 
File Offset: 0x180, Data Offset: 0x0, Data Length: 0x108



Volatility, my own cheatsheet (Part 2): Processes and DLLs

Once identified the correct profile, we can start to analyze the processes in the memory and, when the dump come from a windows system, the loaded DLLs.


To list the processes of a system, use the pslist command. This walks the doubly-linked list pointed to by PsActiveProcessHead and shows the offset, process name, process ID, the parent process ID, number of threads, number of handles, and date/time when the process started and exited. As of 2.1 it also shows the Session ID and if the process is a Wow64 process (it uses a 32 bit address space on a 64 bit kernel).

This plugin does not detect hidden or unlinked processes (but psscan can do that).

If you see processes with 0 threads, 0 handles, and/or a non-empty exit time, the process may not actually still be active.

For more information, see

Below, you’ll notice regsvr32.exe has terminated even though its still in the “active” list.

Also note the two processes System and smss.exe will not have a Session ID, because System starts before sessions are established and smss.exeis the session manager itself.

$ vol.py -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 pslist
Volatility Foundation Volatility Framework 2.4
Offset(V)          Name                    PID   PPID   Thds     Hnds   Sess  Wow64 Start                Exit                
------------------ -------------------- ------ ------ ------ -------- ------ ------ -------------------- --------------------
0xfffffa80004b09e0 System                    4      0     78      489 ------      0 2012-02-22 19:58:20                      
0xfffffa8000ce97f0 smss.exe                208      4      2       29 ------      0 2012-02-22 19:58:20                      
0xfffffa8000c006c0 csrss.exe               296    288      9      385      0      0 2012-02-22 19:58:24                      
0xfffffa8000c92300 wininit.exe             332    288      3       74      0      0 2012-02-22 19:58:30                      
0xfffffa8000c06b30 csrss.exe               344    324      7      252      1      0 2012-02-22 19:58:30                      
0xfffffa8000c80b30 winlogon.exe            372    324      5      136      1      0 2012-02-22 19:58:31                      
0xfffffa8000c5eb30 services.exe            428    332      6      193      0      0 2012-02-22 19:58:32                      
0xfffffa80011c5700 lsass.exe               444    332      6      557      0      0 2012-02-22 19:58:32                      
0xfffffa8000ea31b0 lsm.exe                 452    332     10      133      0      0 2012-02-22 19:58:32                      
0xfffffa8001296b30 svchost.exe             568    428     10      352      0      0 2012-02-22 19:58:34                      
0xfffffa80012c3620 svchost.exe             628    428      6      247      0      0 2012-02-22 19:58:34                      
0xfffffa8001325950 sppsvc.exe              816    428      5      154      0      0 2012-02-22 19:58:41                      
0xfffffa80007b7960 svchost.exe             856    428     16      404      0      0 2012-02-22 19:58:43                      
0xfffffa80007bb750 svchost.exe             880    428     34     1118      0      0 2012-02-22 19:58:43                      
0xfffffa80007d09e0 svchost.exe             916    428     19      443      0      0 2012-02-22 19:58:43                      
0xfffffa8000c64840 svchost.exe             348    428     14      338      0      0 2012-02-22 20:02:07                      
0xfffffa8000c09630 svchost.exe             504    428     16      496      0      0 2012-02-22 20:02:07                      
0xfffffa8000e86690 spoolsv.exe            1076    428     12      271      0      0 2012-02-22 20:02:10                      
0xfffffa8000518b30 svchost.exe            1104    428     18      307      0      0 2012-02-22 20:02:10                      
0xfffffa800094d960 wlms.exe               1264    428      4       43      0      0 2012-02-22 20:02:11                      
0xfffffa8000995b30 svchost.exe            1736    428     12      200      0      0 2012-02-22 20:02:25                      
0xfffffa8000aa0b30 SearchIndexer.         1800    428     12      757      0      0 2012-02-22 20:02:26                      
0xfffffa8000aea630 taskhost.exe           1144    428      7      189      1      0 2012-02-22 20:02:41                      
0xfffffa8000eafb30 dwm.exe                1476    856      3       71      1      0 2012-02-22 20:02:41                      
0xfffffa80008f3420 explorer.exe           1652    840     21      760      1      0 2012-02-22 20:02:42                      
0xfffffa8000c9a630 regsvr32.exe           1180   1652      0 --------      1      0 2012-02-22 20:03:05  2012-02-22 20:03:08 
0xfffffa8000a03b30 rundll32.exe           2016    568      3       67      1      0 2012-02-22 20:03:16                      
0xfffffa8000a4f630 svchost.exe            1432    428     12      350      0      0 2012-02-22 20:04:14                      
0xfffffa8000999780 iexplore.exe           1892   1652     19      688      1      1 2012-02-22 11:26:12                      
0xfffffa80010c9060 iexplore.exe           2820   1892     23      733      1      1 2012-02-22 11:26:15                      
0xfffffa8001016060 DumpIt.exe             2860   1652      2       42      1      1 2012-02-22 11:28:59                      
0xfffffa8000acab30 conhost.exe            2236    344      2       51      1      0 2012-02-22 11:28:59

By default, pslist shows virtual offsets for the _EPROCESS but the physical offset can be obtained with the -P switch:

$ vol.py -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 pslist -P 
Volatility Foundation Volatility Framework 2.4
Offset(P)          Name                    PID   PPID   Thds     Hnds   Sess  Wow64 Start                Exit                
------------------ -------------------- ------ ------ ------ -------- ------ ------ -------------------- --------------------
0x0000000017fef9e0 System                    4      0     78      489 ------      0 2012-02-22 19:58:20                      
0x00000000176e97f0 smss.exe                208      4      2       29 ------      0 2012-02-22 19:58:20                      
0x00000000176006c0 csrss.exe               296    288      9      385      0      0 2012-02-22 19:58:24                      
0x0000000017692300 wininit.exe             332    288      3       74      0      0 2012-02-22 19:58:30                      
0x0000000017606b30 csrss.exe               344    324      7      252      1      0 2012-02-22 19:58:30


To view the process listing in tree form, use the pstree command. This enumerates processes using the same technique as pslist, so it will also not show hidden or unlinked processes. Child process are indicated using indention and periods.

$ vol.py -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 pstree
Volatility Foundation Volatility Framework 2.4
Name                                                  Pid   PPid   Thds   Hnds Time                
-------------------------------------------------- ------ ------ ------ ------ --------------------
 0xfffffa80004b09e0:System                              4      0     78    489 2012-02-22 19:58:20 
. 0xfffffa8000ce97f0:smss.exe                         208      4      2     29 2012-02-22 19:58:20 
 0xfffffa8000c006c0:csrss.exe                         296    288      9    385 2012-02-22 19:58:24 
 0xfffffa8000c92300:wininit.exe                       332    288      3     74 2012-02-22 19:58:30 
. 0xfffffa8000c5eb30:services.exe                     428    332      6    193 2012-02-22 19:58:32 
.. 0xfffffa8000aa0b30:SearchIndexer.                 1800    428     12    757 2012-02-22 20:02:26 
.. 0xfffffa80007d09e0:svchost.exe                     916    428     19    443 2012-02-22 19:58:43 
.. 0xfffffa8000a4f630:svchost.exe                    1432    428     12    350 2012-02-22 20:04:14 
.. 0xfffffa800094d960:wlms.exe                       1264    428      4     43 2012-02-22 20:02:11 
.. 0xfffffa8001325950:sppsvc.exe                      816    428      5    154 2012-02-22 19:58:41 
.. 0xfffffa8000e86690:spoolsv.exe                    1076    428     12    271 2012-02-22 20:02:10 
.. 0xfffffa8001296b30:svchost.exe                     568    428     10    352 2012-02-22 19:58:34 
... 0xfffffa8000a03b30:rundll32.exe                  2016    568      3     67 2012-02-22 20:03:16


To enumerate processes using pool tag scanning (_POOL_HEADER), use the psscan command. This can find processes that previously terminated (inactive) and processes that have been hidden or unlinked by a rootkit. The downside is that rootkits can still hide by overwriting the pool tag values (though not commonly seen in the wild).

$ vol.py --profile=Win7SP0x86 -f win7.dmp psscan
Volatility Foundation Volatility Framework 2.0
 Offset     Name             PID    PPID   PDB        Time created             Time exited             
---------- ---------------- ------ ------ ---------- ------------------------ ------------------------ 
0x3e025ba8 svchost.exe        1116    508 0x3ecf1220 2010-06-16 15:25:25                              
0x3e04f070 svchost.exe        1152    508 0x3ecf1340 2010-06-16 15:27:40                              
0x3e144c08 dwm.exe            1540    832 0x3ecf12e0 2010-06-16 15:26:58                              
0x3e145c18 TPAutoConnSvc.     1900    508 0x3ecf1360 2010-06-16 15:25:41                              
0x3e3393f8 lsass.exe           516    392 0x3ecf10e0 2010-06-16 15:25:18                              
0x3e35b8f8 svchost.exe         628    508 0x3ecf1120 2010-06-16 15:25:19                              
0x3e383770 svchost.exe         832    508 0x3ecf11a0 2010-06-16 15:25:20                              
0x3e3949d0 svchost.exe         740    508 0x3ecf1160 2010-06-16 15:25:20                              
0x3e3a5100 svchost.exe         872    508 0x3ecf11c0 2010-06-16 15:25:20                              
0x3e3f64e8 svchost.exe         992    508 0x3ecf1200 2010-06-16 15:25:24                              
0x3e45a530 wininit.exe         392    316 0x3ecf10a0 2010-06-16 15:25:15                              
0x3e45d928 svchost.exe        1304    508 0x3ecf1260 2010-06-16 15:25:28                              
0x3e45f530 csrss.exe           400    384 0x3ecf1040 2010-06-16 15:25:15                              
0x3e4d89c8 vmtoolsd.exe       1436    508 0x3ecf1280 2010-06-16 15:25:30                              
0x3e4db030 spoolsv.exe        1268    508 0x3ecf1240 2010-06-16 15:25:28                              
0x3e50b318 services.exe        508    392 0x3ecf1080 2010-06-16 15:25:18                              
0x3e7f3d40 csrss.exe           352    316 0x3ecf1060 2010-06-16 15:25:12                              
0x3e7f5bc0 winlogon.exe        464    384 0x3ecf10c0 2010-06-16 15:25:18                              
0x3eac6030 SearchProtocol     2448   1168 0x3ecf15c0 2010-06-16 23:30:52      2010-06-16 23:33:14     
0x3eb10030 SearchFilterHo     1812   1168 0x3ecf1480 2010-06-16 23:31:02      2010-06-16 23:33:14 

If a process has previously terminated, the Time exited field will show the exit time. If you want to investigate a hidden process (such as displaying its DLLs), then you’ll need physical offset of the _EPROCESSobject, which is shown in the far left column. Almost all process-related plugins take a --OFFSET parameter so that you can work with hidden processes.


This plugin is similar to psscan, except it enumerates processes by scanning for DISPATCHER_HEADER instead of pool tags. This gives you an alternate way to carve _EPROCESS objects in the event an attacker tried to hide by altering pool tags. This plugin is not well maintained and only supports XP x86. To use it, you must type --plugins=contrib/plugins on command-line.


To display a process’s loaded DLLs, use the dlllist command. It walks the doubly-linked list of _LDR_DATA_TABLE_ENTRY structures which is pointed to by the PEB’s InLoadOrderModuleList. DLLs are automatically added to this list when a process calls LoadLibrary (or some derivative such as LdrLoadDll) and they aren’t removed until FreeLibrary is called and the reference count reaches zero. The load count column tells you if a DLL was statically loaded (i.e. as a result of being in the exe or another DLL’s import table) or dynamically loaded.

$ vol.py -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 dlllist 
wininit.exe pid:    332
Command line : wininit.exe
Base                             Size          LoadCount Path
------------------ ------------------ ------------------ ----
0x00000000ff530000            0x23000             0xffff C:\Windows\system32\wininit.exe
0x0000000076d40000           0x1ab000             0xffff C:\Windows\SYSTEM32\ntdll.dll
0x0000000076b20000           0x11f000             0xffff C:\Windows\system32\kernel32.dll
0x000007fefcd50000            0x6b000             0xffff C:\Windows\system32\KERNELBASE.dll
0x0000000076c40000            0xfa000             0xffff C:\Windows\system32\USER32.dll
0x000007fefd7c0000            0x67000             0xffff C:\Windows\system32\GDI32.dll
0x000007fefe190000             0xe000             0xffff C:\Windows\system32\LPK.dll
0x000007fefef80000            0xca000             0xffff C:\Windows\system32\USP10.dll
0x000007fefd860000            0x9f000             0xffff C:\Windows\system32\msvcrt.dll

To display the DLLs for a specific process instead of all processes, use the -p or --pid filter as shown below. Also, in the following output, notice we’re analyzing a Wow64 process. Wow64 processes have a limited list of DLLs in the PEB lists, but that doesn’t mean they’re the only DLLs loaded in the process address space. Thus Volatility will remind you to use the ldrmodules instead for these processes.

$ vol.py -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 dlllist -p 1892
Volatility Foundation Volatility Framework 2.4
iexplore.exe pid:   1892
Command line : "C:\Program Files (x86)\Internet Explorer\iexplore.exe" 
Note: use ldrmodules for listing DLLs in Wow64 processes
Base                             Size          LoadCount Path
------------------ ------------------ ------------------ ----
0x0000000000080000            0xa6000             0xffff C:\Program Files (x86)\Internet Explorer\iexplore.exe
0x0000000076d40000           0x1ab000             0xffff C:\Windows\SYSTEM32\ntdll.dll
0x00000000748d0000            0x3f000                0x3 C:\Windows\SYSTEM32\wow64.dll
0x0000000074870000            0x5c000                0x1 C:\Windows\SYSTEM32\wow64win.dll
0x0000000074940000             0x8000                0x1 C:\Windows\SYSTEM32\wow64cpu.dll

To display the DLLs for a process that is hidden or unlinked by a rootkit, first use the psscan to get the physical offset of the EPROCESS object and supply it with — offset=OFFSET. The plugin will “bounce back” and determine the virtual address of the EPROCESS and then acquire an address space in order to access the PEB.

$ vol.py -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 dlllist --offset=0x04a291a8


To extract a DLL from a process’s memory space and dump it to disk for analysis, use the dlldump command. The syntax is nearly the same as what we’ve shown for dlllist above. You can:

  • Dump all DLLs from all processes
  • Dump all DLLs from a specific process (with --pid=PID)
  • Dump all DLLs from a hidden/unlinked process (with --offset=OFFSET)
  • Dump a PE from anywhere in process memory (with --base=BASEADDR), this option is useful for extracting hidden DLLs
  • Dump one or more DLLs that match a regular expression (--regex=REGEX), case sensitive or not (--ignore-case)

To specify an output directory, use --dump-dir=DIR or -d DIR.

$ vol.py -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 dlldump -D dlls/
Process(V)         Name                 Module Base        Module Name          Result
------------------ -------------------- ------------------ -------------------- ------
0xfffffa8000ce97f0 smss.exe             0x0000000047a90000 smss.exe             OK: module.208.176e97f0.47a90000.dll
0xfffffa8000ce97f0 smss.exe             0x0000000076d40000                      Error: DllBase is paged
0xfffffa8000c006c0 csrss.exe            0x0000000049700000 csrss.exe            OK: module.296.176006c0.49700000.dll
0xfffffa8000c006c0 csrss.exe            0x0000000076d40000 ntdll.dll            Error: DllBase is paged
0xfffffa8000c006c0 csrss.exe            0x000007fefd860000 msvcrt.dll           Error: DllBase is paged
0xfffffa80011c5700 lsass.exe            0x000007fefcc40000 WINSTA.dll           Error: DllBase is paged
0xfffffa80011c5700 lsass.exe            0x000007fefd7c0000 GDI32.dll            OK: module.444.173c5700.7fefd7c0000.dll
0xfffffa80011c5700 lsass.exe            0x000007fefc270000 DNSAPI.dll           OK: module.444.173c5700.7fefc270000.dll
0xfffffa80011c5700 lsass.exe            0x000007fefc5d0000 Secur32.dll          OK: module.444.173c5700.7fefc5d0000.dll

If the extraction fails, as it did for a few DLLs above, it probably means that some of the memory pages in that DLL were not memory resident (due to paging). In particular, this is a problem if the first page containing the PE header and thus the PE section mappings is not available. In these cases you can still extract the memory segment using the vaddump command, but you’ll need to manually rebuild the PE header and fixup the sections (if you plan on analyzing in IDA Pro) as described in Recovering CoreFlood Binaries with Volatility.

To dump a PE file that doesn’t exist in the DLLs list (for example, due to code injection or malicious unlinking), just specify the base address of the PE in process memory:

$ vol.py --profile=Win7SP0x86 -f win7.dmp dlldump --pid=492 -D out --base=0x00680000

You can also specify an EPROCESS offset if the DLL you want is in a hidden process:

$ vol.py --profile=Win7SP0x86 -f win7.dmp dlldump -o 0x3e3f64e8 -D out --base=0x00680000


To display the open handles in a process, use the handles command. This applies to files, registry keys, mutexes, named pipes, events, window stations, desktops, threads, and all other types of securable executive objects. As of 2.1, the output includes handle value and granted access for each object.

$ vol.py -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 handles
Volatility Foundation Volatility Framework 2.4
Offset(V)             Pid             Handle             Access Type             Details
------------------ ------ ------------------ ------------------ ---------------- -------
0xfffffa80004b09e0      4                0x4           0x1fffff Process          System(4)
0xfffff8a0000821a0      4               0x10            0x2001f Key              MACHINE\SYSTEM\CONTROLSET001\CONTROL\PRODUCTOPTIONS
0xfffff8a00007e040      4               0x14            0xf003f Key              MACHINE\SYSTEM\CONTROLSET001\CONTROL\SESSION MANAGER\MEMORY MANAGEMENT\PREFETCHPARAMETERS
0xfffff8a000081fa0      4               0x18            0x2001f Key              MACHINE\SYSTEM\SETUP
0xfffffa8000546990      4               0x1c           0x1f0001 ALPC Port        PowerMonitorPort
0xfffffa800054d070      4               0x20           0x1f0001 ALPC Port        PowerPort
0xfffff8a0000676a0      4               0x24            0x20019 Key              MACHINE\HARDWARE\DESCRIPTION\SYSTEM\MULTIFUNCTIONADAPTER
0xfffffa8000625460      4               0x28           0x1fffff Thread           TID 160 PID 4
0xfffff8a00007f400      4               0x2c            0xf003f Key              MACHINE\SYSTEM\CONTROLSET001
0xfffff8a00007f200      4               0x30            0xf003f Key              MACHINE\SYSTEM\CONTROLSET001\ENUM
0xfffff8a000080d10      4               0x34            0xf003f Key              MACHINE\SYSTEM\CONTROLSET001\CONTROL\CLASS
0xfffff8a00007f500      4               0x38            0xf003f Key              MACHINE\SYSTEM\CONTROLSET001\SERVICES
0xfffff8a0001cd990      4               0x3c                0xe Token            
0xfffff8a00007bfa0      4               0x40            0x20019 Key              MACHINE\SYSTEM\CONTROLSET001\CONTROL\WMI\SECURITY
0xfffffa8000cd52b0      4               0x44           0x120116 File             \Device\Mup
0xfffffa8000ce97f0      4               0x48               0x2a Process          smss.exe(208)
0xfffffa8000df16f0      4               0x4c           0x120089 File             \Device\HarddiskVolume2\Windows\System32\en-US\win32k.sys.mui
0xfffffa8000de37f0      4               0x50           0x12019f File             \Device\clfsTxfLog
0xfffff8a000952fa0      4               0x54            0x2001f Key              MACHINE\SYSTEM\CONTROLSET001\CONTROL\VIDEO\{6A8FC9DC-A76B-47FC-A703-17800182E1CE}\0000\VOLATILESETTINGS
0xfffffa800078da20      4               0x58           0x12019f File             \Device\Tcp
0xfffff8a002e17610      4               0x5c                0x9 Key              MACHINE\SOFTWARE\MICROSOFT\WINDOWS NT\CURRENTVERSION\IMAGE FILE EXECUTION OPTIONS
0xfffff8a0008f7b00      4               0x60               0x10 Key              MACHINE\SYSTEM\CONTROLSET001\CONTROL\LSA
0xfffffa8000da2870      4               0x64           0x100001 File             \Device\KsecDD
0xfffffa8000da3040      4               0x68                0x0 Thread           TID 228 PID 4

You can display handles for a particular process by specifying --pid=PIDor the physical offset of an _EPROCESS structure (--physical-offset=OFFSET). You can also filter by object type using -t or --object-type=OBJECTTYPE. For example to only display handles to process objects for pid 600, do the following:

$ vol.py -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 handles -p 296 -t Process
Volatility Foundation Volatility Framework 2.4
Offset(V)             Pid             Handle             Access Type             Details
------------------ ------ ------------------ ------------------ ---------------- -------
0xfffffa8000c92300    296               0x54           0x1fffff Process          wininit.exe(332)
0xfffffa8000c5eb30    296               0xc4           0x1fffff Process          services.exe(428)
0xfffffa80011c5700    296               0xd4           0x1fffff Process          lsass.exe(444)
0xfffffa8000ea31b0    296               0xe4           0x1fffff Process          lsm.exe(452)
0xfffffa8000c64840    296              0x140           0x1fffff Process          svchost.exe(348)
0xfffffa8001296b30    296              0x150           0x1fffff Process          svchost.exe(568)
0xfffffa80012c3620    296              0x18c           0x1fffff Process          svchost.exe(628)
0xfffffa8001325950    296              0x1dc           0x1fffff Process          sppsvc.exe(816)

The object type can be any of the names printed by the “object \ObjectTypes” windbg command.

For more details, see

In some cases, the Details column will be blank (for example, if the objects don’t have names).

By default, you’ll see both named and un-named objects. However, if you want to hide the less meaningful results and only show named objects, use the --silent parameter to this plugin.


To view the SIDs (Security Identifiers) associated with a process, use the getsids command. Among other things, this can help you identify processes which have maliciously escalated privileges and which processes belong to specific users.

For more information, see

$ vol.py -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 getsids
Volatility Foundation Volatility Framework 2.4
System (4): S-1-5-18 (Local System)
System (4): S-1-5-32-544 (Administrators)
System (4): S-1-1-0 (Everyone)
System (4): S-1-5-11 (Authenticated Users)
System (4): S-1-16-16384 (System Mandatory Level)
smss.exe (208): S-1-5-18 (Local System)
smss.exe (208): S-1-5-32-544 (Administrators)
smss.exe (208): S-1-1-0 (Everyone)
smss.exe (208): S-1-5-11 (Authenticated Users)
smss.exe (208): S-1-16-16384 (System Mandatory Level)


The cmdscan plugin searches the memory of csrss.exe on XP/2003/Vista/2008 and conhost.exe on Windows 7 for commands that attackers entered through a console shell (cmd.exe). This is one of the most powerful commands you can use to gain visibility into an attackers actions on a victim system, whether they opened cmd.exe through an RDP session or proxied input/output to a command shell from a networked backdoor.

This plugin finds structures known as COMMAND_HISTORY by looking for a known constant value (MaxHistory) and then applying sanity checks. It is important to note that the MaxHistory value can be changed by right clicking in the top left of a cmd.exe window and going to Properties. The value can also be changed for all consoles opened by a given user by modifying the registry key HKCU\Console\HistoryBufferSize. The default is 50 on Windows systems, meaning the most recent 50 commands are saved. You can tweak it if needed by using the — max_history=NUMBER parameter.

The structures used by this plugin are not public (i.e. Microsoft does not produce PDBs for them), thus they’re not available in WinDBG or any other forensic framework. They were reverse engineered by Michael Ligh from the conhost.exe and winsrv.dll binaries.

In addition to the commands entered into a shell, this plugin shows:

  • The name of the console host process (csrss.exe or conhost.exe)
  • The name of the application using the console (whatever process is using cmd.exe)
  • The location of the command history buffers, including the current buffer count, last added command, and last displayed command
  • The application process handle

Due to the scanning technique this plugin uses, it has the capability to find commands from both active and closed consoles.

$ vol.py -f VistaSP2x64.vmem --profile=VistaSP2x64 cmdscan
Volatility Foundation Volatility Framework 2.4
CommandProcess: csrss.exe Pid: 528
CommandHistory: 0x135ec00 Application: cmd.exe Flags: Allocated, Reset
CommandCount: 18 LastAdded: 17 LastDisplayed: 17
FirstCommand: 0 CommandCountMax: 50
ProcessHandle: 0x330
Cmd #0 @ 0x135ef10: cd \
Cmd #1 @ 0x135ef50: cd de
Cmd #2 @ 0x135ef70: cd PerfLogs
Cmd #3 @ 0x135ef90: cd ..
Cmd #4 @ 0x5c78b90: cd "Program Files"
Cmd #5 @ 0x135fae0: cd "Debugging Tools for Windows (x64)"
Cmd #6 @ 0x135efb0: livekd -w
Cmd #7 @ 0x135f010: windbg 
Cmd #8 @ 0x135efd0: cd \
Cmd #9 @ 0x135fd20: rundll32 c:\apphelp.dll,ExportFunc
Cmd #10 @ 0x5c8bdb0: rundll32 c:\windows_apphelp.dll,ExportFunc
Cmd #11 @ 0x5c8be10: rundll32 c:\windows_apphelp.dll
Cmd #12 @ 0x135ee30: rundll32 c:\windows_apphelp.dll,Test
Cmd #13 @ 0x135fd70: cd "Program Files"
Cmd #14 @ 0x5c8b9e0: dir
Cmd #15 @ 0x5c8be60: cd "Debugging Tools for Windows (x64)"
Cmd #16 @ 0x5c8ba00: dir
Cmd #17 @ 0x135eff0: livekd -w

More information:


Similar to cmdscan the consoles plugin finds commands that attackers typed into cmd.exe or executed via backdoors. However, instead of scanning for COMMAND_HISTORY, this plugin scans for CONSOLE_INFORMATION. The major advantage to this plugin is it not only prints the commands attackers typed, but it collects the entire screen buffer (input and output). For instance, instead of just seeing “dir”, you’ll see exactly what the attacker saw, including all files and directories listed by the “dir” command.

Additionally, this plugin prints the following:

  • The original console window title and current console window title
  • The name and pid of attached processes (walks a LIST_ENTRY to enumerate all of them if more than one)
  • Any aliases associated with the commands executed. For example, attackers can register an alias such that typing “hello” actually executes “cd system”
  • The screen coordinates of the cmd.exe console

Here’s an example of the consoles command. Below, you’ll notice something quite funny. The forensic investigator seems to have lost his mind and cannot find the dd.exe tool for dumping memory. Nearly 20 typos later, he finds the tool and uses it.

$ vol.py -f xp-laptop-2005-07-04-1430.img consoles
Volatility Foundation Volatility Framework 2.4
[csrss.exe @ 0x821c11a8 pid 456 console @ 0x4e23b0]
  OriginalTitle: '%SystemRoot%\\system32\\cmd.exe'
  Title: 'C:\\WINDOWS\\system32\\cmd.exe - dd if=\\\\.\\PhysicalMemory of=c:\\xp-2005-07-04-1430.img conv=noerror'
  HistoryBufferCount: 2
  HistoryBufferMax: 4
  CommandHistorySize: 50
[history @ 0x4e4008]
  CommandCount: 0
  CommandCountMax: 50
  Application: 'dd.exe'
[history @ 0x4e4d88]
  CommandCount: 20
  CommandCountMax: 50
  Application: 'cmd.exe'
  Cmd #0 @ 0x4e1f90: 'dd'
  Cmd #1 @ 0x4e2cb8: 'cd\\'
  Cmd #2 @ 0x4e2d18: 'dr'
  Cmd #3 @ 0x4e2d28: 'ee:'
  Cmd #4 @ 0x4e2d38: 'e;'
  Cmd #5 @ 0x4e2d48: 'e:'
  Cmd #6 @ 0x4e2d58: 'dr'
  Cmd #7 @ 0x4e2d68: 'd;'
  Cmd #8 @ 0x4e2d78: 'd:'
  Cmd #9 @ 0x4e2d88: 'dr'
  Cmd #10 @ 0x4e2d98: 'ls'
  Cmd #11 @ 0x4e2da8: 'cd Docu'
  Cmd #12 @ 0x4e2dc0: 'cd Documents and'
  Cmd #13 @ 0x4e2e58: 'dr'
  Cmd #14 @ 0x4e2e68: 'd:'
  Cmd #15 @ 0x4e2e78: 'cd dd\\'
  Cmd #16 @ 0x4e2e90: 'cd UnicodeRelease'
  Cmd #17 @ 0x4e2ec0: 'dr'
  Cmd #18 @ 0x4e2ed0: 'dd '
  Cmd #19 @ 0x4e4100: 'dd if=\\\\.\\PhysicalMemory of=c:\\xp-2005-07-04-1430.img conv=noerror'
[screen @ 0x4e2460 X:80 Y:300]
  Output: Microsoft Windows XP [Version 5.1.2600]                                         
  Output: (C) Copyright 1985-2001 Microsoft Corp.                                         
  Output: C:\Documents and Settings\Sarah>dd                                              
  Output: 'dd' is not recognized as an internal or external command,                      
  Output: operable program or batch file.                                                 
  Output: C:\Documents and Settings\Sarah>cd\                                             
  Output: C:\>dr                                                                          
  Output: 'dr' is not recognized as an internal or external command,                      
  Output: operable program or batch file.                                                 
  Output: C:\>ee:                                                                         
  Output: 'ee:' is not recognized as an internal or external command,                     
  Output: operable program or batch file.                                                 
  Output: C:\>e;                                                                          
  Output: 'e' is not recognized as an internal or external command,                       
  Output: operable program or batch file.                                                 
  Output: C:\>e:                                                                          
  Output: The system cannot find the drive specified.                                     
  Output: C:\>dr                                                                          
  Output: 'dr' is not recognized as an internal or external command,                      
  Output: operable program or batch file.                                                 
  Output: C:\>d;                                                                          
  Output: 'd' is not recognized as an internal or external command,                       
  Output: operable program or batch file.                                                 
  Output: C:\>d:                                                                          
  Output: D:\>dr                                                                          
  Output: 'dr' is not recognized as an internal or external command,                      
  Output: operable program or batch file.                                                 
  Output: D:\>dr                                                                          
  Output: 'dr' is not recognized as an internal or external command,                      
  Output: operable program or batch file.                                                 
  Output: D:\>ls                                                                          
  Output: 'ls' is not recognized as an internal or external command,                      
  Output: operable program or batch file.                                                 
  Output: D:\>cd Docu                                                                     
  Output: The system cannot find the path specified.                                      
  Output: D:\>cd Documents and                                                            
  Output: The system cannot find the path specified.                                      
  Output: D:\>dr                                                                          
  Output: 'dr' is not recognized as an internal or external command,                      
  Output: operable program or batch file.                                                 
  Output: D:\>d:                                                                          
  Output: D:\>cd dd\                                                                      
  Output: D:\dd>                                                                          
  Output: D:\dd>cd UnicodeRelease                                                         
  Output: D:\dd\UnicodeRelease>dr                                                         
  Output: 'dr' is not recognized as an internal or external command,                      
  Output: operable program or batch file.                                                 
  Output: D:\dd\UnicodeRelease>dd                                                         
  Output: 0+0 records in                                                                  
  Output: 0+0 records out                                                                 
  Output: ^C                                                                              
  Output: D:\dd\UnicodeRelease>dd if=\\.\PhysicalMemory of=c:\xp-2005-07-04-1430.img conv=
  Output: noerror                                                                         
  Output: Forensic Acquisition Utilities, 1, 0, 0, 1035                                   
  Output: dd, 3, 16, 2, 1035                                                              
  Output: Copyright (C) 2002-2004 George M. Garner Jr.                                    
  Output: Command Line: dd if=\\.\PhysicalMemory of=c:\xp-2005-07-04-1430.img conv=noerror
  Output: Based on original version developed by Paul Rubin, David MacKenzie, and Stuart K
  Output: emp                                                                             
  Output: Microsoft Windows: Version 5.1 (Build 2600.Professional Service Pack 2)         
  Output: 04/07/2005  18:30:32 (UTC)                                                      
  Output: 04/07/2005  14:30:32 (local time)                                               
  Output: Current User: SPLATITUDE\Sarah                                                  
  Output: Total physical memory reported: 523676 KB                                       
  Output: Copying physical memory...                                                      
  Output: Physical memory in the range 0x00004000-0x00004000 could not be read.


This plugin shows you which process privileges are present, enabled, and/or enabled by default. You can pass it the — silent flag to only show privileges that a process explicitly enabled (i.e. that were were not enabled by default but are currently enabled). The — regex=REGEX parameter can be used to filter for specific privilege names.

$ vol.py -f win7_trial_64bit.raw privs --profile=Win7SP0x64
Volatility Foundation Volatility Framework 2.3_alpha
Pid      Process          Value  Privilege                            Attributes               Description
-------- ---------------- ------ ------------------------------------ ------------------------ -----------
       4 System                2 SeCreateTokenPrivilege               Present                  Create a token object
       4 System                3 SeAssignPrimaryTokenPrivilege        Present                  Replace a process-level token
       4 System                4 SeLockMemoryPrivilege                Present,Enabled,Default  Lock pages in memory
       4 System                5 SeIncreaseQuotaPrivilege             Present                  Increase quotas
       4 System                6 SeMachineAccountPrivilege                                     Add workstations to the domain
       4 System                7 SeTcbPrivilege                       Present,Enabled,Default  Act as part of the operating system
       4 System                8 SeSecurityPrivilege                  Present                  Manage auditing and security log
       4 System                9 SeTakeOwnershipPrivilege             Present                  Take ownership of files/objects
       4 System               10 SeLoadDriverPrivilege                Present                  Load and unload device drivers
       4 System               11 SeSystemProfilePrivilege             Present,Enabled,Default  Profile system performance
       4 System               12 SeSystemtimePrivilege                Present                  Change the system time
       4 System               13 SeProfileSingleProcessPrivilege      Present,Enabled,Default  Profile a single process
       4 System               14 SeIncreaseBasePriorityPrivilege      Present,Enabled,Default  Increase scheduling priority
       4 System               15 SeCreatePagefilePrivilege            Present,Enabled,Default  Create a pagefile
       4 System               16 SeCreatePermanentPrivilege           Present,Enabled,Default  Create permanent shared objects


To display a process’s environment variables, use the envars plugin. Typically this will show the number of CPUs installed and the hardware architecture (though the kdbgscan output is a much more reliable source), the process’s current directory, temporary directory, session name, computer name, user name, and various other interesting artifacts.

$ vol.py -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 envars
Volatility Foundation Volatility Framework 2.4
Pid      Process              Block              Variable                       Value
-------- -------------------- ------------------ ------------------------------ -----
     296 csrss.exe            0x00000000003d1320 ComSpec                        C:\Windows\system32\cmd.exe
     296 csrss.exe            0x00000000003d1320 FP_NO_HOST_CHECK               NO
     296 csrss.exe            0x00000000003d1320 NUMBER_OF_PROCESSORS           1
     296 csrss.exe            0x00000000003d1320 OS                             Windows_NT
     296 csrss.exe            0x00000000003d1320 Path                           C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\
     296 csrss.exe            0x00000000003d1320 PATHEXT                        .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
     296 csrss.exe            0x00000000003d1320 PROCESSOR_ARCHITECTURE         AMD64
     296 csrss.exe            0x00000000003d1320 PROCESSOR_IDENTIFIER           Intel64 Family 6 Model 2 Stepping 3, GenuineIntel
     296 csrss.exe            0x00000000003d1320 PROCESSOR_LEVEL                6
     296 csrss.exe            0x00000000003d1320 PROCESSOR_REVISION             0203
     296 csrss.exe            0x00000000003d1320 PSModulePath                   C:\Windows\system32\WindowsPowerShell\v1.0\Modules\
     296 csrss.exe            0x00000000003d1320 SystemDrive                    C:
     296 csrss.exe            0x00000000003d1320 SystemRoot                     C:\Windows
     296 csrss.exe            0x00000000003d1320 TEMP                           C:\Windows\TEMP
     296 csrss.exe            0x00000000003d1320 TMP                            C:\Windows\TEMP
     296 csrss.exe            0x00000000003d1320 USERNAME                       SYSTEM
     296 csrss.exe            0x00000000003d1320 windir                         C:\Windows


To display the version information embedded in PE files, use the verinfo command. Not all PE files have version information, and many malware authors forge it to include false data, but nonetheless this command can be very helpful with identifying binaries and for making correlations with other files.

This plugin only supports printing version information from process executables and DLLs, but later will be expanded to include kernel modules. If you want to filter by module name, use the — regex=REGEX and/or — ignore-case options.

$ vol.py -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 verinfo
Volatility Foundation Volatility Framework 2.4
  File version    : 6.1.7600.16385
  Product version : 6.1.7600.16385
  Flags           : 
  OS              : Windows NT
  File Type       : Application
  File Date       : 
  CompanyName : Microsoft Corporation
  FileDescription : Client Server Runtime Process
  FileVersion : 6.1.7600.16385 (win7_rtm.090713-1255)
  InternalName : CSRSS.Exe
  LegalCopyright : \xa9 Microsoft Corporation. All rights reserved.
  OriginalFilename : CSRSS.Exe
  ProductName : Microsoft\xae Windows\xae Operating System
  ProductVersion : 6.1.7600.16385


This plugin enumerates imported and exported functions from processes, dlls, and kernel drivers. Specifically, it handles functions imported by name or ordinal, functions exported by name or ordinal, and forwarded exports. The output will be very verbose in most cases (functions exported by ntdll, msvcrt, and kernel32 can reach 1000+ alone). So you can either reduce the verbosity by filtering criteria with the command-line options (shown below) or you can use look at the code in enumfunc.py and use it as an example of how to use the IAT and EAT parsing API functions in your own plugin. For example, the apihooks plugin leverages the imports and exports APIs to find functions in memory when checking for hooks.

Also note this plugin is in the contrib directory, so you can pass that to — plugins like this:

$ vol.py --plugins=contrib/plugins/ -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 enumfunc -h
  -s, --scan            Scan for objects
  -P, --process-only    Process only
  -K, --kernel-only     Kernel only
  -I, --import-only     Imports only
  -E, --export-only     Exports only

To use pool scanners for finding processes and kernel drivers instead of walking linked lists, use the -s option. This can be useful if you’re trying to enumerate functions in hidden processes or drivers. An example of the remaining command-line options is shown below.

To show exported functions in process memory, use -P and -E like this:

$ vol.py --plugins=contrib/plugins/ -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 enumfunc -P -E
Process              Type       Module               Ordinal    Address              Name
lsass.exe            Export     ADVAPI32.dll         1133       0x000007fefd11dd34 CreateWellKnownSid
lsass.exe            Export     ADVAPI32.dll         1134       0x000007fefd17a460 CredBackupCredentials
lsass.exe            Export     ADVAPI32.dll         1135       0x000007fefd170590 CredDeleteA
lsass.exe            Export     ADVAPI32.dll         1136       0x000007fefd1704d0 CredDeleteW
lsass.exe            Export     ADVAPI32.dll         1137       0x000007fefd17a310 CredEncryptAndMarshalBinaryBlob
lsass.exe            Export     ADVAPI32.dll         1138       0x000007fefd17d080 CredEnumerateA
lsass.exe            Export     ADVAPI32.dll         1139       0x000007fefd17cf50 CredEnumerateW
lsass.exe            Export     ADVAPI32.dll         1140       0x000007fefd17ca00 CredFindBestCredentialA
lsass.exe            Export     ADVAPI32.dll         1141       0x000007fefd17c8f0 CredFindBestCredentialW
lsass.exe            Export     ADVAPI32.dll         1142       0x000007fefd130c10 CredFree
lsass.exe            Export     ADVAPI32.dll         1143       0x000007fefd1630f0 CredGetSessionTypes
lsass.exe            Export     ADVAPI32.dll         1144       0x000007fefd1703d0 CredGetTargetInfoA

To show imported functions in kernel memory, use -K and -I like this:

$ vol.py --plugins=contrib/plugins/ -f ~/Desktop/win7_trial_64bit.raw --profile=Win7SP0x64 enumfunc -K -I
Volatility Foundation Volatility Framework 2.4
Process              Type       Module               Ordinal    Address              Name
<KERNEL>             Import     VIDEOPRT.SYS         583        0xfffff80002acc320 ntoskrnl.exeIoRegisterPlugPlayNotification
<KERNEL>             Import     VIDEOPRT.SYS         1325       0xfffff800029f9f30 ntoskrnl.exeRtlAppendStringToString
<KERNEL>             Import     VIDEOPRT.SYS         509        0xfffff800026d06e0 ntoskrnl.exeIoGetAttachedDevice
<KERNEL>             Import     VIDEOPRT.SYS         443        0xfffff800028f7ec0 ntoskrnl.exeIoBuildSynchronousFsdRequest
<KERNEL>             Import     VIDEOPRT.SYS         1466       0xfffff80002699300 ntoskrnl.exeRtlInitUnicodeString
<KERNEL>             Import     VIDEOPRT.SYS         759        0xfffff80002697be0 ntoskrnl.exeKeInitializeEvent
<KERNEL>             Import     VIDEOPRT.SYS         1461       0xfffff8000265e8a0 ntoskrnl.exeRtlInitAnsiString
<KERNEL>             Import     VIDEOPRT.SYS         1966       0xfffff80002685060 ntoskrnl.exeZwSetValueKey
<KERNEL>             Import     VIDEOPRT.SYS         840        0xfffff80002699440 ntoskrnl.exeKeReleaseSpinLock
<KERNEL>             Import     VIDEOPRT.SYS         1190       0xfffff800027a98b0 ntoskrnl.exePoRequestPowerIrp
<KERNEL>             Import     VIDEOPRT.SYS         158        0xfffff800026840f0 ntoskrnl.exeExInterlockedInsertTailList
<KERNEL>             Import     VIDEOPRT.SYS         1810       0xfffff80002684640 ntoskrnl.exeZwClose

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.


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.


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:


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.

Understanding EXT4

A really interesting series of articles on SANS Digital Forensics Blog

On 2010, Hal Pomeranz has started on SANS Digital Forensics blog a series of technical articles about EXT4 filesystem.

What is EXT4?

EXT4 is a journaling file system for Linux, developed as the successor to ext3: it modifies important data structures of the previous filesystem such as the ones destined to store the file data. The result is a filesystem with an improved design, better performance, reliability and features.
It was accepted as “stable” in the Linux 2.6.28 kernel in October 2008.

The ‘episodes’

The publication of the ‘episodes’ continued since years, and recently Hal has published the part 6, focused on “Directories”.

Here the list of all parts:

1. Extents

20 Dec 2010

EXT4 has moved to 48-bit block addresses. I’ll refer you to the paper cited above for the whys and wherefores of this decision and what it means as far as maximum file system size, etc. What’s really a departure for EXT4 however, is the use of extents rather than the old, inefficient indirect block[3] mechanism used by earlier Unix file systems (e.g. EXT2/EXT3) for tracking file content. Extents are similar to cluster runs in the NTFS file system- essentially they specify an initial block address and the number of blocks that make up the extent. A file that is fragmented will have multiple extents, but EXT4 tries very hard to keep files contiguous.


2. Timestamps

14 Mar 2011

The EXT4 developers tried very hard to maintain backwards compatibility with the EXT2/EXT3 inode layout. 64-bit timestamps and a completely new file creation timestamp obviously complicate this goal. The EXT4 developers solved this problem by putting the extra stuff in the upper 128 bits of the new, larger 256-bit EXT4 inode.


3. Extent Trees

28 Mar 2011

[…] you can only have a maximum of 4 extent structures per inode. Furthermore, there are only 16 bits in each extent structure for representing the number of blocks in the extent, and in fact the upper bit is reserved (it’s used to mark the extent as “reserved but initialized”, part of EXT4’s pre-allocation feature). That means each extent can only contain a maximum of 2¹⁵ blocks- which is 128MB assuming 4K blocks.

Now 128MB is pretty big, but what happens when you have a file that’s bigger than half a gigabyte? Such a file would require more than 4 extents to fully index. Or what happens when you have a file that’s small but very fragmented? Again, you could need more than 4 extents to represent the collections of blocks that make up the file.


4. Demolition Derby

08 Apr 2011

I got curious about what would happen when I deleted my /var/log/messages file. How does the inode change? What happens to block 131090, which holds my extent tree structure? Well, there’s really only one way to find out: I deleted the file… carefully so I didn’t lose any logging data. In fact, I didn’t just delete the file; I used “shred -u /var/log/messages” to overwrite the data blocks with nulls before unlinking the file. Once the file had been purged, I dumped out the both inode associated with the file as well as block 131090 and took a look at them in my hex editor.


5. Large Extents

22 Aug 2011

[…] you can only have 32K blocks in an extent. Assuming a typical 4K block size, that means you can only have 128MB of data in a single extent. A 4GB file is therefore going to require at least 32 extents, and even that assumes you can find 32 runs of 32K contiguous blocks to use. More likely we’ll have more than 32 extents, some of which don’t use the full 128MB length.


6. Directories

07 Jun 2017

One item I never got around to was documenting how directories were structured in EXT. Some recent research has caused me to dive back into this topic, and given me an excuse to add additional detail to this EXT4 series.

If you go back and read earlier posts in this series, you will note that the EXT inode does not store file names. Directories are the only place in traditional Unix file systems where file name information is kept. In EXT, and the classic Unix file systems it is evolved from, directories are simply special files that associate file names with inode numbers.

Furthermore, in the simplest case, EXT directories are just sequential lists of file entries. The entries aren’t even sorted. For the most part, directory entries in EXT are simply added to the directory file in the order files are created in the directory.


I wish you a good reading!