from __future__ import annotations import json import zlib from .device_profile import DeviceProfile KWE_N = "KWE_N" KWE_NPN = "KWE_NPN" LITE_DFP_VERSION = "9.5.4lite.79.137a838b" # 运营商 -> MCC-MNC(从 profile.isp 派生,不再硬编码) _ISP_MCC_MNC = {"CUCC": "46001", "CTCC": "46011", "CMCC": "46000"} LITE_KEYS = [ "k5", "k14", "k22", "k23", "k27", "k29", "k31", "k34", "k35", "k36", "k39", "k40", "k46", "k57", "k61", "k64", "k66", "k68", "k83", "k86", "k93", "k97", "k101", "k102", "k105", "k106", "k107", "k108", "k109", "k110", "k111", "k112", "k113", ] FULL_KEYS = [f"k{index}" for index in range(1, 120)] FULL_DEFAULTS = { **{key: KWE_NPN for key in ("k2", "k9", "k12", "k13", "k18", "k21", "k33", "k41", "k43")}, **{key: KWE_NPN for key in ("k55", "k57", "k62", "k65", "k76", "k79", "k80", "k81")}, **{key: KWE_NPN for key in ("k54", "k68", "k71", "k73", "k74", "k75", "k77", "k82", "k88")}, **{key: KWE_NPN for key in ("k106", "k114", "k115", "k116", "k117", "k118")}, **{key: KWE_N for key in ("k24", "k31", "k53", "k70", "k85", "k86", "k87")}, **{key: KWE_N for key in ("k90", "k91", "k94", "k96", "k101", "k103", "k104")}, "k63": "root", "k95": "KWE_NS", } def _android_suffix(value: str) -> str: return value.removeprefix("ANDROID_") def _text(value: object, default: str = KWE_N) -> str: if value is None: return default text = str(value) return text if text != "" else default def _mcc_mnc(profile: DeviceProfile) -> str: return { "CUCC": "46011", "CTCC": "46003", "CMCC": "46000", }.get(profile.isp.upper(), KWE_NPN) def _k93_json(profile: DeviceProfile) -> str: return json.dumps( { "0": 1, "1": "7", "2": "true", "4": KWE_N, "8": "zz abcdabcdabcdabcdabcd", "11": profile.model, "12": KWE_N, "19": "100", "20": profile.install_time_ms, "23": KWE_N, "24": KWE_N, "25": f"{profile.runtime_hints.wifi_mac or '02:00:00:00:00:00'}@{profile.install_time_ms}@{profile.model}@CTExcel@{_ISP_MCC_MNC.get(profile.isp.upper(), '46001')}", "30": { "op_old": profile.runtime_hints.oaid or KWE_N, "cost_old": 5, "cost_new": 22, }, "27": True, "28": profile.g_rdi2, }, ensure_ascii=False, separators=(",", ":"), ) def _k93_lite_json(profile: DeviceProfile) -> str: return json.dumps( { "19": "100", "20": profile.install_time_ms, "23": KWE_N, "24": KWE_N, "25": f"{profile.runtime_hints.wifi_mac or '02:00:00:00:00:00'}@{profile.install_time_ms}@{profile.model}@CTExcel@{_ISP_MCC_MNC.get(profile.isp.upper(), '46001')}", "30": { "op_old": profile.runtime_hints.oaid or KWE_N, "cost_old": 6, "cost_new": 23, }, "27": True, "28": profile.g_rdi2, }, ensure_ascii=False, separators=(",", ":"), ) def _dalvik_vm(profile: DeviceProfile) -> str: return ( f"Dalvik/2.1.0 (Linux; U; Android {profile.android_release}; " f"{profile.model} Build/{profile.build_id})" ) def _build_fingerprint(profile: DeviceProfile) -> str: if profile.build_fingerprint: return profile.build_fingerprint product = profile.build_product or profile.model return ( f"{profile.manufacturer}/{profile.model}/{product}:" f"{profile.android_release}/{profile.build_id}/{profile.build_display}:" f"{profile.build_type}/{profile.build_tags}" ) def recompute_k14_crc(values: dict[str, str], ordered_keys: list[str]) -> str: crc = 0 for key in ordered_keys: raw = b"AND" if key == "k14" else str(values.get(key, "")).encode("utf-8") crc = zlib.crc32(raw, crc) return f"AND:{crc & 0xFFFFFFFF}" def build_lite_knn( profile: DeviceProfile, overrides: dict[str, str] | None = None, ) -> dict[str, str]: hints = profile.runtime_hints values = {key: KWE_N for key in LITE_KEYS} values.update( { "k5": str(profile.install_time_ms), "k14": "AND", "k22": profile.app_version, "k23": profile.manufacturer, "k27": profile.model, "k29": _dalvik_vm(profile), "k31": KWE_N, "k34": profile.screen_metrics, "k35": profile.android_release, "k36": LITE_DFP_VERSION, "k39": hints.did_gt or str(profile.install_time_ms), "k40": _build_fingerprint(profile), "k46": hints.total_memory_bytes or str(profile.total_memory_mb * 1024 * 1024), "k57": KWE_NPN, "k61": profile.brand, "k66": _android_suffix(profile.o_did), "k68": KWE_NPN, "k83": profile.egid or "KWE_N", "k93": _k93_lite_json(profile), "k97": hints.oaid, "k101": hints.res_soc, "k102": hints.boot_id, "k105": hints.grdi, "k106": KWE_NPN, "k107": str(profile.cdid_tag), "k108": hints.ipv6_map, "k109": hints.lpss, "k110": hints.keeper_seed, "k111": hints.du, "k112": hints.sted_cache_json or "KWE_N", "k113": hints.manus, } ) if overrides: for key, value in overrides.items(): if key not in values: raise KeyError(key) values[key] = "" if value is None else str(value) values["k14"] = recompute_k14_crc(values, LITE_KEYS) return {key: _text(values.get(key), default="") for key in LITE_KEYS} def build_full_knn( profile: DeviceProfile, overrides: dict[str, str] | None = None, ) -> dict[str, str]: hints = profile.runtime_hints values = {key: FULL_DEFAULTS.get(key, KWE_N) for key in FULL_KEYS} values.update( { "k1": "isContent", "k3": profile.package_name, "k4": hints.k4_native, "k5": str(profile.install_time_ms), "k6": "0", "k7": profile.did, "k8": profile.build_type, "k10": "0", "k11": "0", "k14": "AND", "k15": "0", "k16": "kvm-slave-build-s-system-11410184", "k17": "192.168.8.34", "k19": "sun", "k20": str(hints.storage_available_bytes), "k22": profile.app_version, "k23": profile.manufacturer, "k25": "1", "k26": "arm64-v8a,", "k27": profile.model, "k28": "qcom", "k29": _dalvik_vm(profile), "k30": profile.build_display, "k32": "[GMT+08:00,Asia/Shanghai]", "k34": profile.screen_metrics, "k35": profile.android_release, "k36": LITE_DFP_VERSION, "k37": profile.build_id, "k38": "91", "k39": hints.did_gt or str(profile.install_time_ms), "k40": _build_fingerprint(profile), "k42": "[5,100]", "k44": profile.build_tags, "k45": "isContent", "k46": hints.total_memory_bytes or str(profile.total_memory_mb * 1024 * 1024), "k47": "unknown", "k48": "isContent", "k49": "0", "k50": "notExist", "k51": hints.k51_native, "k52": profile.model, "k56": "notExist", "k58": profile.build_product or hints.build_product or profile.model, "k59": "1", "k60": "unknown", "k61": profile.brand, "k66": _android_suffix(profile.o_did), "k67": "gb", "k69": "1", "k72": profile.country_code, "k78": _mcc_mnc(profile), "k83": profile.egid or "KWE_FIRST", "k84": hints.k84_native, "k89": "160816899", "k92": str(profile.cold_launch_time_ms), "k93": _k93_json(profile), "k97": hints.oaid, "k101": hints.res_soc, "k102": hints.boot_id, "k105": hints.grdi, "k107": str(profile.cdid_tag), "k108": hints.ipv6_map, "k109": hints.lpss, "k110": hints.keeper_seed, "k111": hints.du, "k112": hints.sted_cache_json, "k113": hints.manus, "k119": hints.gaid, } ) if overrides: for key, value in overrides.items(): if key not in values: raise KeyError(key) values[key] = "" if value is None else str(value) values["k14"] = recompute_k14_crc(values, FULL_KEYS) return {key: _text(values.get(key), default="") for key in FULL_KEYS} __all__ = [ "FULL_KEYS", "KWE_N", "LITE_DFP_VERSION", "LITE_KEYS", "build_full_knn", "build_lite_knn", "recompute_k14_crc", ]