Files
notiMessage/reverse/scripts/dump_tng_nativelib_methods.py
mars 609635aba1 chore: 备份 TNG 注册/captcha 逆向与 MariBank SG bypass 进展
TngRootBypassHook 增强 captcha 诊断、TigerTally/JNIC 分层与 HWUI 策略;新增逆向脚本、Frida 工具与 UI dump;同步 MariBank SG hook 与 tng_exit_guard 更新。
2026-08-03 15:23:02 +08:00

111 lines
4.0 KiB
Python

"""Minimal DEX parser: dump methods for target classes."""
import struct
import zipfile
from pathlib import Path
TARGET = {
"Lcom/tngd/networksdk/common/NativeLib;",
"Lcom/tngd/networksdk/common/ApiSixSecretKeys;",
"Lmy/com/tngdigital/common/internal/libs/RetrieveFromNativeLibs;",
}
def uleb(data, i):
result = 0
shift = 0
while True:
b = data[i]
i += 1
result |= (b & 0x7F) << shift
if (b & 0x80) == 0:
break
shift += 7
return result, i
def parse_dex(data: bytes, label: str):
if data[:4] != b"dex\n":
return
string_ids_size, string_ids_off = struct.unpack_from("<II", data, 56)
type_ids_size, type_ids_off = struct.unpack_from("<II", data, 64)
proto_ids_size, proto_ids_off = struct.unpack_from("<II", data, 72)
field_ids_size, field_ids_off = struct.unpack_from("<II", data, 80)
method_ids_size, method_ids_off = struct.unpack_from("<II", data, 88)
class_defs_size, class_defs_off = struct.unpack_from("<II", data, 96)
def string_at(idx):
off = struct.unpack_from("<I", data, string_ids_off + idx * 4)[0]
size, p = uleb(data, off)
return data[p : p + size].decode("utf-8", "replace")
def type_at(idx):
return string_at(struct.unpack_from("<I", data, type_ids_off + idx * 4)[0])
def proto_at(idx):
shorty_idx, return_type_idx, parameters_off = struct.unpack_from(
"<III", data, proto_ids_off + idx * 12
)
ret = type_at(return_type_idx)
params = []
if parameters_off:
size = struct.unpack_from("<I", data, parameters_off)[0]
for i in range(size):
tidx = struct.unpack_from("<H", data, parameters_off + 4 + i * 2)[0]
params.append(type_at(tidx))
return ret, params
def method_at(idx):
class_idx, proto_idx, name_idx = struct.unpack_from(
"<HHI", data, method_ids_off + idx * 8
)
ret, params = proto_at(proto_idx)
return type_at(class_idx), string_at(name_idx), ret, params
print(f"\n===== {label} =====")
for c in range(class_defs_size):
class_idx, access_flags, superclass_idx, interfaces_off, source_file_idx, annotations_off, class_data_off, static_values_off = struct.unpack_from(
"<IIIIIIII", data, class_defs_off + c * 32
)
cname = type_at(class_idx)
if cname not in TARGET:
continue
print(f"\nCLASS {cname} access=0x{access_flags:x}")
if not class_data_off:
print(" (no class_data)")
continue
p = class_data_off
static_fields_size, p = uleb(data, p)
instance_fields_size, p = uleb(data, p)
direct_methods_size, p = uleb(data, p)
virtual_methods_size, p = uleb(data, p)
# skip fields
for _ in range(static_fields_size + instance_fields_size):
_, p = uleb(data, p)
_, p = uleb(data, p)
mid = 0
for kind, count in (("direct", direct_methods_size), ("virtual", virtual_methods_size)):
mid = 0
for _ in range(count):
diff, p = uleb(data, p)
access, p = uleb(data, p)
code_off, p = uleb(data, p)
mid += diff
cls, name, ret, params = method_at(mid)
flags = []
if access & 0x100:
flags.append("native")
if access & 0x8:
flags.append("static")
if access & 0x10000:
flags.append("constructor")
print(f" [{kind}] {' '.join(flags)} {name}({', '.join(params)}){ret} code=0x{code_off:x}")
apk = Path(r"C:\Users\Administrator\Desktop\notiMessage\reverse\apks\tng\base.apk")
with zipfile.ZipFile(apk) as z:
for n in z.namelist():
if n.endswith(".dex"):
data = z.read(n)
if any(t.encode() in data for t in ("NativeLib;", "ApiSixSecretKeys;", "RetrieveFromNativeLibs;")):
parse_dex(data, n)