4.1.2 Understanding ActiveProcessLinks

Windows uses a circular double linked list of _EPROCESS structures to keep track of all the active processes. The _EPROCESS structure contains a field called ActiveProcessLinks which is of type LIST_ENTRY. The _LIST_ENTRY is another structure that contains two members, as shown in the following command output. The Flink (forward link) points to the _LIST_ENTRY of the next _EPROCESS structure, and the Blink (backward link) points to the _LIST_ENTRY of the previous _EPROCESS structure:

kd> dt nt!_LIST_ENTRY
+0x000 Flink : Ptr64 _LIST_ENTRY
+0x008 Blink : Ptr64 _LIST_ENTRY

Flink and Blink together create a chain of process objects; this can be visualized as follows:

A point to note is that Flink and Blink do not point to the start of the _EPROCESS structure. Flink points to the start (first byte) of the _LIST_ENTRY structure of the next _EPROCESS structure, and Blink points to the first byte of the _LIST_ENTRY structure of the previous _EPROCESS structure. The reason why this is important is that, once you find the _EPROCESS structure of a process, you can walk the doubly linked list forward (using Flink) or backward (Blink) and then subtracting an offset value to get to the start of the _EPROCESS structure of the next or the previous process. To help you understand what this means, let's look at the values of the fields Flink and Blink in the _EPROCESS structure of smss.exe:

kd> dt -b -v nt!_EPROCESS fffffa8061d35700
struct _EPROCESS, 135 elements, 0x4d0 bytes
.....
+0x180 UniqueProcessId : 0x00000000`000000fc
+0x188 ActiveProcessLinks : struct _LIST_ENTRY, 2 elements, 0x10 bytes
[ 0xfffffa80`62583cb8 - 0xfffffa80`6106ccb8 ]
+0x000 Flink : 0xfffffa80`62583cb8
+0x008 Blink : 0xfffffa80`6106ccb8

Flink has a value of 0xfffffa8062583cb8; this is the start address of the ActiveProcessLinks (Flink) of the next _EPROCESS structure. Since ActiveProcessLinks, in our example, is at offset 0x188 from the start of the _EPROCESS, you can get to the beginning of the _EPROCESS structure of the next process by subtracting 0x188 from the Flink value. In the following output, note how by subtracting 0x188 we landed on the _EPROCESS structure of the next process, which is csrss.exe:

kd> dt nt!_EPROCESS (0xfffffa8062583cb8-0x188)
+0x000 Pcb : _KPROCESS
+0x160 ProcessLock : _EX_PUSH_LOCK
[REMOVED]
+0x180 UniqueProcessId : 0x00000000`0000014c Void
+0x188 ActiveProcessLinks : _LIST_ENTRY [ 0xfffffa80`625acb68 - 0xfffffa80`61d35888 ]
+0x198 ProcessQuotaUsage : [2] 0x2c18
[REMOVED]
+0x288 Win32WindowStation : (null)
+0x290 InheritedFromUniqueProcessId : 0x00000000`00000144 Void
[REMOVED]
+0x2d8 Session : 0xfffff880`042ae000 Void
+0x2e0 ImageFileName : [15] "csrss.exe"
+0x2ef PriorityClass : 0x2 ''

As you can see, by walking the doubly linked list, it is possible to list the information about all the active processes running on the system. On a live system, tools such as task manager or Process Explorer make use of API functions, which ultimately rely on finding and walking the same doubly linked list of _EPROCESS structures that exist in kernel memory. The pslist plugin also incorporates the logic of finding and walking the same doubly linked list of _EPROCESS structures from the memory image. To do that, the pslist plugin finds a symbol named _PsActiveProcessHead, which is defined in ntoskrnl.exe (or ntkrnlpa.exe). This symbol points to the beginning of the doubly linked list of _EPROCESS structures; the pslist then walks the doubly linked list of the _EPROCESS structures to enumerate all the running processes.

For detailed information on the workings and the logic used by the Volatility plugins covered in this book, refer to The Art of Memory Forensics: Detecting Malware and Threats in Windows, Linux, and Mac Memory by Michael Hale Ligh, Andrew Case, Jamie Levy, and Aaron Walters.

As mentioned earlier, a plugin such as pslist supports multiple options and arguments; this can be displayed by typing -h (--help) next to the plugin's name. One of the pslist options is --output-file. You can use this option to redirect the pslist output to the file, as shown here:

$ python vol.py -f perseus.vmem --profile=Win7SP1x86 pslist --output-file=pslist.txt

Another option is -p (--pid). Using this option, you can determine the information of a specific process if you know its process ID (PID):

$ python vol.py -f perseus.vmem --profile=Win7SP1x86 pslist -p 3832
Volatility Foundation Volatility Framework 2.6
Offset(V) Name PID PPID Thds Hnds Wow64 Start
---------- ------------ ---- ---- ---- ---- ----- -------------------
0x8503f0e8 svchost..exe 3832 3712 11 303 0 2016-09-23 09:24:55