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:
282
reverse/frida/trace_tng_native_exit.js
Normal file
282
reverse/frida/trace_tng_native_exit.js
Normal file
@@ -0,0 +1,282 @@
|
||||
/**
|
||||
* 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");
|
||||
Reference in New Issue
Block a user