In this blog post we will look at different types of process hollowing techniques used in the wild to bypass, confuse, deflect and divert the forensic analysis. I also present a Volatility plugin hollowfind to detect these different types of process hollowing. Before looking at the different types of process hollowing, lets try to understand the normal process hollowing, its working and detection. To explain the normal process hollowing I will use memory image which is infected with Stuxnet.
What is Process Hollowing?
Process Hollowing or Hollow Process Injection is a code injection technique in which the executable section of a legitimate process in the memory is replaced with malicious code (mostly malicious executable). This technique is used to blend in malware as a legitimate process and using this technique attackers can cause a legitimate process to execute malicious code. The advantage of this technique is that the path of the process being hollowed out will still point to the legitimate path and by executing within the context of legitimate process the malware can bypass firewalls and host intrusion prevention systems. For example if svchost.exe process is hollowed out the path will still point to the legitimate executable (C:\Windows\system32\svchost.exe), but only in the memory the executable section of svchost.exe is replaced with malicious code, this allows the attackers to remain undetected from live forensic tools.
Working of Process Hollowing?
The working of process hollowing and detecting it is very well explained in the book The Art of Memory Forensics and also in my presentation & video demos The following steps describe how malware normally performs process hollowing. Let’s assume there are two processes A and B, in this case process A is the malicious process and process B is the legitimate process (also called as remote process).
- Process A starts a legitimate process B in the suspended mode as a result of that the executable section of process B is loaded in the memory and also the PEB (process environment block) identifies the full path to the legitimate process and PEB’s ImageBaseAddress points to the address where the legitimate process executable is loaded.
- Malware process A gets the malicious code (mostly executable) to inject. This code can come from the resource section of the malware process or from the file on the disk
- Malware process A determines the base address of the legitimate process B so that it can unmap the executable section of the legitimate process. Malware can determine the base address by reading the PEB (i.e PEB.ImageBaseAddress).
- Malware process A then deallocates the executable section of the legitimate process
- Malware process then allocates the memory in the legitimate process with read, write and execute permission, this memory allocation can is normally done at the same address where the executable was previously loaded.
- Malware then writes the PE Header and PE sections of the executable to inject in the allocated memory.
- Malware then changes the start address of the suspended thread to the address of entry point of the injected executable.
- Malware then resumes the suspended thread of the legitimate process, as a result of that the legitimate process now starts executing malicious code.
Detecting Process Hollowing using Memory Forensics
This section focuses on detecting process hollowing technique, since the code injection happens only in memory it is best detected using memory forensics. Stuxnet is one of the malware which performs hollow process injection using the steps mentioned above. Complete Analysis of Stuxnet using memory forensics is covered in this blog post. In this post I will cover some of the steps relevant to detecting process hollowing using memory forensics.
a) Detecting From Parent Child Process Relationship
Process listing shows two suspicious lsass.exe process (pid 868 and pid 1928) which was not started by winlogon.exe or wininit.exe but these processes were started by services.exe (pid 668). This is one of the technique to detect process hollowing, on a clean system winlogon.exe will be the parent process of lsass.exe on pre-Vista machines and wininit.exe will be the parent process of lsass.exe on Vista and later systems.
b) Detecting by Comparing the PEB and the VAD structure.
Hollow process injection can also be detected by comparing the results from the PEB (process environment block) structure and the VAD (Virtual address descriptor) structure. The PEB structure resides in the process memory and keeps tracks of the full path to the executable and its base address, whereas VAD structure resides in the kernel memory and also contains information about the contiguous process virtual address space allocation and if there is an executable loaded the VAD node contains information about the start address, end address and the full path to the executable. Comparing these two structures for discrepancy can tell if a process is hollowed out.
In the below screenshot running the dlllist plugin shows the full path to lsass.exe (pid 868) and the base address (0x01000000) where it is loaded. The dlllist plugin gets this information from the PEB
In the below screenshot running the ldrmodules plugin (which relies on VAD in the kernel) does not show full path name to the lsass.exe, the reason for this is because the malware umapped the lsass.exe process, as result of that the full path name is no longer associated with the address 0x01000000, looking for this discrepancy can give an indication of hollow process injection.
c) Detecting using suspicious memory protection
Hollow process injection can also be detected by looking for suspicious memory protection. Running the malfind plugin (which looks for suspicious memory protections) shows suspicious memory protection (PAGE_EXECUTE_READWRITE) at address 0x1000000 (which is base
address of lsass.exe) indicating that lsass.exe was not loaded normally (but was injected). Any executable that is normally loaded will have a memory protection of PAGE_EXECUTE_WRITECOPY. This further confirms that lsass.exe (pid 868) loaded at 0x1000000 is not legitimate.
Automating Process Hollow Detection using HollowFind Plugin
HollowFind is a Volatility plugin which automates detection of process hollowing by comparing the discrepancy in the PEB and VAD. Below screenshot shows hollowfind plugin in action. Running the hollowfind plugin on the stuxnet infected memory image identified both lsass.exe processes (pid 1928 and pid 868) and it also reports the the invalid exe memory protection (PAGE_EXECUTE_READWRITE) and process path discrepancy between the VAD and PEB and also it disassembles the address of entry point (read further to know more on this), also notice a jump to the address 0x1003121 at the address of entry point.
Once the plugin detects the hollowed process the plugin also displays similar processes which can help in quickly identifying the process anomaly. In the below screenshot notice how both lsass.exe processes (pid 868 and pid 1928) is associated with parent process services.exe (pid 668) indicating that these two processes are not legitimate, whereas the legitimate lsass.exe process (pid 680) has winlogon.exe(pid 624) as its parent. The hollowfind plugin also displays the suspicious memory regions which can help in identifying any injected code. In the below screenshot apart from the address 0x1000000 (which is the executable base address) there is one more address 0x80000 (in pid 868) where a PE File was found and the memory protection is set to PAGE_EXECUTE_READWRITE permission, indicating an executable being injected into this address.
The suspicious memory regions can be dumped with -D option as shown below. After dumping the suspicious memory regions the injected executable at address 0x80000 was submitted to VirusTotal, the VirusTotal results confirm it to be the component of Stuxnet.
Types of Process Hollowing
In this section lets focus on different types of process hollowing techniques used by malwares and see how some of these techniques can confuse the security analyst and divert the forensic analysis. Lets also see how hollowfind plugin can help in detecting such attacks.
a) Example 1: Skeeyah’s Process Hollowing (allocation in a different address and PEB modification)
Skeeyah performs all the steps mentioned above with slight difference, malware starts the svchost.exe process in suspended mode which gets loaded into the address 0x01000000 as shown below
Malware determines the base address of the legitimate process by reading PEB+8 (PEB.ImageBaseAddress) and then deallocates the executable section of the legitimate process as show below
It then allocates the memory in the legitimate process with read, write and execute permission at a different address (0x00400000) and then copies the exectuable to inject into this address.
Malware then overwrites the PEB.ImageBaseAdress of the legitimate process with the newly allocated address. In the below screenshot malware overwrites the PEB.ImageBaseAdress of svchost.exe with the new address (0x00400000), this changes the base address of svchost.exe
from 0x1000000 to 0x00400000 (which contains injected executable)
Malware then changes the start address of the suspended thread to the address of entry point of the injected executable by setting CONTEXT._Eax and using SetThreadContext api and it then resumes the thread
This type of process hollowing can be detected by comparing the PEB and VAD . In the below screenshots dlllist plugin shows the full path to svchost.exe (pid 1824) and the base address (0x00400000) whereas ldrmodules plugin (which relies on VAD in the kernel) does not show any entry for the svchost.exe, the reason for this is because when the malware hollowed out the svchost.exe process, the entry for that was removed in the VAD, looking for this discrepancy can give an indication of hollow process injection.
This detection is already automated in the hollowfind plugin. In the screenshot below hollowfind plugin shows the hollowed process (svchost.exe with pid 1824), it also reports that the VAD entry for the process executable is missing, it shows the discrepancy between the VAD and PEB and it shows the executable injected at the address 0x00400000
The hollowfind plugin after detecting the hollowed process, also shows the similar processes. In the screenshot below the hollowed process (svchost.exe with pid 1824) doesn’t have a parent process (because the parent process was exited) whereas other legitimate svchost.exe processes have a parent of services.exe (pid 696) and also notice the discrepancy in the creation time. On a clean system the legitimate svchost.exe process is started by services.exe, this indicates that svchost.exe (pid 1824) is malicious. The hollowfind also detected the suspicious memory regions (this is the region where executable was injected)
b) Example 2: No process hollowing (allocation in a different address and PEB Modification)
In this section we will look at another malware sample which performs different type of process hollowing which cause discrepancy in some of existing plugins, this could be deliberate attempt to trick security analyst and the forensic tools. Lets first try to understand how the malware performs process hollowing (or no process hollowing)
Malware creates svchost.exe in the suspsended mode which is loaded into the address 0x01000000 as shown below
Malware then allocates a memory in the remote process (svchost.exe) at address 0x00400000.This memory is allocated with read, write and execute (RWX) permission. In this case the malware did not unmap (hollow out) the memory at the address 0x01000000 (where suspended svchost.exe was loaded).
Malware then writes the PE file to inject (which it extracted from resource section) into the remote process (svchost.exe) at the allocated address 0x00400000
Malware then overwrites the PEB.ImageBaseAdress(PEB+8) of svchost.exe with the new address 0x00400000, at this point according to the PEB the svchost.exe is loaded at 0x00400000 whereas VAD still thinks the svchost.exe is at 0x01000000
Malware then changes the start address of the suspended thread to the address of entry point of the injected executable by setting CONTEXT._Eax and using SetThreadContext api and then it resumes the thread
This technique of not hollowing out the suspended process and modifying the PEB causes discrepancy in some of the plugins. In the screenshot below dlllist plugin (which relies on the PEB which resides in process memory) shows that the base address of svchost.exe (pid 2020) is at 0x00400000 whereas the Module listing from ldrmodules plugin which rely on kernel structures (VAD) shows the discrepancy in the base address indicating that svchost.exe is loaded at 0x01000000. Apart from the base address discrepancy notice the Inload, and InMem values are set to False indicating that svchost.exe could be hidden (which is not true because dlllist output shows the presence of svchost.exe). This discrepancy in the base address for the same process (pid 2020) can confuse the security analyst, the normal reaction could be to rely on the ldrmodules output because it relies on kernel structures (and also because it is giving a feeling that svchost.exe is unlinked)
Let’s rely on the ldrmodules output (which comes from the kernel structure) and lets use the base address reported by ldrmodules(0x01000000). let’s investigate further and see what happens. First lets focus on the svchost.exe with base address 0x01000000 (later we will focus
on the address 0x00400000). Dumping the executable using the base address (0x01000000) reported by ldrmodules confirms that it is an executable. In this case dlldump plugin was used to dump the executable because it allows you to dump any PE file using its base address.
Submitted the PE File dumped using the base address 0x01000000 to VirusTotal does not show any Anti virus detections, indicating that it’s not malicious.
Extracting the strings from the PE File dumped using the base address 0x01000000 does not show many strings as shown below (in fact it has very less strings, only 9 strings in the entire executable). So in this case we dumped the suspended (legitimate) svchost.exe process executable (residing at 0x01000000) not the actual malicious component.
Looking for suspicious memory protections by running the malfind plugin does not shows any suspicious memory protection at the address 0x01000000 whereas it shows a suspicous memory protection at the address 0x00400000 (this is the address where malicious executable was injected, which was also reported by dlllist). This indicates that there is no malicious component at the address 0x01000000 but there is malicious component at address 0x00400000.
Now let’s shift our focus to the svchost.exe with base address 0x00400000 (reported by PEB). Dumping the svchost.exe with base address 0x00400000 and submitting to VirusTotal confirms this to be the malicious component.
Extracting the strings from the PE file of the of the svchost.exe with base address 0x00400000 this time shows more strings and it also contains references to the C2 ip addresses, indicating that we have detected the malicious executable.
As you can see malware was able to create a discrepancy causing confusion and diversion which might trick the analyst to miss the actual malicious component and also it was able to deceive the plugin which rely on kernel structures.
The hollowfind plugin can detect this discrepancy by comparing the VAD and PEB. In the below screenshot the hollowfind plugin detected the discrepancy in the base address and the memory protections, this allows one to quickly identify the malicious component. In this case even though there is discrepancy in the base address but the memory protection of PAGE_EXECUTE_READWRITE at the address 0x400000 tells you that this is the malicious component.
The hollowfind plugin also gives the similar processes and the suspicious memory regions which can help you spot the parent process discrepancy, creation time discrepancy and the injected code.
c) Example 3: Kuluoz’s process hollowing (Address of Entry Point Modification )
In this section let’s try to understand how Kuluoz causes diversion, by understanding the technique we can better understand how to detect and counter such malware techniques. Kuluoz creates svchost.exe process in the suspended mode which loaded svchost.exe at address 0x120000
Instead of using VirtualAllocEX and WriteProcessMemory api call, kuluoz uses a different trick. It first creates a section in its own address space, copies the malicious code into the created section and then maps a view of this section with read, write, execute(rwx) protections in the remote process using NtMapViewOfSection API. As a result of this a memory is allocated in the svchost.exe process at address 0x60000 also the malicious code is copied into that address (this is the code which performs the malicious actions)
Malware then creates another section in its own address space and copies the svchost.exe content into the created section and then patches the svchost.exe at the address of entry point, it just modifies 7 bytes (i.e. 3 instructions). It then unmaps the section in the svchost.exe where its executable is loaded (i.e 0x120000), at this point the svchost.exe is hollowed out, notice in the below screenshot how the entry for svchost.exe is no longer present.
Malware then maps the section (which contains patched svchost.exe) into the remote process (svchost.exe) at the same address 0x120000 with read, write, execute (rwx) protection, also in the screenshot below the tool no longer shows the full path to the svchost.exe (this is because of hollow process technique).
Comparing the address of entry point of the legitimate svchost.exe (on the left) and the patched svchost.exe (on the right) process shows the difference in the 7 bytes at the address of entry point, whereas all other bytes are same. These 7 bytes turn out to be 3 instructions which
will redirect the control flow to the malicious code that was injected before (at address 0x60000)
Malware then resumes the suspended thread as result of that malware executes the code at the address of entry point of svchost.exe which will redirect the control to the malicious code (at address 0x60000) which performs malicious actions.
Lets look at a memory image infected with Kulouz, the technique mentoned above attempts to creates confusion and diversion by creating discrepancy in the dlllist and ldrmodules making it look like the suspect svchost.exe process is malicious. In this case even though the suspect svchost.exe process is patched but it is not completely malicious, the malicious code is at a different location. In the screenshot below the notice the svchost.exe process path discrepancy and the base address is 0x00a00000.
Running malfind plugin shows the suspicious memory protection at the address(0x00a00000) where svchost.exe is loaded indicating that svchost.exe was not normally loaded. If you just dump the suspect svchost.exe process and analyze you will be spending time analyzing the legitimate svchost.exe (execpt the 3 instructions which are patched, the rest all are legitimate code). It becomes important to detect the actual malicious code.
The malfind also detected another address 0x60000, even though it doesn’t contain executable but looking at the disassembly it looks like it contains code (where the svchost.exe process execution will be redirected).
Even though malfind is very useful and helped in detecting the suspicious memory regions it is still possible to miss the actual malicious code injected at address 0x60000 (unless the security analyst is aware of this technique). Hollowfind plugin helps in detecting this type of process hollow technique and also it disassembles the address of entry point which can help in detecting such redirection attack technique. In the below screenshot hollowfind plugin detected the invalid exe memory protection and the process path discrepancy, In addition to that the plugin also shows the disassembly of the address of entrypoint, which shows the redirection to the address 0x60000 (using the push and ret instruction)
The plugin also displays similar processes and the suspcious memory regions. In the below screenshot the suspect svchost.exe (pid 3056) process was started by order.exe(pid 3040) and also shows that the address 0x60000 contains code.
d) Example 4: Modifying Kuluoz to be more Evasive (Changing the Memory Protection to PAGE_EXECUTE_WRITECOPY)
From the previous example we saw that Kuluoz was able to divert the analysis but its malicious code was detected because of the suspicious memory protections (PAGE_EXECUTE_READWRITE) if there is a way to change that protection at the same time manage to execute code it can bypass the malfind plugin thereby making it even more stealthier. To test this I modified Kuluoz code to do two things
- Instead of creating svchost.exe in the suspended mode, I created explorer.exe in the suspended mode, the reason is because explorer.exe is normally started by userinit.exe and it terminates itself which means userinit.exe will not be in the process listing (and will not show as parent for explorer.exe). So if malware starts explorer.exe, injects code and terminates itself, it can become hard to tell based on the parent process.
- As mentioned in the analysis of Kuluoz, it maps memory section containing malicious code into the remote process using NtMapViewOfSection with read, write, execute(RWX) permission but if we can map that memory section containing malicious code with PAGE_EXECUTE_WRITECOPY protection we should be able to bypass the malfind plugin but the problem is Microsoft does not support this flag PAGE_EXEXCUTE_WRITECOPY in the memory allocation API’s like VirtualAllocEx as per the documentation(as shown in the screenshot). It turns out that we can set the PAGE_EXECUTE_WRITECOPY protection by using the native api like NtMapViewOfSection, so I modified the Kuluoz code to do that
Below are details of the modification done to kuluoz to make it more evasive.
Kuluoz malwares sample was modified to create explorer.exe in the suspended mode instead of svchost.exe. The explorer.exe was loaded at base address 0x570000 with the PAGE_EXECUTE_WRITECOPY(WCX) protection(because at this point it is normally loaded)
Malware was then allowed to create a section in its own address space, after which it copies the malicious code into the created section and then maps a view of this section in the remote process, at this point instead of allowing the malware to map the section with read, write, execute(RWX) protection (which is constant 0x40), it was modified to map the section with writecopy(WCX) protection by changing the constant value to 0x80. As a result of this memory was allocated in the explorer.exe process at address 0x60000 also the malicious code was copied in that address (this is the code which performs the malicious actions). Notice in the below screenshot the memory protection of the allocated memory is set to write copy (WCX) instead of read, write, execute (RWX)
Malware then creates another section in its own address space and copies the explorer.exe content into the created section and then patches the explorer.exe at the address of entry point, it just modifies 7 bytes (i.e. 3 instructions). It then unmaps the section in the explorer.exe where its executable is loaded (i.e. 0x570000), at this point the explorer.exe is hollowed out
Malware then maps the section (which contains patched explorer.exe) into the remote process (explorer.exe) at the same address 0x570000 with read, write, execute (RWX) protection. The below screenshot shows the mapped memory in the explorer.exe process, also notice the tool no longer shows the full path to the explorer.exe (this is because of hollow process technique).
Malware then resumes the suspended thread as result of that malware executes the code at the address of entry point of explorer.exe which will redirect the control to the malicious code (at address 0x60000) which performs malicious actions and also notice after resuming the thread how the patched explorer.exe is running on the system.
Now to check if the modified memory protection of the memory (where the malicious code is injected) can bypass the malfind plugin, memory image was taken and memory forensics was carried out
The screenshot below shows two instances of explorer.exe running on the system and also notice both explorer.exe parent process could not be determined because they are terminated, so this makes it slightly hard to detect based on the parent process. There are other things that can be used to detect, like looking for multiple instances of explorer.exe running on the system and the creation time of the process.
Running the dlllist plugin (which relies on PEB) shows explorer.exe is loaded at base address 0x570000. Whereas using ldrmodules (which relies on VAD structure) and grepping for that base address does not show the full path to the explorer.exe. This kind of behaviour occurs when the legitimate process executable memory is deallocated and then the memory is re-allocated at the same address, at this point comparing the results from the dlllist plugin (PEB) and ldrmodules plugin (VAD) is giving an indication of hollow process injection. But if you dump the explorer.exe from the memory and analyse it will not give you much because that is not performing the malicious actions, it is just redirecting, and this is a diversion tactic
Running the malfind plugin only detects the suspicious memory allocation at 0x570000 (where explorer.exe is loaded), this time it did not detect the address 0x60000 (where the malicious code is residing), this is because the memory protection was changed to PAGE_EXECUTE_WRITECOPY and malfind does not look for this memory protection. Again this diversion tactic can lead an analyst to dump the explorer.exe and analyse it (but they will be missing on the actual malicious component located at 0x60000 and might be wasting time analyzing the explorer.exe)
The hollowfind plugin is designed to detect this type of evasion, the hollowfind plugin detects suspicious memory protections like malfind plugin apart from that it also detects any memory regions which does not contain PE file but has a memory protection of PAGE_EXECUTE_WRITECOPY. In the below screenshot the hollowfind plugin reports the hollowed process explorer.exe (pid 2588) and it also detected the redirection to the address 0x60000
In the below screenshot the hollowfind plugin also detected the similar processes and the suspicious memory regions, and it also detected the address 0x60000 as suspicous because this address does not contain a PE file but still has a memory protection of PAGE_EXECUTE_WRITECOPY.
e) Example 5: Kronos Process Hollowing (Changing the Memory Protection to PAGE_EXECUTE_WRITECOPY)
Few days back I came across a malware sample called Kronos which performs similar redirection mentioned above, this sample hollows out the explorer.exe process, patches the address of entry point and attempts to redirect execution flow inside an executable which was injected with PAGE_EXECUTE_WRITECOPY protections. While testing this executable the explorer.exe crashed as shown below, but still the memory image was taken for further analysis.
Running the hollowfind plugin on the kronos infected memory image detected the suspicious process and the redirection attempt to the address 0x6f60b at the address of entry point
The plugin also detects suspicious memory region where a PE File was found with PAGE_EXECUTE_WRITECOPY protection but with no memory mapped file.
Inspite of executing Kronos malware mutiple times it crashed explorer.exe, so its not clear if the malware will sucessfully execute if an executable is injected and its protection is modified to PAGE_EXECUTE_WRITECOPY (or there could be a workaround which malware authors are aware, I’m not sure). I tried multiple times but if an executable is injected with PAGE_EXECUTE_WRITECOPY the executable seems to crash, but during the test (as in case of Kuluoz sample) it was detected if a code is injected and the memory protection is modified to PAGE_EXECUTE_WRITECOPY the code executes without any problems. In any case if malware attempts to perform any of these evasive techniques the hollowfind plugin should be able to successfully detect these attacks.
Process Hollowing is a code injection technique which was used to trick the live forensic tools and to blend in with legitimate processes. It looks like the attackers are now using different types of process hollowing not just to blend in but also to remain stealthy, bypass detection, confuse and divert the forensic analysis tools and the security analysts. From an incident response perspective it becomes important to understand the working of such stealth techniques, understanding these techniques will help us in better countering and responding to such malware attacks. The hollowfind plugin was written to detect such techniques, the plugin detects such attacks by finding discrepancy in the VAD and PEB, it also disassembles the address of entry point to detect any redirection attempts and also reports any suspicious memory regions which should help in detecting any injected code.
Download Link: HollowFind Plugin