docs(huya): R16 dfpReport加密体侦察 — turing反欺诈定位+全链结构解码
- 结构: getDfpConfig(81B密文配置)->selectOperator(SDID+hyudb_ts)->dfpReport(10B魔数+3988B密文体)->服务端回t1/SDID - 魔数/协议串147库全零: 运行时装配/turing混淆; Java无dfp类 - 关键材料: mpdc_108298_1=32hex设备号0399ED0B...; ga2 1860B; .turing.dat 76B - Java全量hook方案弃用(闪退); turing=工业级SDK, 建议独立子项目
This commit is contained in:
@@ -0,0 +1 @@
|
||||
{"event": "dfp-classes", "list": ["android.text.util.-$$Lambda$Linkify$7J_-cMhIF2bcttjkxA2jDFP8sKw"], "total": 1}
|
||||
@@ -0,0 +1,59 @@
|
||||
'use strict';
|
||||
function emit(row) {
|
||||
try { send(row); } catch (e) {}
|
||||
}
|
||||
// dfpReport 链 Java hook: 找 dfp/udbdf 类 -> hook 请求方法 -> 抓 tReq blob + 调用栈
|
||||
function bx() {
|
||||
try {
|
||||
return Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new()).split("\n").slice(0, 14).join(" | ");
|
||||
} catch (e) { return ''; }
|
||||
}
|
||||
setTimeout(() => {
|
||||
try {
|
||||
Java.perform(() => {
|
||||
const hits = [];
|
||||
Java.enumerateLoadedClasses({
|
||||
onMatch(name) {
|
||||
if (/dfp|Dfp|DFP|udbdf|Udbdf/.test(name)) hits.push(name);
|
||||
},
|
||||
onComplete() {
|
||||
emit({ event: 'dfp-classes', list: hits.slice(0, 60), total: hits.length });
|
||||
for (const cn of hits.slice(0, 40)) {
|
||||
try {
|
||||
const K = Java.use(cn);
|
||||
const methods = K.class.getDeclaredMethods();
|
||||
for (const m of methods) {
|
||||
const mn = m.getName();
|
||||
if (/post|report|send|build|req|encrypt|get|init/i.test(mn) && m.getParameterTypes().length <= 6) {
|
||||
try {
|
||||
K[mn].overloads.forEach(ov => {
|
||||
ov.implementation = function () {
|
||||
const args = Array.from(arguments).map(a => {
|
||||
try {
|
||||
if (a === null || a === undefined) return String(a);
|
||||
if (a instanceof Java.use("byte[]")) {
|
||||
const arr = Java.array('byte', a);
|
||||
return 'byte[' + arr.length + ']:' + Array.from(arr.slice(0, 48)).map(b => (b & 0xff).toString(16).padStart(2, '0')).join('');
|
||||
}
|
||||
const s = String(a);
|
||||
if (s.length > 200) return s.slice(0, 80) + ('…len' + s.length);
|
||||
if (s.indexOf('dfp') >= 0 || s.indexOf('udbdf') >= 0 || s.indexOf('571882cf') >= 0) return s;
|
||||
return s.slice(0, 60);
|
||||
} catch (e2) { return '<arg>'; }
|
||||
});
|
||||
emit({ event: 'dfp-call', cls: cn, method: mn, args: args.slice(0, 6), stack: bx() });
|
||||
return ov.apply(this, arguments);
|
||||
};
|
||||
});
|
||||
} catch (e3) {}
|
||||
}
|
||||
}
|
||||
} catch (e4) {}
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
} catch (e) {
|
||||
emit({ event: 'dfp-err', msg: String(e) });
|
||||
}
|
||||
}, 4000);
|
||||
@@ -26,7 +26,7 @@ PKG = "com.duowan.kiwi"
|
||||
SERVER_PATH = "/data/local/tmp/fs152"
|
||||
SERVER_PORT = "31878"
|
||||
BYpass_RE = "/Users/yml/codes/Reverse-Engineering-Agent-Universal-v3.0/evidence/scripts/bypass_msaoaid_maps_art_callsite.js"
|
||||
HOOK_LOCAL = os.environ.get("CAP_HOOK", "/Users/yml/codes/Reverse-Engineering-Agent-Universal-v3.0/evidence/scripts/hook_huya_crypto.js")
|
||||
HOOK_LOCAL = os.environ.get("CAP_HOOK")
|
||||
|
||||
MAX_ATTEMPTS = int(os.environ.get("CAP_MAX_ATTEMPTS", "8"))
|
||||
WINDOW_SEC = int(os.environ.get("CAP_WINDOW", "150"))
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import subprocess, sys, time
|
||||
pkg="com.duowan.kiwi"
|
||||
adb = lambda *a: subprocess.run(["adb"]+list(a), capture_output=True, text=True)
|
||||
adb("shell","su","-c","if ! pgrep -f /data/local/tmp/fs152; then nohup /data/local/tmp/fs152 -l 127.0.0.1:31878 >/data/local/tmp/fs152.log 2>&1 & fi")
|
||||
time.sleep(1.5)
|
||||
import frida
|
||||
dev = frida.get_device_manager().add_remote_device("127.0.0.1:31878")
|
||||
# attach the CURRENT running process (not spawn — just attach for the scan)
|
||||
procs = [p for p in dev.enumerate_processes() if p.name == pkg or (p.parameters or {}).get('name')==pkg or pkg in p.name]
|
||||
if not procs:
|
||||
print("app not running, spawn...", file=sys.stderr)
|
||||
pid = dev.spawn([pkg]); dev.resume(pid); time.sleep(12)
|
||||
procs = [p for p in dev.enumerate_processes() if pkg in p.name]
|
||||
target = procs[0]
|
||||
print(f"attaching {target.pid} {target.name}")
|
||||
session = dev.attach(target.pid)
|
||||
def on_message(msg, data):
|
||||
if msg.get('type')=='send':
|
||||
print("SCAN:", msg['payload'])
|
||||
session.create_script(open('/Users/yml/codes/douyu_login_py/tools/frida/scan_magic.js').read()).on('message', on_message).load()
|
||||
time.sleep(18)
|
||||
try: session.detach()
|
||||
except: pass
|
||||
@@ -0,0 +1,25 @@
|
||||
import subprocess, sys, time
|
||||
pkg="com.duowan.kiwi"
|
||||
adb = lambda *a: subprocess.run(["adb"]+list(a), capture_output=True, text=True)
|
||||
adb("shell","su","-c","if ! pgrep -f /data/local/tmp/fs152; then nohup /data/local/tmp/fs152 -l 127.0.0.1:31878 >/data/local/tmp/fs152.log 2>&1 & fi")
|
||||
time.sleep(1.5)
|
||||
import frida
|
||||
dev = frida.get_device_manager().add_remote_device("127.0.0.1:31878")
|
||||
pid = dev.spawn([pkg]); print("spawned", pid)
|
||||
session = dev.attach(pid)
|
||||
bypass = open("/Users/yml/codes/Reverse-Engineering-Agent-Universal-v3.0/evidence/scripts/bypass_msaoaid_maps_art_callsite.js").read()
|
||||
session.create_script(bypass).load()
|
||||
dev.resume(pid)
|
||||
print("resumed; waiting 25s for app init + dfpReport...")
|
||||
time.sleep(8)
|
||||
def on_message(msg, data):
|
||||
if msg.get('type')=='send' and isinstance(msg.get('payload'), dict) and msg['payload'].get('event')=='magic-scan':
|
||||
print("SCAN total:", msg['payload'].get('total'))
|
||||
for h in (msg['payload'].get('hits') or [])[:30]:
|
||||
print(" ", h['mod'], h['off'])
|
||||
script = session.create_script(open("scan_magic.js").read())
|
||||
script.on('message', on_message)
|
||||
script.load()
|
||||
time.sleep(10)
|
||||
try: session.detach()
|
||||
except: pass
|
||||
@@ -0,0 +1,19 @@
|
||||
'use strict';
|
||||
// 扫描进程内魔数 571882cf664bb39401ee
|
||||
const PATTERN = '57 18 82 cf 66 4b b3 94 01 ee';
|
||||
const mods = Process.enumerateModules();
|
||||
const hits = [];
|
||||
for (const m of mods) {
|
||||
if (m.size > 300 * 1024 * 1024) continue;
|
||||
try {
|
||||
Memory.scan(m.base, m.size, PATTERN, {
|
||||
onMatch(addr, size) {
|
||||
const mm = Process.findModuleByAddress(addr);
|
||||
const off = mm ? addr.sub(mm.base) : addr;
|
||||
hits.push({ mod: mm ? mm.name : '?', off: off.toString() });
|
||||
},
|
||||
onComplete() {},
|
||||
});
|
||||
} catch (e) {}
|
||||
}
|
||||
send({ event: 'magic-scan', hits: hits.slice(0, 40), total: hits.length });
|
||||
Reference in New Issue
Block a user