add upcloud key extractor

Co-authored-by: William Oldham <github@binaryoverload.co.uk>
This commit is contained in:
mrjvs 2023-11-07 20:51:39 +01:00
parent 00134c1487
commit 5dee60c69a
1 changed files with 41 additions and 11 deletions

View File

@ -24,6 +24,34 @@ function isJSON(json: string) {
}
}
/*
example script segment:
switch(I9){case 0x0:II=X,IM=t;break;case 0x1:II=b,IM=D;break;case 0x2:II=x,IM=f;break;case 0x3:II=S,IM=j;break;case 0x4:II=U,IM=G;break;case 0x5:II=partKeyStartPosition_5,IM=partKeyLength_5;}
*/
function extractKey(script: string): [number, number][] | null {
const startOfSwitch = script.lastIndexOf('switch');
const endOfCases = script.indexOf('partKeyStartPosition');
const switchBody = script.slice(startOfSwitch, endOfCases);
const nums: [number, number][] = [];
const matches = switchBody.matchAll(/:[a-zA-Z]+=([a-zA-Z]+),[a-zA-Z]+=([a-zA-Z]+);/g);
for (const match of matches) {
const innerNumbers: number[] = [];
for (const varMatch of [match[1], match[2]]) {
const regex = new RegExp(`${varMatch}=0x([a-zA-Z0-9]+)`, 'g');
const varMatches = [...script.matchAll(regex)];
const lastMatch = varMatches[varMatches.length - 1];
if (!lastMatch) return null;
const number = parseInt(lastMatch[1], 16);
innerNumbers.push(number);
}
nums.push([innerNumbers[0], innerNumbers[1]]);
}
return nums;
}
export const upcloudScraper = makeEmbed({
id: 'upcloud',
name: 'UpCloud',
@ -45,20 +73,22 @@ export const upcloudScraper = makeEmbed({
let sources: { file: string; type: string } | null = null;
if (!isJSON(streamRes.sources)) {
const decryptionKey = JSON.parse(
await ctx.proxiedFetcher<string>(`https://raw.githubusercontent.com/enimax-anime/key/e4/key.txt`),
) as [number, number][];
const scriptJs = await ctx.proxiedFetcher<string>(`https://rabbitstream.net/js/player/prod/e4-player.min.js`);
const decryptionKey = extractKey(scriptJs);
if (!decryptionKey) throw new Error('Key extraction failed');
let extractedKey = '';
const sourcesArray = streamRes.sources.split('');
for (const index of decryptionKey) {
for (let i: number = index[0]; i < index[1]; i += 1) {
extractedKey += streamRes.sources[i];
sourcesArray[i] = '';
}
}
let strippedSources = streamRes.sources;
let totalledOffset = 0;
decryptionKey.forEach(([a, b]) => {
const start = a + totalledOffset;
const end = start + b;
extractedKey += streamRes.sources.slice(start, end);
strippedSources = strippedSources.replace(streamRes.sources.substring(start, end), '');
totalledOffset += b;
});
const decryptedStream = AES.decrypt(sourcesArray.join(''), extractedKey).toString(enc.Utf8);
const decryptedStream = AES.decrypt(strippedSources, extractedKey).toString(enc.Utf8);
const parsedStream = JSON.parse(decryptedStream)[0];
if (!parsedStream) throw new Error('No stream found');
sources = parsedStream;