ksjsb/core/dfp_knn.py
2026-07-30 20:25:56 +08:00

306 lines
9.1 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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",
]