gablilli commited on
Commit
45d0424
·
verified ·
1 Parent(s): 844453f

fix: broken key parser

Browse files
Files changed (1) hide show
  1. providers/src/bsmart/crypto.js +47 -10
providers/src/bsmart/crypto.js CHANGED
@@ -2,6 +2,34 @@ import fetch from 'node-fetch';
2
  import msgpack from 'msgpack-lite';
3
  import aesjs from 'aes-js';
4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  /**
6
  * Fetches the encryption key from the bSmart website
7
  * @returns {Promise<Buffer>} The encryption key
@@ -9,15 +37,24 @@ import aesjs from 'aes-js';
9
  export async function fetchEncryptionKey() {
10
  const page = await fetch('https://my.bsmart.it/');
11
  const text = await page.text();
12
- const script = text.match(/<script src="(\/scripts\/.*.min.js)">/)[1];
13
- const scriptText = await fetch('https://my.bsmart.it' + script).then(res => res.text());
14
- let keyScript = scriptText.slice(scriptText.indexOf('var i=String.fromCharCode'));
15
- keyScript = keyScript.slice(0, keyScript.indexOf('()'));
16
- const sourceCharacters = keyScript.match(/var i=String.fromCharCode\((((\d+),)+(\d+))\)/)[1].split(',').map(e => parseInt(e)).map(e => String.fromCharCode(e));
17
- const map = keyScript.match(/i\[\d+\]/g).map(e => parseInt(e.slice(2, -1)));
18
- const snippet = map.map(e => sourceCharacters[e]).join('');
19
- const key = Buffer.from(snippet.match(/'((?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?)'/)[1], 'base64');
20
- return key;
 
 
 
 
 
 
 
 
 
21
  }
22
 
23
  /**
@@ -52,4 +89,4 @@ export async function decryptFile(file, key) {
52
  reject({ e, file });
53
  }
54
  });
55
- }
 
2
  import msgpack from 'msgpack-lite';
3
  import aesjs from 'aes-js';
4
 
5
+ function extractBase64Key(snippet) {
6
+ const keyMatch = snippet.match(/['"]((?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?)['"]/);
7
+ return keyMatch ? Buffer.from(keyMatch[1], 'base64') : null;
8
+ }
9
+
10
+ function extractConstructorKey(scriptText) {
11
+ const constructorMatch = scriptText.match(
12
+ /var\s+([A-Za-z_$][\w$]*)=String\.fromCharCode\(([^)]*)\),([A-Za-z_$][\w$]*)=["']constructor["'];\3\[\3\]\[\3\]\((.*?)\)\(\)/s
13
+ );
14
+ if (!constructorMatch) {
15
+ return null;
16
+ }
17
+
18
+ const [, charVar, charCodes, , expression] = constructorMatch;
19
+ const sourceCharacters = charCodes
20
+ .split(',')
21
+ .map(e => parseInt(e.trim(), 10))
22
+ .map(e => String.fromCharCode(e));
23
+ const indexPattern = new RegExp(`${charVar}\\[(\\d+)\\]`, 'g');
24
+ const indexes = [...expression.matchAll(indexPattern)].map(match => parseInt(match[1], 10));
25
+ if (indexes.length === 0) {
26
+ return null;
27
+ }
28
+
29
+ const snippet = indexes.map(index => sourceCharacters[index]).join('');
30
+ return extractBase64Key(snippet);
31
+ }
32
+
33
  /**
34
  * Fetches the encryption key from the bSmart website
35
  * @returns {Promise<Buffer>} The encryption key
 
37
  export async function fetchEncryptionKey() {
38
  const page = await fetch('https://my.bsmart.it/');
39
  const text = await page.text();
40
+
41
+ const scripts = [...text.matchAll(/<script[^>]+src="([^"]+\.js[^"]*)"[^>]*>/g)]
42
+ .map(match => match[1])
43
+ .filter(src => src.startsWith('/'));
44
+
45
+ if (scripts.length === 0) {
46
+ throw new Error('No JavaScript bundles found on https://my.bsmart.it/');
47
+ }
48
+
49
+ for (const script of scripts) {
50
+ const scriptText = await fetch('https://my.bsmart.it' + script).then(res => res.text());
51
+ const key = extractConstructorKey(scriptText);
52
+ if (key) {
53
+ return key;
54
+ }
55
+ }
56
+
57
+ throw new Error('Unable to extract the bSmart encryption key from the current website bundles.');
58
  }
59
 
60
  /**
 
89
  reject({ e, file });
90
  }
91
  });
92
+ }