Dolls Division / 浩劫前线 & 三国:战地美人 / Thrones and Beauties 解密相关

为便于各位佬分析这里提供一下下载器的源码

import os
import shutil
from xxhash import xxh32
from hashlib import md5 as cmd5
import itertools
import requests
import json
proxyaddr = useproxy = 0
def zgzddownloader(overwrite):
    def Get_Hash_Name(string: str) -> str:
        b = string.encode()
        s = xxh32(b).hexdigest() + cmd5(b).hexdigest()
        return s.upper()

    SIGN = b'zbobv1'

    def ror(value, n):
        n %= 8
        return ((value >> n) | (value << (8 - n))) & 0xFF

    def dec(data: bytearray) -> bytes:
        if not data.endswith(SIGN):
            return bytes(data)
        return bytes([
            ror(data_byte ^ key_byte, key_index + 1)
            for data_byte, (key_index, key_byte) in zip(
                data[:-len(SIGN)],
                itertools.cycle(enumerate(bytes([0x78, 0x21, 0x7A, 0x40, 0x6F, 0x23, 0x62, 0x24])))
            )
        ])

    def decrypt_file(filepath):
        try:
            with open(filepath, 'rb') as f:
                data = bytearray(f.read())
            return dec(data)
        except Exception as e:
            print(f"读取或解密失败: {filepath},错误: {e}")
            return None

    def decrypt_folder(root_folder):
        for root, dirs, files in os.walk(root_folder):
            for file in files:
                full_path = os.path.join(root, file)
                try:
                    with open(full_path, 'rb') as f:
                        data = bytearray(f.read())
                    new_data = dec(data)
                    if new_data != data:
                        with open(full_path, 'wb') as f:
                            f.write(new_data)
                        print(f"已解密: {full_path}")
                    else:
                        print(f"跳过未加密文件: {full_path}")
                except Exception as e:
                    print(f"处理文件失败: {full_path},错误:{e}")

    manifest_url = "https://cdn.gamezdjsmr.net/images/download_res/Android/proj.manifest"
    response = requests.get(manifest_url)
    response.raise_for_status()
    manifest = response.json()

    base_url = manifest.get("packageUrl", "https://cdn.gamezdjsmr.net/images/download_res/Android/")
    assets = manifest.get("assets", {})

    lines = []
    for path in assets:
        filename = path.split('/')[-1]
        full_url = base_url + path
        if (not os.path.exists(os.path.join("resdownload", "thrones-and-beauties", "download", filename))) or overwrite:
            lines.append(f"{full_url}\n   out=download/{filename}")

    with open("thrones-and-beauties.txt", "w", encoding="utf-8") as f:
        f.write("\n".join(lines))

    print("主资源链接已写入 thrones-and-beauties.txt")
    os.system(f"aria2c -i thrones-and-beauties.txt -j 32 -s 16 -x 16 --auto-file-renaming=false {f'{proxyaddr} ' if useproxy else ''}{'--allow-overwrite=true ' if overwrite else ''}--check-certificate=false --dir=resdownload/thrones-and-beauties")

    filelistname = Get_Hash_Name('extra_res3.json')
    filelistpath = f"resdownload/thrones-and-beauties/download/{filelistname}"

    if not os.path.exists(filelistpath):
        print(f"未找到 extra_res3.json 加密文件: {filelistpath}")
        return

    raw_data = decrypt_file(filelistpath)
    if raw_data is None:
        print("extra_res3.json 解密失败")
        return

    try:
        filelistdata = json.loads(raw_data)
    except Exception as e:
        print(f"extra_res3.json 解析失败: {e}")
        return

    extra_lines = []
    for group_path, files in filelistdata.items():
        for filepath in files:
            hashed = Get_Hash_Name(filepath)
            local_path = os.path.join("resdownload", "thrones-and-beauties", "download", hashed)

            if not os.path.exists(local_path):
                print(f"未找到源文件: {local_path}")
                subfolder = hashed[0]
                extra_url = f"https://cdn.gamezdjsmr.net/images/extra_res/Android/{subfolder}/{hashed}"
                extra_lines.append(f"{extra_url}\n   out=download/{hashed}")
            else:
                print(f"{filepath} -> {hashed}")
    if extra_lines:
        with open("thrones-and-beauties.txt", "w", encoding="utf-8") as f:
            f.write("\n" + "\n".join(extra_lines))

        print("已追加 extra_res 链接到 thrones-and-beauties.txt")
        os.system(f"aria2c -i thrones-and-beauties.txt -j 32 -s 16 -x 16 --auto-file-renaming=false {f'{proxyaddr} ' if useproxy else ''}{'--allow-overwrite=true ' if overwrite else ''}--check-certificate=false --dir=resdownload/thrones-and-beauties")
    decrypt_folder("resdownload/thrones-and-beauties/download")
    for group_path, files in filelistdata.items():
        for filepath in files:
            hashed = Get_Hash_Name(filepath)
            source = os.path.join("resdownload", "thrones-and-beauties", "download", hashed)
            target = os.path.join("resdownload", "thrones-and-beauties", "output", filepath)

            if os.path.exists(source):
                if (not os.path.exists(target)) or overwrite:
                    os.makedirs(os.path.dirname(target), exist_ok=True)
                    shutil.copy2(source, target)
                    print(f"[cp]{filepath} -> {hashed}")
            else:
                print(f"[缺失]{filepath} -> {hashed}")


zgzddownloader(0)