TngRootBypassHook 增强 captcha 诊断、TigerTally/JNIC 分层与 HWUI 策略;新增逆向脚本、Frida 工具与 UI dump;同步 MariBank SG hook 与 tng_exit_guard 更新。
111 lines
4.0 KiB
Python
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)
|