Files
notiMessage/reverse/frida/trace_tng_native_exit.js
mars 609635aba1 chore: 备份 TNG 注册/captcha 逆向与 MariBank SG bypass 进展
TngRootBypassHook 增强 captcha 诊断、TigerTally/JNIC 分层与 HWUI 策略;新增逆向脚本、Frida 工具与 UI dump;同步 MariBank SG hook 与 tng_exit_guard 更新。
2026-08-03 15:23:02 +08:00

283 lines
7.5 KiB
JavaScript

/**
* TNG — catch Promon exit after runtime code decrypt (mmap/mprotect RX).
* Frida 17 compatible.
*/
"use strict";
function log(msg) {
send("[TNG-native] " + msg);
}
function findExport(moduleName, name) {
try {
if (moduleName) {
var m = Process.findModuleByName(moduleName);
if (m) {
var a = m.findExportByName(name);
if (a) return a;
}
}
} catch (e) {}
try {
return Module.getGlobalExportByName(name);
} catch (e2) {
return null;
}
}
var patched = {};
function looksLikeExitSetup(addr) {
for (var i = 1; i <= 12; i++) {
try {
var w = addr.sub(i * 4).readU32();
var opc = w & 0xff800000;
if (opc === 0x52800000 || opc === 0xd2800000) {
var rd = w & 0x1f;
var imm = (w >> 5) & 0xffff;
if (rd === 8 && (imm === 93 || imm === 94)) return imm;
}
// mov x8, xN then earlier load — also catch svc after mov x0, #imm (exit code)
if ((w & 0xffe0ffff) === 0xaa0003e8) return 8; // mov x8, x0.. pattern loose
} catch (e) {}
}
return 0;
}
function patchRegion(base, size, tag) {
if (size <= 0 || size > 64 * 1024 * 1024) return;
var key = base + ":" + size;
if (patched[key]) return;
patched[key] = true;
var nop = [0x1f, 0x20, 0x03, 0xd5];
var n = 0;
var totalSvc = 0;
try {
// only scan 4-byte aligned by walking manually for reliability
var end = base.add(size - 4);
for (var p = base; p.compare(end) <= 0; p = p.add(4)) {
var w;
try {
w = p.readU32();
} catch (e) {
break;
}
if (w !== 0xd4000001) continue; // svc #0
totalSvc++;
var kind = looksLikeExitSetup(p);
if (!kind) continue;
try {
Memory.protect(p, 4, "rwx");
p.writeByteArray(nop);
n++;
log("patched exit SVC#" + kind + " @ " + p + " [" + tag + "]");
} catch (e2) {
log("patch err " + p + ": " + e2);
}
}
if (totalSvc > 0) {
log("region " + tag + " svc#0=" + totalSvc + " patched=" + n + " size=" + size);
}
} catch (e) {
log("scan err " + tag + ": " + e);
}
}
function scanAllExecutable(tag) {
Process.enumerateRanges("r-x").forEach(function (r) {
var file = r.file ? r.file.path : "anon";
// skip system libs except if anonymous / app
if (file.indexOf("/system/") === 0 || file.indexOf("/apex/") === 0) return;
if (file.indexOf("frida") >= 0) return;
patchRegion(r.base, r.size, tag + ":" + file);
});
}
function installLibcExitHooks() {
function blockExit(name, address) {
try {
Interceptor.replace(
address,
new NativeCallback(
function (code) {
log("BLOCKED " + name + "(" + (code | 0) + ")");
},
"void",
["int"]
)
);
log("replaced " + name);
} catch (e) {
Interceptor.attach(address, {
onEnter: function (args) {
log("BLOCKED(attach) " + name + "(" + args[0].toInt32() + ")");
while (true) Thread.sleep(60);
},
});
log("attached " + name);
}
}
["_exit", "exit", "abort", "quick_exit"].forEach(function (n) {
var a = findExport("libc.so", n);
if (a) blockExit(n, a);
});
["kill", "tgkill", "pthread_kill", "raise"].forEach(function (n) {
var a = findExport("libc.so", n);
if (!a) return;
Interceptor.attach(a, {
onEnter: function (args) {
var pid = args[0].toInt32();
var sig = args[1].toInt32();
if ((pid === Process.id || pid === 0 || pid === -1) &&
(sig === 9 || sig === 15 || sig === 6 || sig === 5)) {
log("BLOCKED " + n + " sig=" + sig);
args[1] = ptr(0);
}
},
});
});
var sys = findExport("libc.so", "syscall");
if (sys) {
Interceptor.attach(sys, {
onEnter: function (args) {
var nr = args[0].toInt32();
if (nr === 93 || nr === 94) {
log("BLOCKED syscall exit " + nr);
args[0] = ptr(-1);
}
},
});
}
log("libc hooks OK");
}
function installMprotectWatcher() {
var mprotect = findExport("libc.so", "mprotect");
var mmap = findExport("libc.so", "mmap");
if (mprotect) {
Interceptor.attach(mprotect, {
onEnter: function (args) {
this.addr = args[0];
this.len = args[1].toInt32();
this.prot = args[2].toInt32();
},
onLeave: function () {
// PROT_EXEC = 4
if (this.prot & 4) {
log("mprotect+EXEC " + this.addr + " len=" + this.len);
patchRegion(this.addr, this.len, "mprotect");
}
},
});
}
if (mmap) {
Interceptor.attach(mmap, {
onEnter: function (args) {
this.len = args[1].toInt32();
this.prot = args[2].toInt32();
},
onLeave: function (retval) {
if ((this.prot & 4) && !retval.isNull()) {
log("mmap+EXEC " + retval + " len=" + this.len);
patchRegion(retval, this.len, "mmap");
}
},
});
}
log("mprotect/mmap watchers OK");
}
function installMapsHide() {
var markers = ["frida", "gadget", "xposed", "lsposed", "vector", "zygisk", "magisk", "liblspd"];
var tracked = {};
function hide(line) {
var l = (line || "").toLowerCase();
for (var i = 0; i < markers.length; i++) if (l.indexOf(markers[i]) >= 0) return true;
return false;
}
function filter(buf, len) {
try {
var text = buf.readUtf8String(len);
if (!text) return len;
var out = text.split("\n").filter(function (x) { return !hide(x); }).join("\n");
var bytes = Memory.allocUtf8String(out);
var n = Math.min(len, out.length);
Memory.copy(buf, bytes, n);
return n;
} catch (e) {
return len;
}
}
var openat = findExport("libc.so", "openat");
var readFn = findExport("libc.so", "read");
if (openat) {
Interceptor.attach(openat, {
onEnter: function (args) {
this.path = args[1].isNull() ? null : args[1].readCString();
},
onLeave: function (retval) {
var fd = retval.toInt32();
if (fd >= 0 && this.path && this.path.indexOf("maps") >= 0) tracked[fd] = 1;
},
});
}
if (readFn) {
Interceptor.attach(readFn, {
onEnter: function (args) {
this.fd = args[0].toInt32();
this.buf = args[1];
},
onLeave: function (retval) {
var n = retval.toInt32();
if (n > 0 && tracked[this.fd]) retval.replace(ptr(filter(this.buf, n)));
},
});
}
log("maps hide OK");
}
function installJavaGuards() {
if (typeof Java === "undefined") {
setTimeout(installJavaGuards, 500);
return;
}
Java.perform(function () {
try {
Java.use("java.lang.System").exit.implementation = function (c) {
log("Java System.exit(" + c + ") blocked");
};
} catch (e) {}
try {
var R = Java.use("java.lang.Runtime");
R.exit.overload("int").implementation = function (c) {
log("Java Runtime.exit(" + c + ") blocked");
};
} catch (e) {}
try {
var P = Java.use("android.os.Process");
P.killProcess.implementation = function (pid) {
if (pid === P.myPid()) {
log("Java killProcess(self) blocked");
return;
}
return this.killProcess(pid);
};
} catch (e) {}
log("Java guards OK");
});
}
log("load pid=" + Process.id);
installLibcExitHooks();
installMapsHide();
installMprotectWatcher();
scanAllExecutable("boot");
setInterval(function () {
scanAllExecutable("tick");
}, 1000);
installJavaGuards();
log("ready");