Process Creation Mechanism
Now that you know a little bit about the various structures involved with processes, it would be helpful to know something about how the operating system uses those structures, particularly when it comes to creating an actual process.
A number of steps are followed when a process is created. These steps can be broken down into six stages (taken from Windows Internals, 4th Edition, next topic, by Russinovich and Solomon):
1. The image (.exe) file to be executed is opened. During this stage, the appropriate subsystem (POSIX, MS-DOS, Win 16, etc.) is identified. Also, the Image File Execution Options Registry key is checked to see whether there is a Debugger value, and if there is, the process starts over.
2. The EProcess object is created. The kernel process block (KProcess), the process environment block, and the initial address space are also set up.
3. The initial thread is created.
4. The Windows subsystem is notified of the creation of the new process and thread, along with the ID of the process’s creator and a flag to identify whether the process belongs to a Windows process.
5. Execution of the initial thread starts. At this point, the process environment has been set up and resources have been allocated for the process’s thread(s) to use.
6. The initialization of the address space is completed, in the context of the new process and thread.
At this point, the process now consumes space in memory in accordance with the EProcess structure (which includes the KProcess structure) and the PEB structure. The process has at least one thread and may begin consuming additional memory resources as the process itself executes. At this point, if the process or memory as a whole is halted and dumped, there will at least be something to analyze.
Parsing Memory Dump Contents
The tools described in the DFRWS 2005 Memory Challenge used a methodology for parsing memory contents of locating and enumerating the active process list, using specific values/offsets (derived from system files) to identify the beginning of the list and then walking through the doubly linked list until all the active processes had been identified. The location of the offset for the beginning of the active process list was derived from one of the important system files, ntoskrnl.exe.
Andreas Schuster took a different approach in his Perl script, called ptfinder.pl. His idea was to take a brute force approach to the problemâidentifying specific characteristics of processes in memory and then enumerating the EProcess blocks as well as other information about the processes based on those characteristics. Andreas began his approach by enumerating the structure of the DISPATCHER_HEADER, which is located at offset 0 for each EProcess block (actually, it’s within the structure known as the KProcess block). Using LiveKD, we see that the enumerated structure from a Windows 2000 system has the following elements:
In a nutshell, Andreas found that some of the elements for the DISPATCHER_ HEADER were consistent in all processes on the system. He examined the DISPATCHER_ HEADER elements for processes (and threads) on systems ranging from Windows 2000 up through early betas of Vista and found that the Type value remained consistent across each version of the operating system. He also found that the Size value remained consistent within various versions of the operating system (e.g., all processes on Windows 2000 or XP had the same Size value) but changed between those versions (e.g., for Windows 2000 the Size value is 0x1b, but for early versions ofVista it was 0×20).
Using this information as well as the total size of the structure and the way the structure itself could be broken down, Andreas wrote his ptfinder.pl Perl script, which would enumerate processes and threads located in a memory dump. At the DFRWS 2006 conference he also presented a paper, "Searching for processes and threads in Microsoft Windows memory dumps" (www.dfrws.org/2006/proceedings/2-Schuster.pdf ), which addressed not only the data structures that make up processes and threads but also various rules to determine whether what was found was a legitimate structure or just a bunch of bytes in a file.
Note
In fall 2006, Richard McQuown (http://forensiczone.blogspot.com/) put together a GUI front end for Andreas Schuster’s PTFinder tools. The PTFinder tools are Perl scripts and require that the Perl interpreter be installed on a system to run them. (Perl is installed by default on many Linux distributions and is freely available for Windows platforms from ActiveState.com.)
Not only can Richard’s tool detect the operating system of the RAM dump (rather than have the user enter it manually) using code I’ll discuss later in this topic, but it can also provide a graphical representation of the output. PTFinderFE has some interesting applications, particularly with regard to visualization.
In spring 2006, I wrote some of my own tools to assist in parsing through Windows RAM dump files. Because the currently available exemplars at the time were the dumps for Windows 2000 systems available from the DFRWS 2005 Memory Challenge, I focused my initial efforts on producing code that worked for that platform. This allowed me to address various issues in code development without getting too wrapped up in the myriad differences between the various versions of the Windows operating system. The result was four separate Perl scripts, each run from the command line. All of these scripts are provided on the accompanying DVD, and we’ll discuss them here.
Note
The following tools (lsproc.pl, lspd.pl, lspi.pl, and lspm.pl) are designed to be used solely with Windows 2000 memory dumps. As we’ve discussed so far, there are significant changes in the EProcess structure format between the various versions of Windows (2000, XP, 2003, Vista, etc.). As such, significant work needs to be done to produce a single application that will allow you to parse memory dumps from all versions.
Lsproc.pl
LSproc, short for list processes, is similar to Andreas’s ptfinder.pl; however, lsproc.pl locates processes but not threads. Lsproc.pl takes a single argument, the path and name to a RAM dump file:
The output of lsproc.pl appears at the console (i.e., STDOUT) in six columns: the word Proc (I was anticipating adding threads at a later date), the parent process identifier (PPID), the process identifier (PID), the name of the process, the offset of the process structure within the dump file, and the creation time of the process. Here is an excerpt of the lsproc. pl output:
Proc |
820 |
324 |
helix.exe |
0×00306020 |
Sun |
Jun 5 |
14:09:27 |
2005 |
Proc |
0 |
0 |
Idle |
0x0046d160 |
||||
Proc |
600 |
668 |
UMGR32.EXE |
0x0095f020 |
Sun |
Jun 5 |
00:55:08 |
2005 |
Proc |
324 |
1112 |
cmd2k.exe |
0x00dcc020 |
Sun |
Jun 5 |
14:14:25 |
2005 |
Proc |
668 |
784 |
dfrws2005.exe(x) |
0x00e1fb60 |
Sun |
Jun 5 |
01:00:53 |
2005 |
Proc |
156 |
176 |
winlogon.exe |
0x01045d60 |
Sun |
Jun 5 |
00:32:44 |
2005 |
Proc |
156 |
176 |
winlogon.exe |
0×01048140 |
Sat |
Jun 4 |
23:36:31 |
2005 |
Proc |
144 |
164 |
winlogon.exe |
0×010 4ca0 0 |
Fri |
Jun 3 |
01:25:54 |
2005 |
Proc |
156 |
180 |
csrss.exe |
0×01286480 |
Sun |
Jun 5 |
00:32:43 |
2005 |
Proc |
144 |
168 |
csrss.exe |
0x01297b40 |
Fri |
Jun 3 |
01:25:53 |
2005 |
Proc |
8 |
156 |
smss.exe |
0x012b62c0 |
Sun |
Jun 5 |
00:32:40 |
2005 |
Proc |
0 |
8 |
System |
0x0141dc60 |
||||
Proc |
668 |
784 |
dfrws2005.exe(x) |
0x016a9b60 |
Sun |
Jun 5 |
01:00:53 |
2005 |
Proc |
1112 |
1152 |
dd.exe(x) |
0x019d1980 |
Sun |
Jun 5 |
14:14:38 |
2005 |
Proc |
228 |
592 |
dfrws2 0 05.exe |
0×02138640 |
Sun |
Jun 5 |
01:00:53 |
2005 |
Proc |
820 |
1076 |
cmd.exe |
0x02138c40 |
Sun |
Jun 5 |
00:35:18 |
2005 |
Proc |
240 |
788 |
metasploit.exe(x) |
0×0 2 6 8 6cc0 |
Sun |
Jun 5 |
00:38:37 |
2005 |
Proc |
820 |
964 |
Apoint.exe |
0x02b84400 |
Sun |
Jun 5 |
00:33:57 |
2005 |
Proc |
820 |
972 |
HKserv.exe |
0x02bf86e0 |
Sun |
Jun 5 |
00:33:57 |
2005 |
Proc |
820 |
988 |
DragDrop.exe |
0x02c4 6020 |
Sun |
Jun 5 |
00:33:57 |
2005 |
Proc |
820 |
1008 |
alogserv.exe |
0x02e7ea20 |
Sun |
Jun 5 |
00:33:57 |
2005 |
Proc |
820 |
972 |
HKserv.exe |
0×0 2f8 0 6e0 |
Sun |
Jun 5 |
00:33:57 |
2005 |
Proc |
820 |
1012 |
tgcmd.exe |
0x030826a0 |
Sun |
Jun 5 |
00:33:58 |
2005 |
Proc |
176 |
800 |
userinit.exe(x) |
0x03e35020 |
Sun |
Jun 5 |
00:33:52 |
2005 |
Proc |
800 |
820 |
Explorer.Exe |
0x03e35ae0 |
Sun |
Jun 5 |
00:33:53 |
2005 |
Proc |
820 |
1048 |
PcfMgr.exe |
0x040b4660 |
Sun |
Jun 5 |
00:34:01 |
2005 |
The first process listed in the lsproc.pl output is helix.exe. According to the information provided at the DFRWS 2005 Memory Challenge Web site, utilities on the Helix Live CD were used to acquire the memory dump.
The preceding listing shows only an excerpt of the lsproc.pl output. A total of 45 processes were located in the memory dump file. You’ll notice in the output that several of the processes have (x) after the process name. This indicates that the processes have exited.
Note
Looking closely, you’ll notice some interesting things about the lsproc.pl output. One is that the csrss.exe process (PID = 168) has a creation date that appears to be a day or two earlier than the other listed processes. Looking even more closely, you’ll see something similar for two winlogon.exe processes (PID = 164 and 176). Andreas Schuster noticed these as well, and according to an entry on data persistence in his blog (http://computer.forensikblog.de/ en/2006/04/persistance_through_the_boot_process.html), the system boot time for the dump file was determined to be Sunday, January 5, 2005, at approximately 00:32:27. So, where do these processes come from?
As Andreas points out in his blog, without having more definitive information about the state of the test system prior to collecting data for the Memory Challenge, it is difficult to develop a complete understanding of this issue. However, the specifications of the test system were known and documented, and it was noted that the system suffered a crash dump during data collection.
It is entirely possible that the data survived the reboot. There don’t seem to be any specifications that require that when a Windows system shuts down or suffers a crash dump, the contents of physical memory are zeroed out or wiped in some manner. It is possible, then, that contents of physical memory remain in their previous state, and if they are not overwritten when the system is restarted, the data is still available for analysis. Many BIOS versions have a feature to overwrite memory during boot as part of a RAM test, but this feature is usually disabled to speed up the boot process.
This is definitely an area that requires further study. As Andreas states (http://computer.forensikblog.de/en/2006/04/data_lifetime.html), this area of study has "a bright future."
Lspd.pl
Lspd.pl is a Perl script that will allow you to list the details of the process. Like the other tools we will be discussing, lspd.pl is a command-line Perl script that relies on the output of lsproc.pl to obtain its information. Specifically, lspd.pl takes two arguments: the full path of the dump file and the physical offset of the process that you’re interested in (the physical offset of the process within memory is obtained from the lsproc.pl output). Although lsproc. pl takes some time to parse through the contents of the dump file, lspd.pl is much quicker, because you’re telling it exactly where to go in the file to enumerate its information.
Let’s take a look at a specific process. In this case, we’ll look at dd.exe, the process with PID 284. The command line to use lspd.pl to get detailed information about this process is:
Note
The lsproc.pl output just shown is an excerpt of the entire output; I didn’t list the entire output simply because the excerpt illustrates enough information for me to make my point. However, the process referenced in the lspd.pl command line (i.e., at offset 0x0414dd60) is not listed in that excerpt, although it is visible in the full output of lsproc.pl.
Notice that with lspd.pl, we’re using two arguments: the name and path to the dump file and the physical offset in the dump file where we found the process with lsproc.pl. We’ll take a look at the output of lspd.pl in sections, starting with some useful information pulled directly from the EProcess structure itself:
Process Name |
: dd.exe |
PID |
: 284 |
Parent PID |
: 1112 |
TFLINK |
: 0xff2401c4 |
TBLINK |
: 0xff2401c4 |
FLINK |
: 0x8046b980 |
BLINK |
: 0xff1190c0 |
SubSystem |
: 4.0 |
Exit Status |
: 259 |
Create Time |
: Sun Jun 5 14:53:42 2005 |
Exit Called |
: 0 |
DTB |
: 0x01d9e0 0 0 |
ObjTable |
: 0xff158708 (0x00eb6708) |
PEB |
: 0x7ffdf000 (0x02c2d000) |
InheritedAddressSpace |
: 0 |
ReadImageFileExecutionOptions |
: 0 |
BeingDebugged |
: 0 |
CSDVersion |
: Service Pack 1 |
Mutant |
= 0xffffffff |
Img Base Addr |
= 0×00400000 (0x00fee000) |
PEB LDR DATA |
= 0×0 0131e90 (0x03a1ee90) |
Params |
= 0×00020000 (0x03a11000) |
Note
The flink and blink values seen in the preceding lspd.pl output are the values that point to the next and previous processes, respectively. As displayed in the output of lspd.pl, these pointers are to addresses in memory, not physical addresses or offsets within the dump file.
As you can see from the preceding command line, the file \intrusion\audit.log is located on the F:\ drive and is the output file for the log of activity generated by dd.exe, which explains why it would be listed as an open file handle in use by the process. Using this information as derived from other processes, you can get an understanding of files you should be concerned with during an investigation. In this particular instance, you can assume that the E:\ drive listed in ImagePathName is a CD-ROM drive, because Helix can be run from a CD. You can confirm this by checking Registry values in an image of the system in question (a system image is not provided as part of the memory challenge, however). You can also use similar information to find out a little bit more about the F:\ drive. I will cover this information in next topic.
Finally, one other thing that lspd.pl will do is go to the location pointed to by the Image Base Addr value (once it has been translated from a virtual address to a physical offset within the memory dump file) and check to see whether a valid executable image is located at that address. This check is very simple; all it does is read the first two bytes starting at the translated address to see whether they’re MZ. These two bytes are not a definitive check, but PE files (files with .exe, .dll, .ocs, .sys, and similar extensions) start with the initials of Mark Zbikowski, one of the early architects of MS-DOS and Windows NT.
Tip::
If you dumped the contents of physical memory from a Windows 2000 or XP system using winen.exe and you have a licensed EnCase dongle, you can parse process information from a memory dump using EnScripts written by TK_Lane and available through the "EDD and Forensics" blog (http://eddandforensics.blogspot.com/2008/04/windows-memory-analysis.html).
Volatility Framework
Aaron Walters provides some valuable information about the Volatility Framework in his OMFW presentation, available from https://www.volatilesystems.com/volatility/omfw/ Walters_OMFW_2008.pdf.
The readme.txt file that is part of the Volatility distribution ( Version 1.3 beta at the time of this writing) provides a great deal of information about how to use Volatility and what types of commands and capabilities are available, as well as examples of how to launch the various commands. Aaron designed Volatility to use some of the commands that are commonly used in incident response activities; for example, to get a list of running processes from a memory dump, Volatility uses pslist. Before using Volatility, be sure to read through the readme.txt file to see what type of information can be retrieved from a Windows XP SP2 or SP3 memory dump.
To illustrate what type of information is available from a raw, dd-style memory dump, let’s take a look at an example; in this case a 512MB memory dump from a Windows XP SP2 laptop. We can start by getting some basic information about the memory dump using the ident command:
This can be very useful information in documenting our analysis of the memory dump, as in some instances, we may not have access to the ident information as part of our documentation. Using the pslist command, we can retrieve the active process list from the memory dump in a format similar to what we’re used to seeing when running pslist.exe on a live system:
wuauclt.exe |
2424 |
840 |
4 |
160 |
Sat |
Jun 25 16:49:21 |
2005 |
firefox.exe |
2160 |
1812 |
6 |
182 |
Sat |
Jun 25 16:49:22 |
2005 |
PluckSvr.exe |
944 |
740 |
9 |
227 |
Sat |
Jun 25 16:51:00 |
2005 |
iexplore.exe |
2392 |
1812 |
9 |
365 |
Sat |
Jun 25 16:51:02 |
2005 |
PluckTray.exe |
2740 |
944 |
3 |
105 |
Sat |
Jun 25 16:51:10 |
2005 |
PluckUpdater.ex |
3076 |
1812 |
0 |
-1 |
Sat |
Jun 25 16:51:15 |
2005 |
PluckUpdater.ex |
1916 |
944 |
0 |
-1 |
Sat |
Jun 25 16:51:40 |
2005 |
PluckTray.exe |
3256 |
1812 |
0 |
-1 |
Sat |
Jun 25 16:54:28 |
2005 |
cmd.exe |
2624 |
1812 |
1 |
29 |
Sat |
Jun 25 16:57:36 |
2005 |
wmiprvse.exe |
4080 |
740 |
7 |
0 |
Sat |
Jun 25 16:57:53 |
2005 |
PluckTray.exe |
3100 |
1812 |
0 |
-1 |
Sat |
Jun 25 16:57:59 |
2005 |
dd.exe |
4012 |
2624 |
1 |
22 |
Sat |
Jun 25 16:58:46 |
2005 |
We can run similar commands to retrieve information about all process objects in the memory dump, including exited processes, using the psscan or psscan2 command. Commands to retrieve information about all objects (network connections, processes, etc.) are slower, as they use a linear scanning method to run completely through the memory dump file, examining all possible objects, rather than using specific offsets provided by the operating system (see the discussion about LiveKD earlier in this topic).
One of the more useful things most analysts look to when responding to an intrusion or compromise is network connections. You can retrieve a list of active network connections (similar to using the netstat -ano command) from a memory dump using the connections command, as follows:
Taking this a step further, you can scan the entire memory dump file for indications of network connection objects, specifically looking for network connections that may have been closed at the time the memory dump was acquired:
Local Address |
Remote Address |
Pid |
192.168.2.7:1115 |
207.126.123.29:80 |
1916 |
3.0.48.2:17985 |
66.179.81.245:20084 |
4287933200 |
192.168.2.7:1164 |
66.179.81.247:80 |
944 |
192.168.2.7:1082 |
205.161.7.134:80 |
2392 |
192.168.2.7:1086 |
199.239.137.200:80 |
1916 |
192.168.2.7:1162 |
170.224.8.51:80 |
1916 |
127.0.0.1:1055 |
127.0.0.1:1056 |
2160 |
192.168.2.7:1116 |
66.161.12.81:80 |
1916 |
192.168.2.7:1161 |
66.135.211.87:443 |
1916 |
192.168.2.7:1091 |
209.73.26.183:80 |
1916 |
192.168.2.7:1151 |
66.150.96.111:80 |
1916 |
192.168.2.7:1077 |
64.62.243.144:80 |
2392 |
192.168.2.7:1066 |
199.239.137.200:80 |
2392 |
192.168.2.7:1157 |
66.151.149.10:80 |
1916 |
192.168.2.7:1091 |
209.73.26.183:80 |
1916 |
192.168.2.7:1115 |
207.126.123.29:80 |
1916 |
192.168.2.7:1155 |
66.35.250.150:80 |
1916 |
127.0.0.1:1056 |
127.0.0.1:1055 |
2160 |
192.168.2.7:1115 |
207.126.123.29:80 |
1916 |
192.168.2.7:1155 |
66.35.250.150:80 |
1916 |
Volatility is a powerful open source framework, allowing others to extend its capabilities by developing additional modules (knowledge of Python programming is a significant requirement). Brendan Dolan-Gavitt (a.k.a. Moyix) created a Volatility module that looks for Windows messages (http://moyix.blogspot.com/2008/09/window-messages-as-forensic-resource.html), which are various events generated by Windows GUI applications and handled by the message queue. As Brendan points out, an application may be poorly written and may not handle its own messages very well; if this is the case, you may be able to find remnants of those messages still visible in the memory dump. This information may be useful during a forensic examination.
Volatility is a powerful open source framework, allowing others to extend its capabilities by developing additional modules (knowledge of Python programming is a significant requirement). Brendan Dolan-Gavitt (a.k.a. Moyix) created a Volatility module that looks for Windows messages (http://moyix.blogspot.com/2008/09/window-messages-as-forensic-resource.html), which are various events generated by Windows GUI applications and handled by the message queue. As Brendan points out, an application may be poorly written and may not handle its own messages very well; if this is the case, you may be able to find remnants of those messages still visible in the memory dump. This information may be useful during a forensic examination.
Tip::
Brendan also produced several Volatility plug-ins for accessing Registry data found in Windows memory dumps (his blog post is at http://moyix.blogspot.com/2009/01/memory-registry-tools.html, and updates to the code are at http://moyix.blogspot.com/2009/01/registry-code-updates.html). In his own blog (http://forensiczone.blogspot.com/2009/01/using-volatility-1.html), Richard McQuown demonstrated using these modules to extract passwords from a Security Account Manager (SAM) hive file located in memory so that he could crack those passwords using his tool of choice.
To use Volatility and Brendan’s modules to extract passwords from hive files located in memory, you have to install the PyCrypto modules (available as prebuilt Windows binaries from www.voidspace.org.uk/python/modules.shtml#pycrypto).
In addition, Jesse Kornblum produced two modules: suspicious, which looks for suspicious entries in process command lines, and cryptoscan, which looks for TrueCrypt passphrases. This last module can be extremely beneficial to an analyst, as TrueCrypt (www.truecrypt.org/) is a powerful, albeit free, application that can be used to encrypt volumes and disks.
Volatility works with much more than just simply raw memory dumps. Thanks to the efforts of Matthieu Suiche (www.msuiche.net/), Volatility includes the capability to parse hibernation files, as well. This started out as the Sandman Project, and later became an integral part of the Volatility Framework. In December 2008, Matthieu released a stand-alone, closed source (alpha) version of the hibernation framework shell, called hibrshell (www.msuiche. net/hibrshell/). This version of hibrshell reportedly works with hibernation files from Windows XP, 2003, Vista, and 2008 systems.
Tip::
Regardless of the framework used to analyze it, the hibernation file provides a responder or analyst with several options that were not previously available. First, the hibernation file can be used as historical data, providing information about the system’s live, running state at a previous point in time. This can be extremely valuable in malware analysis, as well as to assist in determining a timeline for an intrusion, particularly if the analyst also has a current memory dump to analyze. In circumstances where the previously mentioned tools (e.g., mdd.exe, etc.) cannot be used to dump the contents of physical memory from a system, the responder may be able to force the system to hibernate to create a memory dump that can then be analyzed.
Volatility can also parse crash dump files, as well as convert a raw, dd-style memory dump to crash dump format so that the analyst can use Microsoft’s debugger tools.
By now it should be clear that the Volatility Framework provides some extremely powerful capabilities, and just how much information the analyst can retrieve from a memory dump. To help correlate some of the data that can be retrieved using Volatility, Jamie Levy wrote a Perl script called vol2html.pl (http://gleeda.blogspot.com/2008/11/vol2html-perl-script.html).The script takes the output of the Volatility pslist,files, and dlllist commands and correlates them into an HTML report, an example of which you can see at http://venus.cs.qc.edu/~jlevy/code/report/index.html. Similar to the familiar listdlls.exe available from Microsoft (Sysinternals), the Volatility dlllist command includes the process command line as part of its output; this command line also appears in the HTML output of vol2html.pl.
Examples of Windows XP memory dump files are available as part of the DFRWS 2008 Forensic Rodeo (www.dfrws.org/2008/rodeo.shtml), as well as from the National Institute of Standards and Technology (www.cfreds.nist.gov/mem/Basic_Memory_Images.html).
Michael Hale Ligh provides two blog posts that describe how he has used the Volatility Framework to great effect, particularly with respect to malware analysis; see "Recovering CoreFlood Binaries with Volatility" (http://mnin.blogspot.com/2008/11/recovering-coreflood-binaries-with.html), and "Locating Hidden Clampi DLLs (VAD-style)" (http://mnin.blogspot.com/2008/11/locating-hidden-clampi-dlls-vad-style.html). Both blog posts provide excellent examples of how the Volatility Framework can maximize an analyst’s capabilities.