As we push towards realizing the Cyber Mongol vision of teaming advanced automation with human defenders, it’s exciting to see pieces of our technology come to life from concept. Our most recent concept that went under the lightning rod and brought to life like Mary Shelley’s Frankenstein, was automated adversary behavior tagging. Essentially, any emerging tradecraft that hits our sensors and passes triage, will be automatically defined and categorized by the offensive behavior it represents – example process injection. While it seems common practice in the industry today to elude to the fact that your solution only uses the most advanced neural networks and ML models, that can be incredibly misleading as rule-based Regex is still a major component for effective detections. I’m not saying we don’t use ML within our pipeline, I’m just saying it works synergistically with the other logic to produce results. This blog post is a product of creating a small subset of Regex rule-based logic to detect process injection and I thought it might be helpful to share with the community.
We have been conducting extensive research in process injection, their variations and security solution API hook evasion over the last month. While none of these techniques are new, we are seeing an increased interest within the security community in regard to these vectors, based on our ingested signals. Additionally, these signals represent ways to execute malicious code on endpoints and evade AV/EDR solutions, emphasizing their significance in relation to the cyber Kill Chain. Process Injections, their variants and API hook evasion techniques like direct SYSTEM calls are heavily used by advanced actors such as nation states, criminal syndicates and hacktivists. I wanted to share a high-level overview of a few process injection variants and the common API calls they make. This post is not meant to be a deep technical dive into the internal workings of process injection, but to possibly aid in the comprehension of the technique to the unfamiliar, and enumerate some of the functions (common and uncommon) that we see being utilized for this tradecraft. Knowing which API calls are in vogue and may represent malicious activity, can definitely strengthen a threat hunting initiative.
So, what is a process injection? Process injections attempt to run arbitrary code in the memory space of targeted processes, executing malicious code that can evade endpoint protections. At the most basic level (and most well-known), a process injection works by getting access to a target process with the OpenProcess function, allocating memory within the process with VirtualAllocEx, writing malicious code to the allocated memory space with WriteProcessMemory, and then finally executing the malicious code with CreateRemoteThread. Alternatively, instead of opening an already existing process, an operator may choose to spawn a new process and inject malicious code into that process’s memory space with the CreateProcess function. These API’s are well known to be heavily exploited by injection techniques, and as such, security venders monitor (or hook) these functions so that they can inspect the code being executed. These security hooks (or inspections) happen in what’s called Userland (code that runs outside of the OS kernel) and can be bypassed with various techniques , . Additionally, there are different variations of process injection – Process Hollowing and Process Doppelganging are two variation examples.
Process Hollowing substitutes the memory space of a remote process with operator-controlled memory. This is achieved by creating a process in a suspended state with CreateProcess(CREATE_SUSPENDED), deallocating (hollowing) the suspended process’s memory space with NtUnmapViewOfSection, allocating memory for malicious use with VirtualAllocEx, write the malicious PE (portable executable) sections (data, text, etc…) to the newly allocated memory addresses with WriteProcessMemory, point the EAX register to the correct position in the text section by using SetThreadContext and finally, execution is achieved once the process is re-started with ResumeThread. This technique’s goal is to hide the execution of malicious code within a benign process.
Process Doppelganging looks to achieve execution of malicious code in the context of a legitimate process, use none of the suspicious API calls used in Process Hollowing (NtUnmapViewOfSection, VirtualProtectEx, SetThreadContext), to have the antivirus only scan clean files and to remain hidden from advanced forensic tools. A Doppelganger has 4 steps which are needed to successfully execute this type of injection. It needs to overwrite a legitimate executable with a malicious one (Transact), it needs to load a malicious executable (load), it needs to roll back to the original executable (rollback), and it needs to bring the Doppelganger to life (animate). The Transact step uses multiple Transactional NTFS functions to accomplish its goal. The CreateTransaction function will create an initial transaction, the CreateFileTransacted function is used to open a clean file (example svchost.exe) within the transaction and lastly, the clean file meant to evade endpoint protections will be overwritten with malicious code using the WriteFile function. Anything trying to inspect the file will not see the changes that have been made as they have occurred within the transaction, and the inspection is taking place outside of that transaction’s context. Additionally, after the rollback phase (which completes the NTFS transaction), the file will be reverted to its original clean state. The load phase will create a section object (a buffer of sorts) from the transacted file (svchost.exe) that points to a malicious executable with NtCreateSection. The Rollback step simply rolls back the changes made to the file system with RollbackTransaction but leaves the malicious section object that is pointing to the evil executable, intact. In the final step, the technique needs to create a process from this malicious section with NtCreateProcessEx(Process,..Section) which looks legitimate but runs malicious code inside of it, create a thread to the process using NtCreateThreadEx , create process parameters, copy parameters to the newly created process’s address space and start the Doppelganger’s execution using NtResumeThread.
Even if endpoint protections are bypassed with some of the techniques mentioned above, it still may be possible to enumerate suspicious API usage if you know what you are looking for – example ProcMon . Some EDR vendors also offer advanced hunting queries that may also be used to assist in locating malicious API calls.
At Cyber Mongol, we are in the business of forecasting and articulating trends in emerging adversary behaviors. One important aspect of behavior forecasting is ground truthing some of the emerging signals we see being articulated by our CTI engine. Over the last year, it has become increasingly more difficult to execute and evade on a Windows 10 endpoint, with off-the-shelf tooling. Being able to pull-off sophisticated operator tactics, with little to no modification to the underlying tradecraft, is important to our research because it signals to the likelihood an enterprise may encounter this vector. An effective technique to skirt modern defenses and achieve execution with just the knowledge of what tool systems to string together is quite advantageous for adversaries. Unsophisticated adversaries will utilize this knowledge for the obvious reason of reducing the associated skill barrier with an otherwise advanced technique that may not be otherwise accessible. Sophisticated adversaries may also utilize this same knowledge to mimic unsophisticated adversaries and make attribution more difficult. In this research, we string together tools that have been signaled by our CTI engine to get a Covenant C2 grunt (implant) to execute on a Win10E 1909 endpoint and bypass standard defenses in the Enterprise stack.
The Tools: Covenant C2
Covenant C2 is a .NET command and control framework that aims to highlight the attack surface of .NET, make the use of offensive .NET tradecraft easier, and serve as a collaborative command and control platform for red teamers . This opensource project is connected to one of the most influential development clusters associated with offensive .NET tradecraft. The efficacy of emerging tool systems can also be judged by other tool systems connected to the same development cluster. In this case, this tool walks among gods with the likes of Empire , Bloodhound  and Impacket  associated to the cluster
The Tools: donut
Donut creates position-independent shellcode that loads .NET assemblies. This is a massive topic domain in itself and a great place to start, is to read the Wover’s blog post  which is a primer on the tool and .NET tradecraft. For this discussion, it will suffice just to know this tool enables us to take Covenant’s binary launcher(.exe) and create shellcode that will inject into a suspended process’s memory and gain execution while evading defenses. This is actually quite important tradecraft when operating with Covenant C2 as the framework does not possess the ability to generate shellcode natively, which is needed for more advanced attacks like process injection.
The Tools: defcon27 Talk
Our sensors picked up chatter mid 2019 regarding a talk at defcon entitled “Writing custom backdoor payloads with C# ”. The resources surrounding this talk (lab guide and source code) are incredibly great to learn these advanced techniques from. They also make it fairly easy for an operator possessing an intermediate skillset to implement sophisticated tactics – provided they know how to slightly modify the vector articulated in the talk.
Technique: Process Hollowing (T1093)
Process hollowing occurs when a process is created in a suspended state then its memory is unmapped and replaced with malicious code. Similar to process Injection, execution of the malicious code is masked under a legitimate process and may evade defenses and detection analysis . Examples of advanced adversaries and tool systems that utilize process hollowing are Gorgon Group , Cobalt Strike  and Smoke Loader .
Stringing It All Together
As stated above, the whole point of this exercise is to get a Covenant Grunt executed on a Windows 10 endpoint, without tripping defenses. It would stand to reason that the first step would then be to setup a Covenant C2 infrastructure as per your needs.