Memory Forensics: Enumeration
In Part 1 of this article, we have looked at the memory forensics power during the enumeration of forensically important objects like PROCESS, VAD nodes, MEMORY mapping, etc. In this article we will see memory forensics enumeration of other forensically important objects.
DLLS Enumeration from memory
DLL’s are used to be shared among processes for code reusability. These get linked to process via dynamic linking, as dependencies of other DLLs and even via injection. Since DLLs lives under a process, they got full access to process memory space.
This plugin traverses the dll list to find the loaded dlls per process. This plugin will miss out on hidden dlls.
This is a very useful plugin to find out the hidden DLLs. Like explained earlier DLL can be easily hidden from the LinkedLists by changing the Flink and Blink pointers. Ldrmodules can list the DLL status in all three lists stated above in ‘True’ or ‘False’ column
GUI objects enumeration
Windows GUI subsystem handles user inputs, look and feel of the interface, isolation of different user environments, etc. From a forensics perspective, it becomes important to understand all the objects in GUI, their structure and what all information can be gathered from them while they are in memory.
There are different types of windows stations in Windows for example stations that require user input like WinSta0 are interactive stations whereas those which operate at background are non-interactive stations.
- The desktop object is the container for all user interface objects. As mentioned under Session object section, on login a user is assigned Winsta0. Under Winsta0 there are three types of desktop:
- Winlogon: This desktop represents the login screen to the user and is interactive since it accepts user inputs.
- Default: On logon, Winlogon desktop switches to Default login which is user desktop
- There are various ways for users to log into a system like Remote Desktop Protocol (RDP), console, etc. and for each of these, the kernel creates a session for each user.
- We can see the rdpclip.exe file in above screenshot. It is used to handle remote clipboard operation like copy, paste, etc. To map the interesting process back to the user, we will use Volatility’s getsids plugin. Plugin getsids will take process pid as input and will display the associated users SIDs.
Example: Process Hollowing
It is a technique by which malware will replace a legitimate process with a duplicate process but with malicious code. This helps the malware to hide among other legitimate processes. The new malicious process looks so similar to the original legitimate process that even the image name, path and command lines remain unchanged. Below are the steps usually followed for process hallowing:
- First, target process is created in suspended state using CreateProcess with a CREATE_SUSPENDED option. After the process is created its memory space can be altered with the handle provided. This handle will be referenced in all the subsequent function calls. Note that at this point malicious process is loaded but not yet executed because it was created in a suspended state.
- Next step is to find the Process Environment Block (PEB section) for this malicious process which can be done using ReadRemotePEB helper function. After this is acquired, image base address is read to locate the NT headers.
- Next step is to hollow the legitimate code from memory in the hosted process. For this NtUnmapViewOfSection is used. Because it is a kernel function, malware usually resolves the function at runtime using GetProcAddress.
- Next step is to allocate a new block of memory to host malicious code. Malware usually makes the entire block PAGE_EXECUE_READWRITE for simplicity otherwise permissions can be set for each section as well.
- Since space has been allocated for a new image, WriteProcessMemory is used to write the new image code in place of original image code. In the optional header structure, the base address will be changed to that of the new memory image. If however, the image base of the new image does not match up with image base of original image then the image base of the new image need to be rebased.
- SetThreadContext function is used to set the context of this process.
- The last step is just to resume the process using ResumeThread.
After obtaining system image, it is observed to have multiple instances of lsass running. Under normal circumstances, only one instance of lsass should be running.
Using Volatility plugin malfind
As discussed above, if the malware author forgot to fix the RWX protection on his malicious spawned process, then that can be detected by Volatility plugin ‘malfind.’ Malfind looks for memory section that has PAGE_EXECUTE_READWRITE privileges and cannot be mapped onto the disk. It also dumps the assembly code at that memory section and final check to look at whether there is an executable code in the dump code is left for the analysts.
We can see that both these has MZ header but cannot be mapped to disk (pre-requisite for malfind). However, this MZ header can be easily manipulated by malware authors. To overcome this malfind gives you all the possible hallowed/injected section which Redline miss if the memory section does not have an MZ header.
Challenges in Memory Forensics
- Memory is not acquired properly and is corrupted.
- Change in OS internal structures with new releases.
- Compatibility issues between Image creator software and VM’s.
- Requires a thorough understanding of internal structures and expected(benign) OS/process’s behavior.
- To analyze end to end, memory forensics must be combined with Reverse Engineering.
There are lot more forensically important artifacts like registry keys etc. that can also be enumerated from memory which we have not discussed. Because of all this, it thus becomes necessary for monitoring and response teams to incorporate Memory Forensics in daily investigations