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:
94
reverse/scripts/scan_tng.py
Normal file
94
reverse/scripts/scan_tng.py
Normal file
@@ -0,0 +1,94 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Scan TNG eWallet APK for AppProtect / root detection artifacts."""
|
||||
import re
|
||||
import sys
|
||||
import zipfile
|
||||
|
||||
KEYS = [
|
||||
b"AppProtect", b"appprotect", b"vkey", b"V-Key", b"VKey", b"VGuard",
|
||||
b"jailbroken", b"Jailbroken", b"Rooted Device", b"rooted device",
|
||||
b"Close app", b"tngdigital", b"TNG eWallet", b"How to keep device safe",
|
||||
b"enhanced our security", b"RootBeer", b"SafetyNet", b"PlayIntegrity",
|
||||
b"detectRoot", b"isRooted", b"checkRoot", b"magisk", b"xposed", b"lsposed",
|
||||
b"frida", b"emulator", b"su binary", b"/system/xbin/su",
|
||||
]
|
||||
|
||||
CLASS_KEYS = [
|
||||
b"safemode", b"SafeMode", b"appprotect", b"AppProtect", b"vkey", b"VKey",
|
||||
b"vguard", b"VGuard", b"rooted", b"RootBeer", b"integrity", b"jailbreak",
|
||||
b"security", b"RiskDevice", b"tamper", b"hook", b"frida",
|
||||
]
|
||||
|
||||
|
||||
def scan_strings(apk_path):
|
||||
print("=== STRING SCAN: %s ===" % apk_path)
|
||||
with zipfile.ZipFile(apk_path) as zf:
|
||||
for name in sorted(zf.namelist()):
|
||||
if not name.endswith(".dex"):
|
||||
continue
|
||||
data = zf.read(name)
|
||||
hits = []
|
||||
for key in KEYS:
|
||||
start = 0
|
||||
while True:
|
||||
idx = data.find(key, start)
|
||||
if idx < 0:
|
||||
break
|
||||
s = max(0, idx - 60)
|
||||
e = min(len(data), idx + len(key) + 100)
|
||||
chunk = re.sub(rb"[^\x20-\x7e]+", b" ", data[s:e])
|
||||
chunk = chunk.decode("ascii", "ignore").strip()
|
||||
if chunk and chunk not in hits:
|
||||
hits.append(chunk)
|
||||
start = idx + 1
|
||||
if hits:
|
||||
print("\n--- %s (%d hits) ---" % (name, len(hits)))
|
||||
for h in sorted(set(hits))[:40]:
|
||||
print(" ", h)
|
||||
if len(hits) > 40:
|
||||
print(" ... +%d more" % (len(hits) - 40))
|
||||
|
||||
|
||||
def scan_classes(apk_path):
|
||||
print("\n=== CLASS SCAN: %s ===" % apk_path)
|
||||
with zipfile.ZipFile(apk_path) as zf:
|
||||
for name in sorted(zf.namelist()):
|
||||
if not name.endswith(".dex"):
|
||||
continue
|
||||
data = zf.read(name)
|
||||
classes = set(re.findall(rb"L[a-zA-Z0-9_$/]+;", data))
|
||||
hits = []
|
||||
for raw in classes:
|
||||
low = raw.lower()
|
||||
if any(k.lower() in low for k in CLASS_KEYS):
|
||||
s = raw.decode("ascii", "ignore")[1:-1].replace("/", ".")
|
||||
hits.append(s)
|
||||
if hits:
|
||||
print("\n--- %s (%d classes) ---" % (name, len(hits)))
|
||||
for h in sorted(set(hits))[:60]:
|
||||
print(" ", h)
|
||||
if len(hits) > 60:
|
||||
print(" ... +%d more" % (len(hits) - 60))
|
||||
|
||||
|
||||
def scan_native(apk_path):
|
||||
print("\n=== NATIVE LIB SCAN: %s ===" % apk_path)
|
||||
with zipfile.ZipFile(apk_path) as zf:
|
||||
for name in sorted(zf.namelist()):
|
||||
if not name.endswith(".so"):
|
||||
continue
|
||||
data = zf.read(name)
|
||||
lib = name.split("/")[-1]
|
||||
found = []
|
||||
for key in KEYS + [b"libvos", b"libvkey", b"libvguard", b"libappprotect"]:
|
||||
if key.lower() in data.lower():
|
||||
found.append(key.decode("ascii", "ignore"))
|
||||
if found:
|
||||
print(" %s: %s" % (lib, ", ".join(sorted(set(found)))))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
path = sys.argv[1] if len(sys.argv) > 1 else "reverse/apks/tng/base.apk"
|
||||
scan_strings(path)
|
||||
scan_classes(path)
|
||||
scan_native(path)
|
||||
Reference in New Issue
Block a user