The Final Curtain for Process Doppelganging: Unmasking the Defender
Note: This blog does not delve deeply into this technique. However, if you want to learn more about it, you can either watch the original video on Process Doppelganging or read some blogs. One that we recommend is the blog written by hasherezade.
Process injection techniques are like the Swiss Army knives of hacking and cybersecurity. They’re methods used to sneak malicious code or software into the memory space of another running process on a computer. Think of it as a digital Trojan horse. These techniques are used by both attackers and security experts, each with different intentions. Understanding process injection techniques is vital in the ever-evolving landscape of cybersecurity, as they remain a pivotal tool in both offensive and defensive digital strategies.
Among various process injection techniques, ‘Process Doppelganging’ was one of the techniques used by attackers to outwit the detection capabilities of security products. There was a time when security products struggled to detect this technique, but those days are now behind us; Security products have made significant advancements in their capacity to detect and thwart it. To be specific, the renowned Windows inbuilt antivirus, Windows Defender, now effectively neutralises this technique. “No need to install additional security products to stop this technique”.
Brief on Process Doppelganging
Sometimes, it’s truly fascinating how attackers and researchers delve deep into their investigations to discover such astonishing techniques. When it was first introduced at the Black Hat 2017 security conference by security researchers Tal Liberman and Eugene Kogan, we came to understand how rarely used components, such as Windows NTFS Transactions, and the old process creation API (NtCreateProcessEx), which now exists for backwards compatibility reasons, can be exploited to create a technique capable of performing fileless code injection while evading detection by security products.
To implement this technique, we first need a basic understanding of Windows NTFS Transactions. NTFS Transactions are relatively lesser-known APIs in Windows, and Microsoft does not strongly recommend their use, possibly hinting at their future availability. Transactional NTFS allows multiple operations to be grouped together and either committed or rolled back as a single unit, ensuring data integrity in the face of unexpected failures. Now, this incredible feature, while heavenly in its design, can sometimes be tempted into mischief, especially when there’s another supporting feature in the shadows – the mysterious, undocumented process loader API known as NtCreateProcessEx.
Steps to Achieve Process Doppelganging
The steps won’t be detailed, but we’ll mention some key APIs that play crucial roles in Process Doppelganging.
The initial steps involve NTFS Transactions.
- Firstly the Transaction object is created using the API NtCreateTransaction.
- Next, the file is opened within the transaction. This marks the file as open for the transaction and also, where the malicious payload will be written later. CreateFileTransactedW API is used for this operation, which functions similarly to the CreateFileW function. The key distinction is that the CreateFileTransactedW function takes in the transaction object created in Step 1 as a parameter.
- Now, the malware payload buffer is written into the transacted file created in Step 2. What’s intriguing is that the file remains within a transaction and isn’t written to the disk yet. As a reminder, in an NTFS transaction, the operation isn’t considered complete until it’s committed. To write the file with the payload buffer to the disk, the operation requires commitment using the API CommitTransaction. However, this is where the clever trick of this technique comes into play; instead of immediately committing the transaction, a section object is created with the help of the transacted file using API NtCreateSection with SEC_IMAGE flag which performs the PE header validation.
Note: Committing the transaction operation might write a file with the malware buffer to the disk which will definitely get scanned by the security products, so the operation is never committed even after creating the section object.
- Once the section object is created, there is no longer a need for the transacted file. Rather than committing the transaction, it is rolled back using the API RollbackTransaction/NtRollbackTransaction. This action completely removes the transacted file with the payload buffer from the system.
At this point, the role of the NTFS transaction is fulfilled. Now, emerging from the shadows comes the ultimate weapon of this technique— the undocumented process loader API known as NtCreateProcessEx.
- NtCreateProcessEx is a legacy process creation API, however, it’s not a modern process creation API. Two cool feature of NtCreateProcessEx that make this technique possible is:
- It accepts the section object from the user mode as a parameter, allowing the attacker to control the section object. The section object created in step 3 is now passed into the API NtCreateProcessEx as a parameter.
Note that the image section object is passed into NtCreateProcessEx to create a new process.
- It creates only the process body and doesn’t create any threads. Attackers can define process parameters; however, defining these parameters can be a bit complex and cumbersome. Also, it’s required to create a new remote thread.
- The previous step only creates the process body. Before creating a new thread within the process body, the process parameters are required and need to be set. And this is done by using API RtlCreateProcessParametersEx.
- After completing all the intricate tasks of setting process parameters, a new remote thread is created, which will then execute the malicious code. The new thread is created using API NtCreateThreadEx. Following is a simple diagram to visualize the technique.
After all the effort, when attempting to run the Process Doppelganging loader, Windows Defender steps in to prevent the execution of the new thread.
NOTE: We are covering more interesting Simulate & Detect scenarios in our CPIA mini-course
Root cause of error code 0xC0000022
In the previous screenshot, as the loader tries to initiate a new thread within the recently created remote process body, it encounters error code 0xC0000022, commonly denoting an ‘ACCESS_DENIED’ issue.
If we reverse the WDFilter.sys filter driver, we can observe a registered callback in the below screenshots. The ‘MpCreateProcessNotifyRoutineEx’ callback routine is registered, and it gets triggered when a new process is created.
If we look at the third parameter of “MpCreateProcessNotifyRoutineEx” it’s the creation info the full structure is in the below screenshot. There we can see two interesting fields:
- FileObject: This contains information about the file that was used to create the section, which was ultimately used to create the process.
- CreationStatus: The NTSTATUS value for process creation status. It can be altered by drivers to transform it into an error code, effectively halting the process creation operation. In the case of the Process Doppelganging loader, this is where Windows Defender steps in, altering the NTSTATUS code as observed.
We conducted an analysis of the ‘MpCreateProcessNotifyRoutineEx’ and observed that it retrieves the file object from the Creation Info structure(_PS_CREATE_NOTIFY_INFO). Subsequently, this file object is passed into the IoGetTransactionParameterBlock function.
IoGetTransactionParameterBlock retrieves the pointer to the _TXN_PARAMETER_BLOCK from the file object which is passed as the parameter into it.
In the following screenshot, we can observe two distinct file objects: one representing a transacted file and the other representing a normal file. When examining the file object of the transacted file, we notice that the ‘FileObjectExtension’ field points to a specific memory address. In contrast, within the normal file object, the ‘FileObjectExtension’ is null. Notably, the ‘FileObjectExtension’ field stores additional information about the file, and for transacted files, the second member at ‘FileObjectExtension’ is ‘_TXN_PARAMETER_BLOCK’ which can be clearly seen in the following screenshot.
If IoGetTransactionParameterBlock locates a non-null pointer to the ‘_TXN_PARAMETER_BLOCK‘, it deduces that the process was created using a transacted file and subsequently modifies the CreationStatus error code to 0xC0000022. This can be clearly seen in the following image.
We can observe how Windows Defender effectively prevents the Process Doppelganging technique from initiating the first new thread in the remote process. Despite the technique being thoroughly thwarted, acquiring knowledge of such a method remains valuable. The transactional file is still employed to create a section and map it to another running process for code injection. Additionally, the approach of creating a process using NtCreateProcessEx continues to be utilized by similar techniques such as Process Herpaderping and Process Ghosting.
Hope you enjoyed reading the detailed analysis. If you are interested in more such interesting Attack Simulation and detection scenarios related to all known Process Injection Techniques.
CWL Team is conducting a 2 day practical webinar, 3 hrs each on 14th & 15th Oct 23. Enrolled candidates will have access to the webinar video recording (downloadable) and will get FREE access to the Certified Process Injection Analyst (CPIA) mini-course which comes with an in-depth recorded videos & multiple interesting exercises along with technical support. Plus, upon successful completion of the on-demand exam at the end, you will receive a CWL verified accredible badge which will boost your profile.
Till then stay tuned !!