feat(maribank): PH 注册 OTP 突破、SG bypass 与中文文档
菲律宾 SeaBank 在 Root+LSPosed+Shamiko 下 register 已通过并触发 OTP;扩展 SG 包名、加密前 Hook、Magisk 设备伪装脚本,并将 docs 整理为中文操作与风控说明。
This commit is contained in:
@@ -0,0 +1,232 @@
|
||||
package com.miraclegarden.smsmessage.xposed.hook;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import de.robv.android.xposed.XC_MethodHook;
|
||||
import de.robv.android.xposed.XposedBridge;
|
||||
import de.robv.android.xposed.XposedHelpers;
|
||||
import de.robv.android.xposed.callbacks.XC_LoadPackage;
|
||||
|
||||
/**
|
||||
* SHPSSDK attestation 生成链 Hook(含 native JNI)。
|
||||
* 目标:在 {@code rdVerifyInfo.data/dataKey} 组装前,让 native 采集层读到「干净环境」。
|
||||
*/
|
||||
public final class MariBankAttestationHook {
|
||||
|
||||
private static final String TAG = "notiMessageHook/MariBankAttest";
|
||||
|
||||
private static volatile boolean installed = false;
|
||||
|
||||
private MariBankAttestationHook() {
|
||||
}
|
||||
|
||||
public static void installLate(XC_LoadPackage.LoadPackageParam lpparam) {
|
||||
if (installed) {
|
||||
return;
|
||||
}
|
||||
installed = true;
|
||||
|
||||
int n = 0;
|
||||
n += hookAttestationClass(lpparam, "com.shopee.shpssdkbank.wvvvuwwu");
|
||||
n += hookAttestationClass(lpparam, "com.shopee.shpssdk.wvvvuwwu");
|
||||
n += hookAttestationClass(lpparam,
|
||||
"com.shopee.shpssdkbank.uwuvuvvww.uvwuuuuuw.vvvvuwwvu");
|
||||
n += hookKnownAttestationMethods(lpparam);
|
||||
hookEnvironmentProbes(lpparam);
|
||||
XposedBridge.log(TAG + " attestation hooks=" + n);
|
||||
}
|
||||
|
||||
/** 逆向确认的 attestation / requestDefense 桥接方法。 */
|
||||
private static int hookKnownAttestationMethods(XC_LoadPackage.LoadPackageParam lpparam) {
|
||||
int count = 0;
|
||||
count += hookMethodByName(lpparam, "com.shopee.shpssdkbank.wvvvuwwu", "vvuwuuvuu");
|
||||
count += hookMethodByName(lpparam, "com.shopee.shpssdkbank.wvvvuwwu", "wwvwvwuvv");
|
||||
count += hookMethodByName(lpparam, "com.shopee.shpssdkbank.wvvvuwwu", "vuwuuuwv");
|
||||
count += hookMethodByName(lpparam, "com.shopee.shpssdkbank.uwuvuvvww.vvuuuuvvv", "wuvwuvwwu");
|
||||
return count;
|
||||
}
|
||||
|
||||
private static int hookMethodByName(
|
||||
XC_LoadPackage.LoadPackageParam lpparam, String className, String methodName) {
|
||||
int count = 0;
|
||||
try {
|
||||
Class<?> clazz = XposedHelpers.findClass(className, lpparam.classLoader);
|
||||
for (Method method : clazz.getDeclaredMethods()) {
|
||||
if (!methodName.equals(method.getName())) {
|
||||
continue;
|
||||
}
|
||||
if (hookAttestationMethod(className, method)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
XposedBridge.log(TAG + " skip " + className + "." + methodName + ": " + t.getMessage());
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private static int hookAttestationClass(
|
||||
XC_LoadPackage.LoadPackageParam lpparam, String className) {
|
||||
int count = 0;
|
||||
try {
|
||||
Class<?> clazz = XposedHelpers.findClass(className, lpparam.classLoader);
|
||||
for (Method method : clazz.getDeclaredMethods()) {
|
||||
if (!Modifier.isStatic(method.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
if (hookAttestationMethod(className, method)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
XposedBridge.log(TAG + " skip class " + className + ": " + t.getMessage());
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private static boolean hookAttestationMethod(String className, Method method) {
|
||||
Class<?> rt = method.getReturnType();
|
||||
if (rt == String.class) {
|
||||
XposedBridge.hookMethod(method, new XC_MethodHook() {
|
||||
@Override
|
||||
protected void afterHookedMethod(MethodHookParam param) {
|
||||
Object result = param.getResult();
|
||||
if (!(result instanceof String)) {
|
||||
return;
|
||||
}
|
||||
String s = (String) result;
|
||||
String sanitized = sanitizeAttestationString(s);
|
||||
if (!sanitized.equals(s)) {
|
||||
param.setResult(sanitized);
|
||||
XposedBridge.log(TAG + " " + className + "#" + method.getName()
|
||||
+ (Modifier.isNative(method.getModifiers()) ? " (native)" : "")
|
||||
+ " sanitized len=" + s.length());
|
||||
}
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
if (rt == byte[].class) {
|
||||
XposedBridge.hookMethod(method, new XC_MethodHook() {
|
||||
@Override
|
||||
protected void afterHookedMethod(MethodHookParam param) {
|
||||
Object result = param.getResult();
|
||||
if (!(result instanceof byte[])) {
|
||||
return;
|
||||
}
|
||||
byte[] bytes = (byte[]) result;
|
||||
byte[] out = MariBankRegisterPayloadUtil.sanitizeRegistrationBytes(bytes);
|
||||
if (out != bytes) {
|
||||
param.setResult(out);
|
||||
XposedBridge.log(TAG + " " + className + "#" + method.getName()
|
||||
+ " byte[] sanitized");
|
||||
} else {
|
||||
byte[] tokenOut = MariBankRiskTokenUtil.sanitizeBytes(bytes, 0, bytes.length);
|
||||
if (tokenOut != bytes) {
|
||||
param.setResult(tokenOut);
|
||||
XposedBridge.log(TAG + " " + className + "#" + method.getName()
|
||||
+ " byte[] riskToken sanitized");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
if (rt == boolean.class || rt == Boolean.class) {
|
||||
XposedBridge.hookMethod(method, new XC_MethodHook() {
|
||||
@Override
|
||||
protected void beforeHookedMethod(MethodHookParam param) {
|
||||
param.setResult(false);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
if (rt == int.class || rt == Integer.class) {
|
||||
XposedBridge.hookMethod(method, new XC_MethodHook() {
|
||||
@Override
|
||||
protected void beforeHookedMethod(MethodHookParam param) {
|
||||
param.setResult(0);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String sanitizeAttestationString(String s) {
|
||||
if (s == null || s.isEmpty()) {
|
||||
return s;
|
||||
}
|
||||
if (MariBankRegisterPayloadUtil.isRegistrationPayload(s)) {
|
||||
return MariBankRegisterPayloadUtil.sanitizeRegistrationJson(s);
|
||||
}
|
||||
if (s.contains("|")) {
|
||||
return MariBankRiskTokenUtil.sanitizeRiskToken(s);
|
||||
}
|
||||
return MariBankRiskTokenUtil.sanitizeAllInText(s);
|
||||
}
|
||||
|
||||
private static void hookEnvironmentProbes(XC_LoadPackage.LoadPackageParam lpparam) {
|
||||
try {
|
||||
XposedHelpers.findAndHookMethod(
|
||||
"android.os.Debug",
|
||||
lpparam.classLoader,
|
||||
"isDebuggerConnected",
|
||||
new XC_MethodHook() {
|
||||
@Override
|
||||
protected void beforeHookedMethod(MethodHookParam param) {
|
||||
param.setResult(false);
|
||||
}
|
||||
}
|
||||
);
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
try {
|
||||
XposedHelpers.findAndHookMethod(
|
||||
"android.os.Debug",
|
||||
lpparam.classLoader,
|
||||
"waitingForDebugger",
|
||||
new XC_MethodHook() {
|
||||
@Override
|
||||
protected void beforeHookedMethod(MethodHookParam param) {
|
||||
param.setResult(false);
|
||||
}
|
||||
}
|
||||
);
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
RootBypassHelper.hookFileExists(lpparam);
|
||||
RootBypassHelper.hookRuntimeExec(lpparam);
|
||||
RootBypassHelper.hookSystemGetProperty(lpparam);
|
||||
hookProcessBuilder(lpparam);
|
||||
}
|
||||
|
||||
private static void hookProcessBuilder(XC_LoadPackage.LoadPackageParam lpparam) {
|
||||
try {
|
||||
XposedHelpers.findAndHookMethod(
|
||||
ProcessBuilder.class,
|
||||
"start",
|
||||
new XC_MethodHook() {
|
||||
@Override
|
||||
protected void beforeHookedMethod(MethodHookParam param) {
|
||||
ProcessBuilder pb = (ProcessBuilder) param.thisObject;
|
||||
if (pb == null || pb.command() == null) {
|
||||
return;
|
||||
}
|
||||
String joined = String.join(" ", pb.command()).toLowerCase();
|
||||
if (joined.contains(" su") || joined.startsWith("su")
|
||||
|| joined.contains("magisk") || joined.contains("which su")
|
||||
|| joined.contains("getprop ro.debuggable")) {
|
||||
XposedBridge.log(TAG + " blocked ProcessBuilder: " + joined);
|
||||
throw new SecurityException("blocked root probe");
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
} catch (Throwable t) {
|
||||
XposedBridge.log(TAG + " ProcessBuilder hook failed: " + t.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.miraclegarden.smsmessage.xposed.hook;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import de.robv.android.xposed.XposedBridge;
|
||||
|
||||
/**
|
||||
* register 加密前 JSON 净化:{@code scene=REGISTRATION} 路径上的 deviceFingerprint / riskToken。
|
||||
*/
|
||||
final class MariBankRegisterPayloadUtil {
|
||||
|
||||
private static final String TAG = "notiMessageHook/MariBankRegister";
|
||||
|
||||
private static final Pattern DEVICE_FINGERPRINT = Pattern.compile(
|
||||
"\"deviceFingerprint\"\\s*:\\s*\"([^\"]+)\"");
|
||||
|
||||
private MariBankRegisterPayloadUtil() {
|
||||
}
|
||||
|
||||
static boolean isRegistrationPayload(String text) {
|
||||
if (text == null || text.length() < 24) {
|
||||
return false;
|
||||
}
|
||||
return text.contains("\"scene\":\"REGISTRATION\"")
|
||||
|| text.contains("\"scene\": \"REGISTRATION\"")
|
||||
|| (text.contains("rdVerifyInfo") && text.contains("\"step\":\"BE\""));
|
||||
}
|
||||
|
||||
static byte[] sanitizeRegistrationBytes(byte[] data) {
|
||||
if (data == null || data.length == 0) {
|
||||
return data;
|
||||
}
|
||||
String text = new String(data, StandardCharsets.UTF_8);
|
||||
if (!isRegistrationPayload(text)) {
|
||||
return MariBankRiskTokenUtil.sanitizeBytes(data, 0, data.length);
|
||||
}
|
||||
String out = sanitizeRegistrationJson(text);
|
||||
if (out.equals(text)) {
|
||||
return data;
|
||||
}
|
||||
XposedBridge.log(TAG + " sanitized register payload len=" + data.length + " -> " + out.length());
|
||||
return out.getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
static String sanitizeRegistrationJson(String json) {
|
||||
if (json == null) {
|
||||
return null;
|
||||
}
|
||||
String out = MariBankRiskTokenUtil.sanitizeAllInText(json);
|
||||
Matcher m = DEVICE_FINGERPRINT.matcher(out);
|
||||
StringBuffer sb = new StringBuffer();
|
||||
boolean changed = false;
|
||||
while (m.find()) {
|
||||
String old = m.group(1);
|
||||
String neu = MariBankRiskTokenUtil.sanitizeRiskToken(old);
|
||||
if (!neu.equals(old)) {
|
||||
changed = true;
|
||||
}
|
||||
m.appendReplacement(sb, Matcher.quoteReplacement(
|
||||
"\"deviceFingerprint\":\"" + neu + "\""));
|
||||
}
|
||||
if (changed) {
|
||||
m.appendTail(sb);
|
||||
out = sb.toString();
|
||||
XposedBridge.log(TAG + " deviceFingerprint sanitized in register JSON");
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package com.miraclegarden.smsmessage.xposed.hook;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Process;
|
||||
import android.view.View;
|
||||
@@ -22,13 +23,30 @@ import de.robv.android.xposed.XposedHelpers;
|
||||
import de.robv.android.xposed.callbacks.XC_LoadPackage;
|
||||
|
||||
/**
|
||||
* MariBank / SeaBank PH(ph.seabank.seabank)Root 检测绕过。
|
||||
* 逆向:SafeMode SDK + SHPSSDK;检测到 Root 后会 Toast 并 Process.killProcess 自杀。
|
||||
* MariBank / SeaBank Root 检测绕过(PH + SG)。
|
||||
* 逆向:SafeMode SDK + SHPSSDK;SG 额外有 USB/无线 ADB 检测(RISK_USB_ADB / RISK_WIFI_ADB)。
|
||||
*/
|
||||
public final class MariBankRootBypassHook {
|
||||
|
||||
private static final String TAG = "notiMessageHook/MariBankRoot";
|
||||
/** 菲律宾 MariBank / SeaBank PH */
|
||||
public static final String PACKAGE = "ph.seabank.seabank";
|
||||
/** 新加坡 MariBank */
|
||||
public static final String PACKAGE_SG = "sg.com.maribankmobile.digitalbank";
|
||||
|
||||
private static final String[] TARGET_PACKAGES = {PACKAGE, PACKAGE_SG};
|
||||
|
||||
public static boolean isTargetPackage(String packageName) {
|
||||
if (packageName == null) {
|
||||
return false;
|
||||
}
|
||||
for (String pkg : TARGET_PACKAGES) {
|
||||
if (pkg.equals(packageName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** 服务端注册被拒错误码(logcat 实测)。 */
|
||||
private static final int ERROR_CODE_SECURITY_BLOCKED = 4067004;
|
||||
@@ -56,18 +74,21 @@ public final class MariBankRootBypassHook {
|
||||
"com.shopee.bke.biz.user.errorcodehandler.a",
|
||||
"com.shopee.bke.biz.user.errorcodehandler.b",
|
||||
"com.shopee.bke.biz.user.rn.helper.ErrorFlowHelper",
|
||||
"com.shopee.bke.biz.user.viewmodel.RegisterViewModel",
|
||||
};
|
||||
|
||||
private MariBankRootBypassHook() {
|
||||
}
|
||||
|
||||
private static volatile boolean deferredHooksInstalled = false;
|
||||
private static volatile boolean lateAppHooksInstalled = false;
|
||||
|
||||
public static void install(XC_LoadPackage.LoadPackageParam lpparam) {
|
||||
if (!PACKAGE.equals(lpparam.packageName)) {
|
||||
if (!isTargetPackage(lpparam.packageName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
XposedBridge.log(TAG + " install for " + lpparam.packageName);
|
||||
hookAntiSuicide(lpparam);
|
||||
hookAntiSoftCrash(lpparam);
|
||||
scheduleAppHooks(lpparam);
|
||||
@@ -85,6 +106,13 @@ public final class MariBankRootBypassHook {
|
||||
MariBankShpsNativeHook.installDeferred(lpparam);
|
||||
}
|
||||
};
|
||||
XC_MethodHook afterOnCreate = new XC_MethodHook() {
|
||||
@Override
|
||||
protected void afterHookedMethod(MethodHookParam param) {
|
||||
MariBankShpsNativeHook.installLateNativeHooks(lpparam);
|
||||
installLateAppHooks(lpparam);
|
||||
}
|
||||
};
|
||||
try {
|
||||
XposedHelpers.findAndHookMethod(
|
||||
"com.shopee.bke.digitalbank.BkeApplication",
|
||||
@@ -92,36 +120,54 @@ public final class MariBankRootBypassHook {
|
||||
"attachBaseContext",
|
||||
"android.content.Context",
|
||||
afterAttach);
|
||||
XposedBridge.log(TAG + " waiting attachBaseContext for app hooks");
|
||||
XposedHelpers.findAndHookMethod(
|
||||
"com.shopee.bke.digitalbank.BkeApplication",
|
||||
lpparam.classLoader,
|
||||
"onCreate",
|
||||
afterOnCreate);
|
||||
XposedBridge.log(TAG + " waiting attachBaseContext + onCreate for app hooks");
|
||||
} catch (Throwable t) {
|
||||
XposedBridge.log(TAG + " attachBaseContext hook failed, install now: " + t.getMessage());
|
||||
XposedBridge.log(TAG + " BkeApplication hook failed, install now: " + t.getMessage());
|
||||
installDeferredHooks(lpparam);
|
||||
MariBankShpsNativeHook.installDeferred(lpparam);
|
||||
MariBankShpsNativeHook.installLateNativeHooks(lpparam);
|
||||
installLateAppHooks(lpparam);
|
||||
}
|
||||
}
|
||||
|
||||
/** onCreate 之后补装:此时 classes11 / SHPSSDK 与 RN SO 均已就绪。 */
|
||||
private static void installLateAppHooks(XC_LoadPackage.LoadPackageParam lpparam) {
|
||||
if (lateAppHooksInstalled) {
|
||||
return;
|
||||
}
|
||||
lateAppHooksInstalled = true;
|
||||
|
||||
int hooked = 0;
|
||||
for (String className : SAFE_MODE_CLASSES) {
|
||||
hooked += hookAllBooleanChecks(lpparam, className);
|
||||
}
|
||||
hooked += hookShpsRisk(lpparam);
|
||||
hookShpsToken(lpparam);
|
||||
hookErrorFlowLogging(lpparam);
|
||||
MariBankSdkUtilsHook.installLate(lpparam);
|
||||
MariBankAttestationHook.installLate(lpparam);
|
||||
|
||||
XposedBridge.log(TAG + " late app hooks installed, booleanHooks=" + hooked);
|
||||
}
|
||||
|
||||
private static void installDeferredHooks(XC_LoadPackage.LoadPackageParam lpparam) {
|
||||
if (deferredHooksInstalled) {
|
||||
return;
|
||||
}
|
||||
deferredHooksInstalled = true;
|
||||
|
||||
int hooked = 0;
|
||||
for (String className : SAFE_MODE_CLASSES) {
|
||||
hooked += hookAllBooleanChecks(lpparam, className);
|
||||
}
|
||||
|
||||
hookSafeModeDialog(lpparam);
|
||||
hookRootDialogBlock(lpparam);
|
||||
hookErrorFlowLogging(lpparam);
|
||||
hooked += hookShpsRisk(lpparam);
|
||||
hookShpsToken(lpparam);
|
||||
hookAdbBypass(lpparam);
|
||||
hookNetworkLogging(lpparam);
|
||||
|
||||
XposedBridge.log(TAG + " app hooks installed, booleanHooks=" + hooked);
|
||||
XposedBridge.log(TAG + " early app hooks installed");
|
||||
}
|
||||
|
||||
/** SafeMode 类方法名被混淆,Hook 所有返回 boolean/int 的实例方法。 */
|
||||
private static int hookAllBooleanChecks(XC_LoadPackage.LoadPackageParam lpparam, String className) {
|
||||
int count = 0;
|
||||
try {
|
||||
@@ -416,7 +462,9 @@ public final class MariBankRootBypassHook {
|
||||
}
|
||||
String args = Arrays.toString(param.args);
|
||||
if (args.contains("1201") || args.contains("-1201")
|
||||
|| args.toLowerCase().contains("error")) {
|
||||
|| args.contains("406")
|
||||
|| args.toLowerCase().contains("error")
|
||||
|| args.toLowerCase().contains("unavailable")) {
|
||||
XposedBridge.log(TAG + " " + className + "."
|
||||
+ method.getName() + " args=" + args);
|
||||
}
|
||||
@@ -903,12 +951,17 @@ public final class MariBankRootBypassHook {
|
||||
body = sanitized;
|
||||
}
|
||||
String lower = body.toLowerCase();
|
||||
if (lower.contains("blocked")
|
||||
String url = CURRENT_REQUEST_URL.get();
|
||||
boolean maribankApi = url != null
|
||||
&& (url.contains("maribank.com") || url.contains("seabank.ph"));
|
||||
boolean interesting = lower.contains("blocked")
|
||||
|| body.contains(String.valueOf(ERROR_CODE_SECURITY_BLOCKED))
|
||||
|| body.contains(String.valueOf(ERROR_CODE_SECURITY_BLOCKED_ALT))
|
||||
|| lower.contains("risktoken")
|
||||
|| lower.contains("\"code\"")) {
|
||||
String url = CURRENT_REQUEST_URL.get();
|
||||
|| lower.contains("\"code\"")
|
||||
|| (maribankApi && (lower.contains("register")
|
||||
|| lower.contains("error") || lower.contains("unavailable")));
|
||||
if (interesting) {
|
||||
String snippet = body.length() > 600
|
||||
? body.substring(0, 600) + "..." : body;
|
||||
XposedBridge.log(TAG + " HTTP"
|
||||
@@ -1035,6 +1088,20 @@ public final class MariBankRootBypassHook {
|
||||
if (sanitized != request) {
|
||||
XposedHelpers.setObjectField(param.thisObject, "originalRequest", sanitized);
|
||||
}
|
||||
try {
|
||||
Object req = XposedHelpers.getObjectField(param.thisObject, "originalRequest");
|
||||
if (req != null) {
|
||||
Object url = XposedHelpers.callMethod(req, "url");
|
||||
if (url != null) {
|
||||
String urlStr = String.valueOf(url);
|
||||
if (urlStr.contains("maribank.com") || urlStr.contains("seabank.ph")
|
||||
|| urlStr.contains("/register")) {
|
||||
XposedBridge.log(TAG + " outbound " + urlStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}
|
||||
@@ -1516,6 +1583,139 @@ public final class MariBankRootBypassHook {
|
||||
}
|
||||
}
|
||||
|
||||
/** SG:ADB / 无线调试检测 + Root 弹窗/Toast/全屏页拦截。 */
|
||||
private static void hookAdbBypass(XC_LoadPackage.LoadPackageParam lpparam) {
|
||||
hookAdbSettings(lpparam);
|
||||
hookAdbActivityEscape(lpparam);
|
||||
}
|
||||
|
||||
private static void hookAdbSettings(XC_LoadPackage.LoadPackageParam lpparam) {
|
||||
XC_MethodHook fakeDisabled = new XC_MethodHook() {
|
||||
@Override
|
||||
protected void beforeHookedMethod(MethodHookParam param) {
|
||||
if (param.args.length < 2 || !(param.args[1] instanceof String)) {
|
||||
return;
|
||||
}
|
||||
String key = (String) param.args[1];
|
||||
if (!isAdbSettingKey(key)) {
|
||||
return;
|
||||
}
|
||||
Class<?> ret = ((Method) param.method).getReturnType();
|
||||
if (ret == int.class || ret == Integer.class) {
|
||||
param.setResult(0);
|
||||
} else if (ret == long.class || ret == Long.class) {
|
||||
param.setResult(0L);
|
||||
} else if (ret == String.class) {
|
||||
param.setResult("0");
|
||||
}
|
||||
XposedBridge.log(TAG + " faked Settings key=" + key);
|
||||
}
|
||||
};
|
||||
|
||||
String[][] targets = {
|
||||
{"android.provider.Settings$Global", "getInt"},
|
||||
{"android.provider.Settings$Global", "getLong"},
|
||||
{"android.provider.Settings$Global", "getString"},
|
||||
{"android.provider.Settings$Secure", "getInt"},
|
||||
{"android.provider.Settings$Secure", "getString"},
|
||||
{"android.provider.Settings$System", "getInt"},
|
||||
};
|
||||
for (String[] target : targets) {
|
||||
try {
|
||||
Class<?> clazz = XposedHelpers.findClass(target[0], lpparam.classLoader);
|
||||
for (Method method : clazz.getDeclaredMethods()) {
|
||||
if (!target[1].equals(method.getName())) {
|
||||
continue;
|
||||
}
|
||||
Class<?>[] params = method.getParameterTypes();
|
||||
if (params.length >= 2 && ContentResolver.class.isAssignableFrom(params[0])
|
||||
&& params[1] == String.class) {
|
||||
XposedBridge.hookMethod(method, fakeDisabled);
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
XposedBridge.log(TAG + " skip Settings hook " + target[0] + ": " + t.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 若全屏/RN 页已展示 ADB 拦截文案,直接 finish 退出该 Activity。 */
|
||||
private static void hookAdbActivityEscape(XC_LoadPackage.LoadPackageParam lpparam) {
|
||||
try {
|
||||
XposedHelpers.findAndHookMethod(
|
||||
Activity.class,
|
||||
"onResume",
|
||||
new XC_MethodHook() {
|
||||
@Override
|
||||
protected void afterHookedMethod(MethodHookParam param) {
|
||||
Activity activity = (Activity) param.thisObject;
|
||||
if (activity == null || activity.isFinishing()) {
|
||||
return;
|
||||
}
|
||||
String name = activity.getClass().getName();
|
||||
if (name.contains("SafeModeRecoverActivity")) {
|
||||
return;
|
||||
}
|
||||
String text = extractActivityText(activity);
|
||||
if (isAdbBlockText(text)) {
|
||||
XposedBridge.log(TAG + " finish adb block activity: " + name);
|
||||
activity.finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
} catch (Throwable t) {
|
||||
XposedBridge.log(TAG + " adb activity hook failed: " + t.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static String extractActivityText(Activity activity) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
try {
|
||||
CharSequence title = activity.getTitle();
|
||||
if (title != null) {
|
||||
sb.append(title);
|
||||
}
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
try {
|
||||
if (activity.getWindow() != null) {
|
||||
collectTextViews(activity.getWindow().getDecorView(), sb);
|
||||
}
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static boolean isAdbSettingKey(String key) {
|
||||
if (key == null) {
|
||||
return false;
|
||||
}
|
||||
String lower = key.toLowerCase();
|
||||
return lower.contains("adb")
|
||||
|| "development_settings_enabled".equals(lower)
|
||||
|| lower.contains("wireless_debug");
|
||||
}
|
||||
|
||||
private static boolean isAdbBlockText(String text) {
|
||||
if (text == null || text.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
String lower = text.toLowerCase();
|
||||
return lower.contains("adb/wireless adb")
|
||||
|| lower.contains("wireless adb detected")
|
||||
|| lower.contains("usb debugging")
|
||||
|| lower.contains("wireless debugging")
|
||||
|| lower.contains("turn off adb")
|
||||
|| lower.contains("third parties to access")
|
||||
|| lower.contains("safeguard your banking")
|
||||
|| (lower.contains("adb") && lower.contains("detect"));
|
||||
}
|
||||
|
||||
private static boolean isEnvironmentBlockText(String text) {
|
||||
return isRootBlockText(text) || isAdbBlockText(text);
|
||||
}
|
||||
|
||||
private static void hookSafeModeDialog(XC_LoadPackage.LoadPackageParam lpparam) {
|
||||
try {
|
||||
XposedHelpers.findAndHookMethod(
|
||||
@@ -1540,9 +1740,9 @@ public final class MariBankRootBypassHook {
|
||||
XC_MethodHook blankRootTextHook = new XC_MethodHook() {
|
||||
@Override
|
||||
protected void beforeHookedMethod(MethodHookParam param) {
|
||||
if (param.args.length > 0 && isRootBlockText(String.valueOf(param.args[0]))) {
|
||||
if (param.args.length > 0 && isEnvironmentBlockText(String.valueOf(param.args[0]))) {
|
||||
param.args[0] = " ";
|
||||
XposedBridge.log(TAG + " blanked root dialog message");
|
||||
XposedBridge.log(TAG + " blanked env block dialog message");
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1574,9 +1774,9 @@ public final class MariBankRootBypassHook {
|
||||
@Override
|
||||
protected void afterHookedMethod(MethodHookParam param) {
|
||||
String s = (String) param.getResult();
|
||||
if (isRootBlockText(s)) {
|
||||
if (isEnvironmentBlockText(s)) {
|
||||
param.setResult(" ");
|
||||
XposedBridge.log(TAG + " blanked root string resource");
|
||||
XposedBridge.log(TAG + " blanked env block string resource");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1593,8 +1793,8 @@ public final class MariBankRootBypassHook {
|
||||
@Override
|
||||
protected void beforeHookedMethod(MethodHookParam param) {
|
||||
Dialog dialog = (Dialog) param.thisObject;
|
||||
if (isRootBlockText(extractDialogText(dialog))) {
|
||||
XposedBridge.log(TAG + " blocked root Dialog.show: "
|
||||
if (isEnvironmentBlockText(extractDialogText(dialog))) {
|
||||
XposedBridge.log(TAG + " blocked env Dialog.show: "
|
||||
+ dialog.getClass().getSimpleName());
|
||||
param.setResult(null);
|
||||
}
|
||||
@@ -1620,6 +1820,9 @@ public final class MariBankRootBypassHook {
|
||||
if (isRootBlockText(text)) {
|
||||
XposedBridge.log(TAG + " blocked root Toast.show");
|
||||
param.setResult(null);
|
||||
} else if (isAdbBlockText(text)) {
|
||||
XposedBridge.log(TAG + " blocked adb Toast.show");
|
||||
param.setResult(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1638,7 +1841,9 @@ public final class MariBankRootBypassHook {
|
||||
|| lower.contains("modified device")
|
||||
|| lower.contains("magisk/xposed/frida")
|
||||
|| lower.contains("cannot be accessed on such devices")
|
||||
|| lower.contains("restore to factory settings");
|
||||
|| lower.contains("restore to factory settings")
|
||||
|| lower.contains("does not support root")
|
||||
|| lower.contains("support root device");
|
||||
}
|
||||
|
||||
private static boolean isSecurityBlockText(String text) {
|
||||
|
||||
@@ -0,0 +1,225 @@
|
||||
package com.miraclegarden.smsmessage.xposed.hook;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import de.robv.android.xposed.XC_MethodHook;
|
||||
import de.robv.android.xposed.XposedBridge;
|
||||
import de.robv.android.xposed.XposedHelpers;
|
||||
import de.robv.android.xposed.callbacks.XC_LoadPackage;
|
||||
|
||||
/**
|
||||
* register body 加密前 Hook:{@code com.shopee.bke.lib.jni.utils.d} / {@code uvwuvwuv}。
|
||||
* 勿 Hook {@code utils.f}(SoUtils),否则会 libsdkutils 白屏。
|
||||
*/
|
||||
public final class MariBankSdkUtilsHook {
|
||||
|
||||
private static final String TAG = "notiMessageHook/MariBankEncrypt";
|
||||
private static final int MAX_LOG = 2000;
|
||||
|
||||
private static final String WRAPPER = "com.shopee.bke.lib.jni.utils.d";
|
||||
private static final String NATIVE_ENCRYPT = "com.shopee.bke.lib.jni.utils.uvwuvwuv";
|
||||
|
||||
private static volatile boolean installed = false;
|
||||
|
||||
private MariBankSdkUtilsHook() {
|
||||
}
|
||||
|
||||
/** BkeApplication.onCreate 之后安装(libsdkutils 已加载)。 */
|
||||
public static void installLate(XC_LoadPackage.LoadPackageParam lpparam) {
|
||||
if (installed) {
|
||||
return;
|
||||
}
|
||||
installed = true;
|
||||
int n = hookEncryptWrapper(lpparam);
|
||||
n += hookNativeEncryptUtils(lpparam);
|
||||
n += hookGsonRegister(lpparam);
|
||||
XposedBridge.log(TAG + " late encrypt hooks=" + n);
|
||||
}
|
||||
|
||||
private static int hookEncryptWrapper(XC_LoadPackage.LoadPackageParam lpparam) {
|
||||
int count = 0;
|
||||
try {
|
||||
Class<?> clazz = XposedHelpers.findClass(WRAPPER, lpparam.classLoader);
|
||||
for (Method method : clazz.getDeclaredMethods()) {
|
||||
if (Modifier.isStatic(method.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
XposedBridge.hookMethod(method, new XC_MethodHook() {
|
||||
@Override
|
||||
protected void beforeHookedMethod(MethodHookParam param) {
|
||||
String name = method.getName();
|
||||
XposedBridge.log(TAG + " >> utils.d." + name);
|
||||
for (int i = 0; i < param.args.length; i++) {
|
||||
Object sanitized = sanitizeArg(param.args[i]);
|
||||
if (sanitized != param.args[i]) {
|
||||
param.args[i] = sanitized;
|
||||
}
|
||||
logArg(" in" + i, param.args[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void afterHookedMethod(MethodHookParam param) {
|
||||
Object result = param.getResult();
|
||||
if (result == null) {
|
||||
return;
|
||||
}
|
||||
if (result instanceof String[]) {
|
||||
for (int i = 0; i < ((String[]) result).length; i++) {
|
||||
logArg(" out" + i, ((String[]) result)[i]);
|
||||
}
|
||||
} else if (result instanceof byte[]) {
|
||||
logArg(" out", result);
|
||||
}
|
||||
}
|
||||
});
|
||||
count++;
|
||||
}
|
||||
if (count > 0) {
|
||||
XposedBridge.log(TAG + " hooked utils.d methods=" + count);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
XposedBridge.log(TAG + " skip utils.d: " + t.getMessage());
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private static int hookNativeEncryptUtils(XC_LoadPackage.LoadPackageParam lpparam) {
|
||||
int count = 0;
|
||||
try {
|
||||
Class<?> clazz = XposedHelpers.findClass(NATIVE_ENCRYPT, lpparam.classLoader);
|
||||
for (Method method : clazz.getDeclaredMethods()) {
|
||||
if (!Modifier.isStatic(method.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
XposedBridge.hookMethod(method, new XC_MethodHook() {
|
||||
@Override
|
||||
protected void beforeHookedMethod(MethodHookParam param) {
|
||||
XposedBridge.log(TAG + " >> uvwuvwuv." + method.getName());
|
||||
for (int i = 0; i < param.args.length; i++) {
|
||||
Object sanitized = sanitizeArg(param.args[i]);
|
||||
if (sanitized != param.args[i]) {
|
||||
param.args[i] = sanitized;
|
||||
}
|
||||
logArg(" in" + i, param.args[i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
count++;
|
||||
}
|
||||
if (count > 0) {
|
||||
XposedBridge.log(TAG + " hooked uvwuvwuv methods=" + count);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
XposedBridge.log(TAG + " skip uvwuvwuv: " + t.getMessage());
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private static int hookGsonRegister(XC_LoadPackage.LoadPackageParam lpparam) {
|
||||
try {
|
||||
XposedHelpers.findAndHookMethod(
|
||||
"com.google.gson.Gson",
|
||||
lpparam.classLoader,
|
||||
"toJson",
|
||||
Object.class,
|
||||
new XC_MethodHook() {
|
||||
@Override
|
||||
protected void afterHookedMethod(MethodHookParam param) {
|
||||
if (!(param.getResult() instanceof String)) {
|
||||
return;
|
||||
}
|
||||
String json = (String) param.getResult();
|
||||
if (!looksLikeRegisterJson(json)) {
|
||||
return;
|
||||
}
|
||||
String sanitized = MariBankRegisterPayloadUtil.isRegistrationPayload(json)
|
||||
? MariBankRegisterPayloadUtil.sanitizeRegistrationJson(json)
|
||||
: MariBankRiskTokenUtil.sanitizeAllInText(json);
|
||||
if (!sanitized.equals(json)) {
|
||||
param.setResult(sanitized);
|
||||
json = sanitized;
|
||||
}
|
||||
if (MariBankRegisterPayloadUtil.isRegistrationPayload(json)) {
|
||||
XposedBridge.log(TAG + " Gson REGISTRATION: " + truncate(json));
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
return 1;
|
||||
} catch (Throwable t) {
|
||||
XposedBridge.log(TAG + " skip Gson.toJson: " + t.getMessage());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean looksLikeRegisterJson(String text) {
|
||||
if (text == null || text.length() < 8) {
|
||||
return false;
|
||||
}
|
||||
if (MariBankRegisterPayloadUtil.isRegistrationPayload(text)) {
|
||||
return true;
|
||||
}
|
||||
String lower = text.toLowerCase();
|
||||
return lower.contains("rdverifyinfo")
|
||||
|| lower.contains("devicefingerprint")
|
||||
|| (lower.contains("encphone") && lower.contains("scene"));
|
||||
}
|
||||
|
||||
private static Object sanitizeArg(Object arg) {
|
||||
if (arg instanceof String) {
|
||||
String s = (String) arg;
|
||||
if (!s.contains("|") && !looksLikeRegisterJson(s)) {
|
||||
return arg;
|
||||
}
|
||||
String out = MariBankRegisterPayloadUtil.isRegistrationPayload(s)
|
||||
? MariBankRegisterPayloadUtil.sanitizeRegistrationJson(s)
|
||||
: MariBankRiskTokenUtil.sanitizeAllInText(s);
|
||||
return out.equals(s) ? arg : out;
|
||||
}
|
||||
if (arg instanceof byte[]) {
|
||||
byte[] bytes = (byte[]) arg;
|
||||
byte[] out = MariBankRegisterPayloadUtil.sanitizeRegistrationBytes(bytes);
|
||||
return out == bytes ? arg : out;
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
||||
private static void logArg(String label, Object arg) {
|
||||
if (arg == null) {
|
||||
XposedBridge.log(TAG + label + " null");
|
||||
return;
|
||||
}
|
||||
if (arg instanceof String) {
|
||||
String s = (String) arg;
|
||||
if (s.length() > 4 || s.contains("|") || looksLikeRegisterJson(s)) {
|
||||
XposedBridge.log(TAG + label + " String(" + s.length() + ") " + truncate(s));
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (arg instanceof byte[]) {
|
||||
byte[] bytes = (byte[]) arg;
|
||||
String text;
|
||||
try {
|
||||
text = new String(bytes, StandardCharsets.UTF_8);
|
||||
} catch (Throwable t) {
|
||||
text = "<bin>";
|
||||
}
|
||||
if (text.contains("|") || looksLikeRegisterJson(text) || bytes.length < 512) {
|
||||
XposedBridge.log(TAG + label + " byte[" + bytes.length + "] " + truncate(text));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String truncate(String s) {
|
||||
if (s == null) {
|
||||
return "";
|
||||
}
|
||||
if (s.length() <= MAX_LOG) {
|
||||
return s;
|
||||
}
|
||||
return s.substring(0, MAX_LOG) + "...";
|
||||
}
|
||||
}
|
||||
@@ -72,6 +72,15 @@ public final class MariBankShpsNativeHook {
|
||||
}
|
||||
|
||||
private static volatile boolean deferredInstalled = false;
|
||||
private static volatile boolean lateNativeInstalled = false;
|
||||
|
||||
/**
|
||||
* 勿 Hook:负责 SoUtils.loadSoLibrary / libshpssdk_bank.so 加载,Hook 会导致 SO 找不到。
|
||||
*/
|
||||
private static final Set<String> NATIVE_BRIDGE_EXCLUDED = new HashSet<>(Arrays.asList(
|
||||
"com.shopee.shpssdkbank.vuvuwwwuw",
|
||||
"com.shopee.shpssdkbank.vwuuwwvwv"
|
||||
));
|
||||
|
||||
/** loadPackage 阶段只装 /proc 过滤,避免过早触发 SHPSSDK / libsdkutils 死循环白屏。 */
|
||||
public static void install(XC_LoadPackage.LoadPackageParam lpparam) {
|
||||
@@ -82,21 +91,28 @@ public final class MariBankShpsNativeHook {
|
||||
XposedBridge.log(TAG + " early hooks OK (proc only)");
|
||||
}
|
||||
|
||||
/** attachBaseContext 之后安装 SHPSSDK 相关 Hook(ClassLoader 已就绪)。 */
|
||||
/** attachBaseContext 之后:仅装不干扰 SO/RN 加载的 Hook。 */
|
||||
public static void installDeferred(XC_LoadPackage.LoadPackageParam lpparam) {
|
||||
if (deferredInstalled) {
|
||||
return;
|
||||
}
|
||||
deferredInstalled = true;
|
||||
hookLoadLibrary(lpparam);
|
||||
hookShpssInstall(lpparam);
|
||||
hookRequestDefense(lpparam);
|
||||
hookShpsNativeBridge(lpparam);
|
||||
hookShpsNativeCore(lpparam);
|
||||
hookBuildFields(lpparam);
|
||||
XposedBridge.log(TAG + " deferred hooks installed for " + lpparam.packageName);
|
||||
}
|
||||
|
||||
/** BkeApplication.onCreate 之后:RN / shpssdk SO 已加载,再装 native 桥接 Hook。 */
|
||||
public static void installLateNativeHooks(XC_LoadPackage.LoadPackageParam lpparam) {
|
||||
if (lateNativeInstalled) {
|
||||
return;
|
||||
}
|
||||
lateNativeInstalled = true;
|
||||
hookShpsNativeBridge(lpparam);
|
||||
hookShpsNativeCore(lpparam);
|
||||
XposedBridge.log(TAG + " late native hooks installed for " + lpparam.packageName);
|
||||
}
|
||||
|
||||
/** native 直接读 /proc/self/maps 查 hook 库;过滤内容。 */
|
||||
private static void hookProcAccess(XC_LoadPackage.LoadPackageParam lpparam) {
|
||||
try {
|
||||
@@ -233,32 +249,7 @@ public final class MariBankShpsNativeHook {
|
||||
return "";
|
||||
}
|
||||
|
||||
private static void hookLoadLibrary(XC_LoadPackage.LoadPackageParam lpparam) {
|
||||
XC_MethodHook logHook = new XC_MethodHook() {
|
||||
@Override
|
||||
protected void beforeHookedMethod(MethodHookParam param) {
|
||||
String lib = String.valueOf(param.args[param.args.length - 1]);
|
||||
if (lib.contains("shpssdk")) {
|
||||
XposedBridge.log(TAG + " loading native lib: " + lib);
|
||||
}
|
||||
}
|
||||
};
|
||||
try {
|
||||
XposedHelpers.findAndHookMethod(
|
||||
Runtime.class, "loadLibrary0", ClassLoader.class, String.class, logHook);
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
try {
|
||||
XposedHelpers.findAndHookMethod(
|
||||
System.class, "loadLibrary", String.class, logHook);
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
private static void hookShpssInstall(XC_LoadPackage.LoadPackageParam lpparam) {
|
||||
// 勿 Hook ShpssInstall / vuvuwwwuw:会干扰 SoUtils.loadSoLibrary,导致 libsdkutils.so 死循环白屏。
|
||||
}
|
||||
|
||||
/** 保留 requestDefense 执行(生成 x-sap-fixme),仅净化返回值中的 risk 字段。 */
|
||||
private static void hookRequestDefense(XC_LoadPackage.LoadPackageParam lpparam) {
|
||||
for (String className : new String[]{
|
||||
"com.shopee.shpssdkbank.SHPSSDK",
|
||||
@@ -271,9 +262,26 @@ public final class MariBankShpsNativeHook {
|
||||
"requestDefense",
|
||||
new XC_MethodHook() {
|
||||
@Override
|
||||
protected void beforeHookedMethod(MethodHookParam param) {
|
||||
XposedBridge.log(TAG + " blocked requestDefense");
|
||||
param.setResult(null);
|
||||
protected void afterHookedMethod(MethodHookParam param) {
|
||||
Object result = param.getResult();
|
||||
if (result instanceof String) {
|
||||
String s = (String) result;
|
||||
if (s.contains("|")) {
|
||||
String sanitized = MariBankRiskTokenUtil.sanitizeRiskToken(s);
|
||||
if (!sanitized.equals(s)) {
|
||||
param.setResult(sanitized);
|
||||
XposedBridge.log(TAG + " requestDefense String sanitized");
|
||||
}
|
||||
}
|
||||
} else if (result instanceof byte[]) {
|
||||
byte[] bytes = (byte[]) result;
|
||||
byte[] out = MariBankRiskTokenUtil.sanitizeBytes(
|
||||
bytes, 0, bytes.length);
|
||||
if (out != bytes) {
|
||||
param.setResult(out);
|
||||
XposedBridge.log(TAG + " requestDefense byte[] sanitized");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -304,6 +312,10 @@ public final class MariBankShpsNativeHook {
|
||||
};
|
||||
int total = 0;
|
||||
for (String className : classes) {
|
||||
if (NATIVE_BRIDGE_EXCLUDED.contains(className)) {
|
||||
XposedBridge.log(TAG + " skip native-bridge (so loader): " + className);
|
||||
continue;
|
||||
}
|
||||
total += hookAllIntBooleanMethods(lpparam, className);
|
||||
total += hookAllStringSanitize(lpparam, className);
|
||||
}
|
||||
@@ -360,6 +372,10 @@ public final class MariBankShpsNativeHook {
|
||||
&& rt != int.class && rt != Integer.class) {
|
||||
continue;
|
||||
}
|
||||
if (Modifier.isNative(method.getModifiers()) && rt != boolean.class
|
||||
&& rt != Boolean.class && rt != int.class && rt != Integer.class) {
|
||||
continue;
|
||||
}
|
||||
if (method.getParameterTypes().length > 4) {
|
||||
continue;
|
||||
}
|
||||
@@ -409,6 +425,9 @@ public final class MariBankShpsNativeHook {
|
||||
if (!Modifier.isStatic(method.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
if (Modifier.isNative(method.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
Class<?> rt = method.getReturnType();
|
||||
if (rt == String.class) {
|
||||
XposedBridge.hookMethod(method, new XC_MethodHook() {
|
||||
@@ -547,6 +566,15 @@ public final class MariBankShpsNativeHook {
|
||||
if ("ro.debuggable".equals(key)) {
|
||||
return "0";
|
||||
}
|
||||
if ("init.svc.adbd".equals(key) || "init.svc.adb".equals(key)) {
|
||||
return "stopped";
|
||||
}
|
||||
if ("service.adb.root".equals(key)) {
|
||||
return "0";
|
||||
}
|
||||
if ("persist.sys.adb_enable".equals(key)) {
|
||||
return "0";
|
||||
}
|
||||
if ("ro.secure".equals(key)) {
|
||||
return "1";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user