In the previous article https://8ksec.io/dissecting-windows-malware-series-beginner-to-advanced-part-1/, we introduced the components of Malware Analysis: Basic Static, Advanced Static, Basic Dynamic, Advanced Dynamic – then, we delved into the analysis of a malware sample that was presented.
The analysis revealed the exploitation of the AppInitDLLs mechanism for persistence, the addition of the attacker’s email address to every outgoing email from the endpoint, and the use of a User-Space Rootkit to continue operating and evade detection.
We stand by our concluding statement from the previous article: “Anyone who truly feels a passion for the field of Malware Analysis can do it, and do it big time!”
As they say: “Practice Makes Perfect!”
If you’ve stayed with us until now, you probably really like it – Let’s get started!
Table of Contents
What's In It For Me❓
This article will review the differences between Process Injection and Process Hollowing, and briefly introduces other injection techniques.
Following this, we will analyze two malware samples: the first showcases Process Injection alongside an innovative persistence mechanism that we found particularly effective; the second employs Process Hollowing.
How Does It Look From Above❓
Revisiting the ‘Super-Categories’ mentioned in the previous article:
- Persistance
- Evasion
When talking about Process Injection and Process Hollowing we can classify both of them under: Evasion and Privilege Escalation – This in turn, makes this technique very attractive among attackers.
A Side Note
There are other ‘Super-Categories’, such as Spread/Movement, which most malware implement in some form. For now, we’ll focus on the mentioned categories.
A Bit Of Theory Before We Start📚
Process Injection, as the name suggests, is a technique for “injecting” (writing) malicious code into another running process.
As a result, the injected process executes the malicious code as if it were its own.
This method is often used by attackers to achieve evasion because the average user will simply see a legitimate process running on their endpoint.
Furthermore, the combination of sophisticated malware and inadequate security measures at the endpoint, allows the attacker to bypass certain antivirus engines and various configurations of security measures at different endpoints.
Process Hollowing, also known as Process Replacement, is essentially a sub-technique of Process Injection. Unlike straightforward injection, Process Hollowing begins with an “Unmap” operation that removes the legitimate code of an existing process (hence the term “Hollow” – implying the removal of existing code content).
Then, malicious code is overwritten in its place.
There are numerous methods to implement Process Injection, including but not limited to:
DLL Injection
PE Injection
APC Injection
Process Doppelgänging
and much more…
Characteristics of Process Injections
All the sub-techniques, including Process Hollowing, contain certain characteristic elements that are common to all Injections – since they are all sub-methods for implementing Process Injection.
In most cases, we will observe calls to the following Windows API functions: VirtualAllocEx and WriteProcessMemory, whose purpose is to alter the memory in the address space of another process.
Additionally, it is likely that we will see some combination of calls to the following API functions:
CreateRemoteThread
SuspendThread
SetThreadContext
ResumeThread
QueueUserAPC
NtQueueApcThread
Note the phrasing ‘in most cases‘ and ‘likely‘ because:
‘Likely’ – because there are various and diverse malware out there that can be implemented in different and varied ways, so we should not be rigid and we’ll need to examine each case on its own.
‘In most cases’ – because the malware sample we’ll see soon, implements Process Injection, and it precisely does not use these Windows API functions😉.
Let's Start Reversing🤩
Process Hollowing
In the generic implementation, a call will be made to certain Windows API functions, which we will review now.
In many cases, the malware will perform obfuscation/encoding and additional methods to disguise the process, making the identification of Process Hollowing more complex.
A small clarification: from previous analysis, we discovered that the process targeted for Process Hollowing is svchost.exe.
Process Enumeration
We identified this through the enumeration of Process IDs (PIDs) that the malware performs in search of the target process.
The malware compares the value of the ‘ecx’ register to the Process ID, and when the processId parameter is the one of svchost.exe we call the function sub_401000.
Unmapping Process Memory
First, the malware initiates a new process via CreateProcess, intended as a ‘container’ for the malicious code in suspended mode (illustrated by passing the parameter 0x4 to achieve this state).
The process’s main thread is created in suspended mode and remains inactive until ResumeThread is called.
Subsequently, GetThreadContext retrieves the relevant thread’s context for modification.
Following memory release by either ZwUnmapViewOfSection or NtUnmapViewOfSection, VirtualAllocEx allocates new memory for the malicious code.
WriteProcessMemory then writes the malware’s sections to the target process, and SetThreadContext updates the entry point to the newly written malicious code.
Finally, ResumeThread transitions the process from suspended to active mode.
A Side Note
While a direct call to NtUnmapViewOfSection isn’t explicitly observed, IDA Pro identifies a reference to this function, which is confirmed through dynamic linking at address 0x00401206, as verified using the debugger OllDbg.
It’s crucial to perform this analysis because sophisticated attackers aim to mislead researchers, attempting to obscure the true functionality and objectives of the malware.
Their goal is often to ensure the malware’s persistence on the host system or to conceal additional malicious features.
Executing the malware and setting a breakpoint at the specified address confirms our hypothesis, as illustrated in the image below:
Process Injection - Generic Implementation And A Small Surprise 🔬
First, we’ll summarize our findings from the initial stages of this investigation, which is separate from the analysis of the previous file.
These findings guided our hypotheses and investigative direction. We discovered attempts by the malware to locate the ‘winlogo.exe‘ process.
Additionally, during the Basic Static Analysis phase, we identified the presence of the ‘CreateRemoteThread‘ string, suggesting potential process injection into ‘winlogo.exe’.
We aim to confirm this hypothesis.
In cases of straightforward process injection, we typically observe the following sequence:
VirtualAllocEx: Allocates memory within the target (host) process for injection.
WriteProcessMemory: Writes the malicious code into the allocated memory.
Execution is initiated using one of the following methods: CreateRemoteThread, NtCreateThreadEx, RtlCreateUserThread, or direct Shellcode execution.
A Bit Of Low-Level Theory📚
Technically, the address of LoadLibrary, which contains the address of the library where the malicious code is located, is passed to one of these API functions, enabling the remote thread to write and execute the malicious code.
It’s worth noting that CreateRemoteThread usage implies the existence of a malicious DLL at the endpoint.
Given that many security mechanisms can detect such DLLs, and thus attackers may opt for less detectable methods.
Upon examining the assembly code, we observed several noteworthy function calls but, curiously, found no trace of WriteProcessMemory as expected.
This anomaly requires further investigation. At the begging of the code, we see a call to sub_4010FC, where SeDebugPrivilege is passed as a parameter, indicating an attempt to perform Privilege Escalation.
Privilege Escalation And Windows Security💾
In short, User-Space processes cannot arbitrarily access resources or invoke functions such as TerminateProcess or CreateRemoteThread on other processes.
Various types of malware attempt to gain access to these restricted functions by modifying the settings of the Access Token.
An Access Token is an object that contains a Security Descriptor about a process, essentially outlining the process’s access permissions.
This token can be modified by calling AdjustTokenPrivileges.
SeDebugPrivilege, initially intended for System-Level debugging, is often exploited by attackers to secure elevated access permissions for System-Level processes.
In our case the process initiates a call to LoadLibrary for the ‘dynamic linking’ of the sfc_os.dll library, followed by a call to GetProcAddress.
Unlike previous instances where calls were made by name, this call utilizes an Ordinal (‘serial number’ for imports) with the value 2.
The critical call to CreateRemoteThread is executed with specific parameters: hProcess, placed in the edx register, serves as a Handle.
Accessing Processes or other resources is done through returning a Handle after running functions and using them onwards in the following calls.
In our case, the handle is associated with the winlogon.exe process.
The lpStartAddress parameter points to the Ordinal of the function within sfc_os.dll – This is the actual address of the function that will inject a thread into winlogon.exe.
Here Comes The Interesting Catch🎇
Through research on Google regarding sfc_os.dll and its ‘Ordinal 2’ function, SfcTerminateWatcherThread, we discover that this library is already loaded into the process winlogon.exe!
This is why, the malware doesn’t need to load this DLL to create a Remote Thread, which intriguingly explains the absence of any WriteProcessMemory calls— a remarkable find!
sfc_os.dll plays a critical role, among others, in overseeing the Windows File Protection (WFP) mechanism and operates multiple threads within winlogon.exe.
The SfcTerminateWatcherThread function is capable of modifying protected Windows files, which are usually secured with robust permissions.
Our analysis shows that the malware accesses the winlogon.exe process with PROCESS_ALL_ACCESS permissions (this is shown in the image below and verified through MSDN documentation on OpenProcess with the value 0x1F0FFF).
It then injects a Remote Thread into winlogon.exe that invokes SfcTerminateWatcherThread from sfc_os.dll, effectively carrying out Process Injection.
By executing SfcTerminateWatcherThread, the malware temporarily disables the WFP mechanism until the system is rebooted.
The Cherry On Top🍒
After the injection is performed, even more interesting events occur:
-
The malware calls functions that perform resource manipulation, as observed in the Basic Static Analysis stage (calls to FindResource, LoadResource, among others).
-
It then extracts a file stored in the resource section of the current malware, which replaces the legitimate system file located at C:\Windows\System32\wupdmgr.exe.
What actually happens is that the malware renames the legitimate file to winup.exe and uses the MoveFile function to transfer it to the Temp directory.
Meanwhile, the malicious file (bearing the legitimate name) is written to the original path: C:\Windows\System32
Note: The fact that the malware can initially create a new Windows Update Handler is solely due to the disabling action on the Windows Update File (WPF) observed earlier. Under any other circumstances, the system would recognize the file as altered and would attempt to overwrite it with the original file
The malware then downloads another malware file using a call to URLDownloadToFile, essentially performing an update to itself!
It achieves Persistence in the following manner: Initially, it allows a legitimate run of the original file, wupdmgr.exe, so that if a user attempts to perform a Windows Update, the process will proceed as expected. The malware then trojanizes the wupdmgr.exe file by:
Injecting a process into winlogon.exe.
Disabling the WFP (Windows File Protection) mechanism.
During this process, malicious code is injected into wupdmgr.exe.
The malicious code executes the original wupdmgr.exe file to avoid detection by the user (For Evasion).
Subsequently, the malware downloads the Updater.exe file, saving it as wupdmgrd.exe to implement its functionality (we do not possess this file and, therefore, cannot analyze it).
This way the malware achieves whole 3 objectives of:
Persistance
Evasion
Privilege Escalation since it acquires the elevated permissions of the injected process.
So What Have We Seen😎
This article included several aspects. On one hand, we explored the differences in the assembly code between process injection and process hollowing.
On the other, we linked each implementation to another point, showcasing connections and insights.
The implementation of Privilege escalation was explained very concisely. However, there is much more to discuss on this subject, both in the context of the malware sample we analyzed and in the broader context of many malware out there. We’ll return to this topic in future writings.
The Windows File Protection (WFP) mechanism, an old security feature mainly used in Windows XP and Windows 2000 operating systems, was also discussed.
While newer operating systems are immune to this particular vulnerability, it doesn’t mean we won’t encounter similar attacks in the future targeting different or analogous mechanisms in Windows.
Hence, understanding this attack process is beneficial.
We mentioned several injection techniques without going into detail, for a few reasons:
Each injection technique is complex, deserving its own detailed article to truly understand how they differ from each other in assembly code.
Additionally, we’ve included a few valuable links in the reference category for those interested in delving deeper.
In this pair of articles, we’ve covered a lot of ground, including persistence mechanisms implemented using AppInit_DLLs, a persistence mechanism using a launcher that downloads additional malware, a straightforward process injection with a twist, and a user-space rootkit implemented using inline hooking.
That’s quite a comprehensive list, and there’s more to explore moving forward!
What's Next😏
Since we already discussed the major objectives of malware, we are going to explore the realm of Data Encoding!
We’ll see the various data encoding mechanisms malware use to encrypt various components of their functionality – Code, Strings and much more!
Understanding Data Encoding will help us when we dive deeper to the realm of Unpacking Malware.
Once again, keep learning and Have Fun Reversing!
References
The Malware Sample is taken from an amazing book called:
Practical Malware Analysis By Michael Sikorski and Andrew Honig
If you’re interested in learning more about various injection methods and would like to see some cool illustrations of each, refer to the following link:
In addition, the following images:
The Process Injection VS Process Hollowing
The various types of Process Injections
Are taken from this resource link.
For those unfamiliar with the MITRE ATT&CK framework, it is essentially a comprehensive and well-structured knowledge base.
It includes various attack methods, strategies for identification and mitigation, characteristics of different attack groups (including APTs), presentations of the Cyber Kill Chain for different attacks, and much more!
I highly recommend visiting and exploring the site. Have fun!