chore: 备份 TNG 注册/captcha 逆向与 MariBank SG bypass 进展
TngRootBypassHook 增强 captcha 诊断、TigerTally/JNIC 分层与 HWUI 策略;新增逆向脚本、Frida 工具与 UI dump;同步 MariBank SG hook 与 tng_exit_guard 更新。
This commit is contained in:
103
reverse/scripts/scan_tng_exiting_deep.py
Normal file
103
reverse/scripts/scan_tng_exiting_deep.py
Normal file
@@ -0,0 +1,103 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Deeper TNG reverse: Exiting/Report, TigerTally API, kill-SVC in SO."""
|
||||
from pathlib import Path
|
||||
import re
|
||||
import struct
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
APK_DIR = ROOT / "reverse" / "apks" / "tng"
|
||||
SO = APK_DIR / "libtngdigital_ewallet.so"
|
||||
|
||||
def load_dexes():
|
||||
files = sorted(APK_DIR.glob("classes*.dex"))
|
||||
if not files:
|
||||
# try extracted under other layouts
|
||||
files = sorted((ROOT / "reverse" / "apks").rglob("tng*/classes*.dex"))
|
||||
return files
|
||||
|
||||
def near(data, needle, before=40, after=80):
|
||||
out = []
|
||||
for m in re.finditer(re.escape(needle), data):
|
||||
s = max(0, m.start() - before)
|
||||
e = min(len(data), m.end() + after)
|
||||
chunk = data[s:e]
|
||||
printable = "".join(chr(b) if 32 <= b < 127 else "." for b in chunk)
|
||||
out.append(printable)
|
||||
return out
|
||||
|
||||
def main():
|
||||
dexes = load_dexes()
|
||||
print(f"dex count={len(dexes)}")
|
||||
all_data = b""
|
||||
for d in dexes:
|
||||
data = d.read_bytes()
|
||||
all_data += data
|
||||
hits = []
|
||||
for k in [b"Exiting:", b"Exiting", b"Report", b"W: 16", b"W:16",
|
||||
b"TigerTallyAPI", b"ttInit", b"collect", b"killProcess",
|
||||
b"SIGABRT", b"abort(", b"tgkill"]:
|
||||
c = data.count(k)
|
||||
if c:
|
||||
hits.append(f"{k.decode('latin1')}x{c}")
|
||||
if hits:
|
||||
print(f"{d.name}: {', '.join(hits)}")
|
||||
|
||||
print("\n=== near Exiting ===")
|
||||
for s in near(all_data, b"Exiting")[:15]:
|
||||
print(" ", s)
|
||||
|
||||
print("\n=== TigerTallyAPI method refs ===")
|
||||
for m in sorted(set(re.findall(rb"Lcom/aliyun/TigerTally/TigerTallyAPI;->[A-Za-z0-9_<>$]+", all_data))):
|
||||
print(" ", m.decode())
|
||||
|
||||
print("\n=== TigerTally t/ classes ===")
|
||||
for m in sorted(set(re.findall(rb"Lcom/aliyun/TigerTally/[a-z]/[A-Za-z0-9_/$]*;", all_data))):
|
||||
print(" ", m.decode())
|
||||
|
||||
print("\n=== xwwqazamx/bl method refs ===")
|
||||
for m in sorted(set(re.findall(rb"Lxwwqazamx/bl;->[A-Za-z0-9_<>$]+", all_data)))[:40]:
|
||||
print(" ", m.decode())
|
||||
|
||||
print("\n=== Process.killProcess / Runtime.exit refs near Promon ===")
|
||||
for pat in [rb"Landroid/os/Process;->killProcess", rb"Ljava/lang/System;->exit",
|
||||
rb"Ljava/lang/Runtime;->exit", rb"Ljava/lang/Runtime;->halt"]:
|
||||
print(pat.decode(), "count=", len(re.findall(pat, all_data)))
|
||||
|
||||
if SO.exists():
|
||||
so = SO.read_bytes()
|
||||
print(f"\n=== SO {SO.name} size={len(so)} ===")
|
||||
# movz x8,#129 = D2801028 LE
|
||||
patterns = {
|
||||
"movz_x8_129": bytes.fromhex("281080d2"),
|
||||
"movz_w8_129": bytes.fromhex("28108052"),
|
||||
"movz_x8_130": bytes.fromhex("481080d2"),
|
||||
"movz_x8_131": bytes.fromhex("681080d2"),
|
||||
"svc0": bytes.fromhex("010000d4"),
|
||||
"brk0": bytes.fromhex("000020d4"),
|
||||
}
|
||||
for name, pat in patterns.items():
|
||||
print(f" {name}: {so.count(pat)}")
|
||||
|
||||
# find movz kill + nearby svc within 32 bytes
|
||||
kill_imm = [bytes.fromhex(x) for x in ("281080d2", "28108052", "481080d2", "681080d2")]
|
||||
svc = bytes.fromhex("010000d4")
|
||||
found = 0
|
||||
for imm in kill_imm:
|
||||
start = 0
|
||||
while True:
|
||||
i = so.find(imm, start)
|
||||
if i < 0:
|
||||
break
|
||||
window = so[i:i+36]
|
||||
if svc in window:
|
||||
found += 1
|
||||
if found <= 20:
|
||||
off = window.find(svc)
|
||||
print(f" kill+svc @ file+0x{i:x} svc_delta={off}")
|
||||
start = i + 4
|
||||
print(f" kill+svc pairs (packed): {found}")
|
||||
else:
|
||||
print(f"\nSO missing: {SO}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user