Simple Loader (Execution Guardrails)
This is a Simple Loader that demonstrates a way to implement execution guardrails, using an environment-derived key, in a DLL loader.
Project Files
NOTES
This is a slightly more involved example, but it's something I really wanted to bring into Tradecraft Garden. I didn't get around to elegantly bringing Execution Guardrails into Cobalt Strike during my run, and that's partially because I felt they belonged in the loader, and I didn't have this kind of technology to do so in a maintainable way. But, I believe in Execution Guardrails as a FUNDAMENTAL GOOD in a safe and professional red team operation. The benefits include:
- Positive control - If your agent lands somewhere it shouldn't, it's rendered inert.
- Obfuscating client information - Red Team C2 payloads LEAK information about your red team operation and, sometimes, your client's environment. Execution Guardrails using environment-derived crpytographic keys are a layer of obfuscation to slow recovery of this information.
- Evasion - Execution guardrails can frustrate sandboxing analysis, making it harder to examine your payload's behavior from a sample.
Making our DLL loaders modular
First, you'll notice this project is split into two specification files. The stage1.spec file sets up our initial position-independent code. This code is responsible for running a guardrail COFF and if it's successful, passing execution to a (now decrypted) stage 2. run "stage2.spec"
processes the stage2.spec file, with the same $VARs
and target as its parent file. This is a way to split up complex builds.
The stage2.spec is a more normal looking spec, similar to our Simple Loader spec. But, there's one twist. Our stage 2 loader is a COFF. One advantage is that it's easier to write loader logic with. But, there's another pragmatic here. When we allocate (or re-use, if we choose) RWX or RX memory for these loading COFFs, we're allocating VERY small amounts. Both the stage 2 loader and guardrail COFFs here require less than one page of eXecutable memory. The data both reference live in another region of memory altogether.
stage2.spec also shows the Crystal Palace import
command to bring "LoadLibraryA, GetProcAddress, VirtualAlloc, VirtualFree" functions into the stage2.x##.o COFFs. The import "a, b, c"
command maps entries in the IMPORTFUNCS struct to function symbols in a COFF. In stage1.c
we've already resolved VirtualAlloc and VirtualFree--there's no need to resolve them again when loading our stage 2.
Execution Guardrails
This implementation of Execution Guardrails encrypts DLLs and other resources with an environment-derived key. There are many possibilities to generate an environment-derived key. That's something that's largely a choice for you to make.
loader.spec uses the prepsum
command to prepend an Adler32 checksum of our DLL data to itself. The next command is rc4 $KEY
to RC4 encrypt the DLL resource with the passed-in key. The last command is preplen
to prepend the length of the ciphertext to itself.
Running this sample will require passing our environment-derived key, ENVKEY=...
, to the ./link command. run.x86.exe and run.x64.exe both print an ENVKEY
that works with this example.
./link stage1.spec demo/test.x64.dll out.bin ENVKEY=0302010003020100
Security vs. Obfuscation
One of the questions I've sat with, is rc4
good enough here? RC4 is an encryption algorithm with known weaknesses. In this context, it's not security for the follow-on data its masking. That's why I've carefully chosen my words and described it as obfuscation--something in place to slow down the recovery of information a follow-on payload might leak. But, I don't see rc4 as the sole problem here. Even if I were to expose other encryption schemes (e.g., AES-CBC 128/256, ChaCha20, etc. are candidates), I believe one would need great care to select environment factors AND a key derivation scheme that yield enough bits of actual randomness before there's any measure of confidentiality in narrow threat model situations. I speculate that it's difficult to achieve a sound confidentiality guarantee with this technique and most attempts would fall short of truly achieving this.
Conversation
- Cobalt Strike: A Cyber Tooling T&E Challenge (DATAWorks, 2024) by Dr. Nathan Wray walks through an analysis of Military OPSEC (e.g., mission and national security, not product evasion) risks from forensic exploitation of Red Team C2 payloads. Military OPSEC evaluation is rarely about finding a conclusive answer. Rather it's evaluating shades of risk, creating awareness for decisions, and it's an opportunity to think about mitigations.
- Execution Guardrails: No One Likes Unintentional Exposure (2024) by Brandon McGrath discusses execution guardails, potential environment keys, and shares some of Brandon's favorite practices and insights in this area.
- Protect Your Payloads: Modern Keying Techniques (DerbyCon, 2018) by Leo Loobek. Discusses the environment keying problem, discusses keying recipes, and introduces Keyring to aid generating environment keys from multiple factors.
- DodgeBox: A deep dive into the updated arsenal of APT41 | Part 1 (2024) by Yin Hong Chang, Sudeep Singh. This report walks through the environment keying approach of an APT41 payload family.
- MITRE ATT&CK T1480 - Execution Guardrails: Environmental Keying lists some real-world uses of environment keying and some ideas you could draw on to design your own environment-keying scheme.
- Choose Your Own Red Team Adventure: Execution Guardrails (2019) by Tim Malcomvetter is a fun yarn of... well... how execution guardrails can frustrate sandbox detonation in some, but not all cases.
License
This project is licensed under the GNU General Public License version 2 (GPLv2) or later..