Ciarands / eplayers-resolver

Resolver for megacloud's e1 player, rabbitstream's e4 player & rapid-cloud's e6 player.
11 stars 2 forks source link

execute error #2

Closed xiaomin0322 closed 8 months ago

xiaomin0322 commented 9 months ago

import re import json import base64 import hashlib import requests

from Cryptodome.Cipher import AES

from Cryptodome.Util.Padding import unpad

from Crypto.Cipher import AES from Crypto.Util.Padding import unpad

class Resolver:
def calculate_md5(self, input_bytes) -> bytes: return hashlib.md5(input_bytes).digest()

def decode_base64_array(self, encoded_str) -> bytearray:
    return bytearray(base64.b64decode(encoded_str))

def get_player_js(self, player) -> str:
    '''
        Fetches player.

        Returns:
            (str): player content
    '''
    urls = {
        "e1": "https://megacloud.tv/js/player/a/prod/e1-player.min.js",
        "e4": "https://rabbitstream.net/js/player/prod/e4-player.min.js",
        "e6": "https://rapid-cloud.co/js/player/prod/e6-player-v2.min.js",
    }

    req = requests.get(urls[player])
    return req.text

def get_extraction_key(self, script) -> list:
    '''
        Extracts key using regex.

        Returns:
            (list): extraction key
    '''
    switch_body = script[script.rindex('switch'):script.index('partKeyStartPosition')]
    indexes = []

    for match_1 in re.finditer(r':[a-zA-Z0-9]+=([a-zA-Z0-9]+),[a-zA-Z0-9]+=([a-zA-Z0-9]+);', switch_body):
        sub_indexes = []

        for match_2 in [match_1.group(1), match_1.group(2)]:
            regex = re.compile(f'{match_2}=0x([a-zA-Z0-9]+)')
            matches = list(re.finditer(regex, script))
            last_match = matches[-1]

            if not last_match:
                return None

            sub_indexes.append(int(last_match.group(1), 16))

        indexes.append([sub_indexes[0], sub_indexes[1]])

    return indexes

def get_final_key(self, deob_key) -> list:
    '''
        Get final extraction key.

        Returns:
            (list): list of integers to get key
    '''
    current_sum = 0
    final_key = []

    for first_term, second_term in deob_key:
        first_term += current_sum
        current_sum += second_term
        second_term += first_term
        final_key.append([first_term,second_term])

    return final_key

def extract_key(self, encrypted_string, extraction_table) -> tuple:
    '''
        Extracts key from encrypted string.

        Returns:
            (str): decrypted key
            (str): new encrypted string
    '''
    decrypted_key = []
    offset = 0

    for start, end in extraction_table:
        decrypted_key.append(encrypted_string[start - offset:end - offset])
        encrypted_string = (
            encrypted_string[:start - offset] + encrypted_string[end - offset:]
        )
        offset += end - start

    return "".join(decrypted_key), encrypted_string

def generate_encryption_key(self, salt, secret) -> bytes:
    '''
        Generates the original AES encryption key from the salt + secret passsed.

        Returns:
            (bytes): encryption key for use in decrypting data
    '''
    key = self.calculate_md5(secret + salt)
    current_key = key
    while len(current_key) < 48:
        key = self.calculate_md5(key + secret + salt)
        current_key += key
    return current_key

def decrypt_aes_data(self, decryption_key, data) -> str:
    '''
        Uses decryption key to decrypt reformatted data.

        Returns:
            (str): decrypted data bytes decoded as utf-8
    '''
    cipher_data = self.decode_base64_array(data)
    encrypted = cipher_data[16:]
    AES_CBC = AES.new(
        decryption_key[:32], AES.MODE_CBC, iv=decryption_key[32:]
    )
    decrypted_data = unpad(
        AES_CBC.decrypt(encrypted), AES.block_size
    )
    return decrypted_data.decode("utf-8")

def get_cdn(self, encrypted, player) -> dict:
    '''
        Takes encrypted data, uses regex to extract player key, uses that key to decrypt the data.

        Returns:
            (dict): decrypted string loaded as json
    '''
    player = self.get_player_js(player)
    array_key = self.get_extraction_key(player)
    final_key = self.get_final_key(array_key)

    key, new_string = self.extract_key(encrypted, final_key)
    print('key',key)
    print('new_string',new_string)
    decryption_key = self.generate_encryption_key(
        self.decode_base64_array(new_string)[8:16], key.encode("utf-8")
        #self.decode_base64_array(new_string)[8:16], key.encode("utf-8")
    )
    main_decryption = self.decrypt_aes_data(decryption_key, new_string)
    return json.loads(main_decryption)

if name == "main": data = "U2FsdGVkX18txJmpNN62UQkv6MDuc5IVWh4/jrEkwLPl36WYo3SVcgJ6/p8F06JQrcG6d6I6ZwjbCcQLNagKRfEuAj7ZSGAGBxLgA72gp4YGOaPfly2UYJE5A8KWthMbnw6LmDknWHtiJ6Xf8Fr79pzFy4cLR8Fgbg96irqoCauQyTmXd75CTStE+s1vFruR50ICAbT8NQczDXH2l8HM09PHIAiwSVPbFo12QNUt4vtU3lgQ+BBoj5p/Sj343Cbv6ZGrqPVdM6YTTMgdzdjC29iSQP7mATgkz4wwy0laHjRTToJdJrmn1aaVyFSykuQ9B2lByTr3pROc6r0r7XSwBOsAzQ8S+rhhjIl+uIJb/iPH/31LLivc3G04pT1zTHnMmW+bl0OmdSGmMSfNUCIlprMBzqosSfU/rxGDzIKtUEhampSOGYkMfpKC/hQByghHbAPszXklri1TVB4EP8OS82iBsQ1lxinejpwA3rbXxQvIUYJuUr20EWuTK3XwGL6g80McjXCp61v/xZy+g4Q" data = 'U2FsdGM6BU5MGVkX1/X0RdUYwYQSiwRfBlv2NNzpStXZzsLCOqJxhKSMaP0PQZrzxz7QAUq/zC3EKqrLxmJLRSNo4XyZj3qJO3kdXG6uziAwh4bMfpJfhhffQPfBgQBpKoqJLIyvhGulxDPAwK8tIkYYFcaqIolAzmnHZaoZ4MBr5kvgPHE1NMumigUH6ztskSfPOfqrKNzS29rKf5+BVZpxmMnqPRYxny9onDPOMEYmsOjFkdqNE3pVmShSXmSq7iXwKs9mntBhCzNdgRTCapzdR0ZuGRkR7otp3ZSkEItnKDdzrQACE4zc9tLcTrTWysMCDUNdZ6ZOEQbd76LQUgRx/XCze3tHW2kVd97UGkLx6SmgHti8tX/9PjvkaVWrh6kI3R1jyR3BDQuXq34Wcx6nrs/zEqmidNj2Q5TThGgPTlH9z1wUbK2yBvBBUC4xodRW9MPOui1HYuuoIvkDIKWVNrAN6KtFuJab/OehJj45WK6KUPxg6zmBZCmfBlvgV9Q8glL2xj3fzLk3bQAWrJZpyOuIcA2pG3a4UKQeQHFO84G' player_type = "e1"

print(Resolver().get_cdn(data, player_type))

key GVkX1/XzsLCOqaP0PQZlxDPAwIolAzm1NMumigUH6ztsf5+BVZ new_string U2FsdGM6BU5M0RdUYwYQSiwRfBlv2NNzpStXZJxhKSMrzxz7QAUq/zC3EKqrLxmJLRSNo4XyZj3qJO3kdXG6uziAwh4bMfpJfhhffQPfBgQBpKoqJLIyvhGuK8tIkYYFcaqnHZaoZ4MBr5kvgPHEkSfPOfqrKNzS29rKpxmMnqPRYxny9onDPOMEYmsOjFkdqNE3pVmShSXmSq7iXwKs9mntBhCzNdgRTCapzdR0ZuGRkR7otp3ZSkEItnKDdzrQACE4zc9tLcTrTWysMCDUNdZ6ZOEQbd76LQUgRx/XCze3tHW2kVd97UGkLx6SmgHti8tX/9PjvkaVWrh6kI3R1jyR3BDQuXq34Wcx6nrs/zEqmidNj2Q5TThGgPTlH9z1wUbK2yBvBBUC4xodRW9MPOui1HYuuoIvkDIKWVNrAN6KtFuJab/OehJj45WK6KUPxg6zmBZCmfBlvgV9Q8glL2xj3fzLk3bQAWrJZpyOuIcA2pG3a4UKQeQHFO84G Traceback (most recent call last): File "c:\workspace-python\my_hook\myflixerz\resolver.py", line 166, in print(Resolver().get_cdn(data, player_type)) File "c:\workspace-python\my_hook\myflixerz\resolver.py", line 155, in get_cdn self.decode_base64_array(new_string)[8:16], key.encode("utf-8") File "c:\workspace-python\my_hook\myflixerz\resolver.py", line 19, in decode_base64_array return bytearray(base64.b64decode(encoded_str)) File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.3056.0_x64__qbz5n2kfra8p0\lib\base64.py", line 87, in b64decode return binascii.a2b_base64(s) binascii.Error: Invalid base64-encoded string: number of data characters (509) cannot be 1 more than a multiple of 4

Ciarands commented 9 months ago

this error would indicate that either the data you passed is stale (cannot use the latest decryption key) or the player_type is incorrect (wrong decryption key), please double check that the data you're passing is up-to-date and you are using the correct player type

Ciarands commented 8 months ago

No update, closing issue.