In this article, we will learn what process hallowing is, how is it done, and how we can detect it while performing memory analysis.
It is a technique by which malware will replace a legitimate process with a duplicate process but with malicious code. The process 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 a suspended state using CreateProcess with 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.
Detection of Process Hallowing Using Volatility
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 first run the malfind plugin on a sample image and got following output
There is some clear process hallowing happened here. Multiple instances of lsass.exe are running where under normal circumstances only 1 should be running. To compare these with a normal lsass.exe we ran pslist plugin and got following output
Now process 680 has parent 624 and process 868 & 1928 has parent 668. Running a pstree will give us a good indication of parent-child relationship.
From above we can conclude that process 680 looks legitimate since it has a valid parent winlogon.exe and it was not present in malfind output. To further illustrate this, we will look at the dumped memory sections from process 868,1928.
Here 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 a MZ header.
It is worth to note that while performing memory analysis process hallowing and code injection looks very same.
Comparing the size of multiple instances of same process
We can even look at the sizes of all lsass process. First we will dump these lsass process using Volatility’s procdump plugin. Then we do a ls on the directory where we dumped all the 3 lsass processes. We can clearly see a difference in the size of the 680 vs. 1928 & 868.
After dumping these devices, I plugged it into a machine which has antivirus installed on it. McAfee recognized 1928 as a malicious process and as per set up policies as below
For other process i.e. 868 I submit it to virus total and it confirms that the process is malicious (39/54)
Comparing the processes with fuzzy hashing
We can even use fuzzy hashing to see how much of these processes match each other. With hashing like md5 we can only see whether an output matches or not but with fuzzy hashing we can see how different files are close to being the same. We will use tool ssdeep over the dumped processes in volatility.
Below is the ssdeep tool running over the executables dumped from volatility in above step.
Below we can see that process 680 has 0 match with process 868 & 1928.
So in this article we see how process hallowing is done and how we can detect it with volatility plugins and fuzzy hashing.