继续破解进度
This commit is contained in:
@@ -19,7 +19,8 @@ import frida
|
||||
|
||||
PACKAGE = "com.duowan.kiwi"
|
||||
RE = Path("/Users/yml/codes/Reverse-Engineering-Agent-Universal-v3.0")
|
||||
OUT = Path("/Users/yml/codes/douyu_login_py/evidence/dfp_pipeline_v2.json")
|
||||
import time as _t
|
||||
OUT = Path("/Users/yml/codes/douyu_login_py/evidence/dfp_pipeline_" + _t.strftime("%H%M%S") + ".json")
|
||||
|
||||
JS = r"""
|
||||
'use strict';
|
||||
@@ -63,7 +64,7 @@ function decodeArg(p, tag){
|
||||
if (startsWith(p, MAGIC_HDR)){
|
||||
res.kind = 'MAGIC';
|
||||
var pre = '';
|
||||
try{ pre = hexb(p.sub(1536), 1536); }catch(e){}
|
||||
try{ pre = hexb(p.sub(8192), 8192); }catch(e){}
|
||||
res.pre = pre;
|
||||
res.full = hexb(p, 9000);
|
||||
return res;
|
||||
@@ -109,6 +110,49 @@ function decodeArg(p, tag){
|
||||
}catch(e){ return null; }
|
||||
}
|
||||
|
||||
// deep decode: scan 1024B at p for plausible pointers, dump 9000B at each
|
||||
function deepDeref(p){
|
||||
var out = {reg: 'deep', addr: String(p)};
|
||||
var found = [];
|
||||
var seen = {};
|
||||
try{
|
||||
// also dump page-aligned base 12000B
|
||||
try{
|
||||
var pg = p.and(ptr('0xfffffffffffff000'));
|
||||
if (isReadable(pg)){
|
||||
found.push({kind: 'page', ptr: String(pg), full: hexb(pg, 12000)});
|
||||
seen[String(pg)] = true;
|
||||
}
|
||||
}catch(e){}
|
||||
var base = p.sub(512);
|
||||
for (var i = 0; i < 1024; i += 8){
|
||||
var v;
|
||||
try{ v = base.add(i).readU64(); }catch(e){ continue; }
|
||||
var cand = v.and(ptr('0x7fffffffffff'));
|
||||
var s = cand.toString();
|
||||
if (cand == ptr('0')) continue;
|
||||
// heap-ish: 0x7[7-9ca].. or 0xb4.. or 0x77..
|
||||
if (!(/^0x(7[78a-c9]|b4)[0-9a-f]{9,}$/.test(s))) continue;
|
||||
if (seen[s]) continue;
|
||||
if (!isReadable(cand)) continue;
|
||||
seen[s] = true;
|
||||
var entry = {off: i - 512, ptr: s};
|
||||
var kind = 'raw';
|
||||
if (startsWith(cand, JSON_HDR)) kind = 'JSON';
|
||||
else if (startsWith(cand, MAGIC_HDR)) kind = 'MAGIC';
|
||||
entry.kind = kind;
|
||||
if (kind === 'JSON' || kind === 'MAGIC'){
|
||||
entry.full = hexb(cand, 9000);
|
||||
} else {
|
||||
entry.head = hexb(cand, 64) || '';
|
||||
}
|
||||
found.push(entry);
|
||||
}
|
||||
}catch(e){}
|
||||
out.entries = found;
|
||||
return out;
|
||||
}
|
||||
|
||||
function hookFn(off, name){
|
||||
try{
|
||||
var base = Process.getModuleByName('libhydeviceid.so').base;
|
||||
@@ -120,6 +164,10 @@ function hookFn(off, name){
|
||||
var pr = decodeArg(ctx[r], r);
|
||||
if (pr) ev[r] = pr;
|
||||
});
|
||||
// cryptoA: deep deref x0
|
||||
if (name === 'cryptoA_5b1f4'){
|
||||
ev.deep = deepDeref(ctx.x0);
|
||||
}
|
||||
send({type:'pipe', ev: ev});
|
||||
}
|
||||
});
|
||||
@@ -146,6 +194,29 @@ function attachOne(base, off, name){
|
||||
var pr = decodeArg(ctx[r], r);
|
||||
if (pr) ev[r] = pr;
|
||||
});
|
||||
// cryptoA: deep deref x0
|
||||
if (name === 'cryptoA_5b1f4'){
|
||||
ev.deep = deepDeref(ctx.x0);
|
||||
}
|
||||
// copy_61098 second call (x0=MAGIC): heap scan for JSON + dump 4600B
|
||||
if (name === 'copy_61098' && (ev.x0||{}).kind === 'MAGIC'){
|
||||
var hits = [];
|
||||
try{
|
||||
var pat = '7b 22 61 70 70 49 64 22 3a 22 35 30 30 38';
|
||||
var ranges = Process.enumerateRanges('rw-');
|
||||
for (var ri = 0; ri < ranges.length; ri++){
|
||||
var rng = ranges[ri];
|
||||
if (rng.size > 0x10000000) continue;
|
||||
var m = Memory.scanSync(rng.base, rng.size, pat);
|
||||
for (var mi = 0; mi < m.length; mi++){
|
||||
var full = hexb(m[mi].address, 4600) || '';
|
||||
var h = full.substring(0, 96);
|
||||
hits.push({addr: String(m[mi].address), head: h, full: full});
|
||||
}
|
||||
}
|
||||
}catch(e){}
|
||||
send({type:'jsonhits', n: hits.length, hits: hits, t: Date.now() - t0});
|
||||
}
|
||||
send({type:'pipe', ev: ev});
|
||||
}
|
||||
});
|
||||
@@ -183,6 +254,20 @@ try{
|
||||
"""
|
||||
|
||||
|
||||
def load_with_retry(session, js, n=5):
|
||||
last = None
|
||||
for i in range(n):
|
||||
try:
|
||||
s = session.create_script(js)
|
||||
s.load()
|
||||
return s
|
||||
except Exception as e:
|
||||
last = e
|
||||
print(f"[retry {i}] {e}", flush=True)
|
||||
time.sleep(3)
|
||||
raise last
|
||||
|
||||
|
||||
def main():
|
||||
device = frida.get_device_manager().add_remote_device("127.0.0.1:31877")
|
||||
pid = device.spawn([PACKAGE])
|
||||
@@ -226,26 +311,25 @@ def main():
|
||||
print(f"[{ev.get('t')}ms] {ev.get('fn')}::{ev.get('phase')} " + " ".join(parts), flush=True)
|
||||
events.append({"type": "pipe", "ev": ev})
|
||||
OUT.write_text(json.dumps(events))
|
||||
elif t == "jsonhits":
|
||||
print(f"[{p.get('t')}ms] [jsonhits] n={p.get('n')}", flush=True)
|
||||
events.append({"type": "jsonhits", "t": p.get('t'), "hits": p.get('hits')})
|
||||
OUT.write_text(json.dumps(events))
|
||||
elif t == "wire":
|
||||
print(f"[{p.get('t')}ms] [wire] len={p.get('len')}", flush=True)
|
||||
events.append({"type": "wire", "len": p.get('len'), "t": p.get('t'), "hex": p.get('hex')})
|
||||
OUT.write_text(json.dumps(events))
|
||||
|
||||
script = session.create_script(JS)
|
||||
script.on("message", on_message)
|
||||
script.load()
|
||||
print("[*] 主JS 已装载, 加载 bypass + resume", flush=True)
|
||||
session.create_script(
|
||||
(RE / "evidence/scripts/bypass_msaoaid_maps_art_callsite.js").read_text()
|
||||
).load()
|
||||
session.create_script(
|
||||
(RE / "evidence/scripts/mask_frida_maps_only.js").read_text()
|
||||
).load()
|
||||
# 严格按约定顺序: spawn -> bypass x2 -> resume + sleep 11 -> patch_guard -> 最后主 hook JS
|
||||
print("[*] loading bypass", flush=True)
|
||||
load_with_retry(session, (RE / "evidence/scripts/bypass_msaoaid_maps_art_callsite.js").read_text())
|
||||
load_with_retry(session, (RE / "evidence/scripts/mask_frida_maps_only.js").read_text())
|
||||
device.resume(pid)
|
||||
time.sleep(11)
|
||||
session.create_script(
|
||||
(RE / "evidence/scripts/patch_guard_block_termination.js").read_text()
|
||||
).load()
|
||||
load_with_retry(session, (RE / "evidence/scripts/patch_guard_block_termination.js").read_text())
|
||||
print("[*] loading 主 hook JS (最后)", flush=True)
|
||||
script = load_with_retry(session, JS)
|
||||
script.on("message", on_message)
|
||||
print("[*] 已 resume。等待 dfpReport", flush=True)
|
||||
try:
|
||||
while True:
|
||||
|
||||
Reference in New Issue
Block a user