Merge branch 'master' of https://github.com/ElderDrivers/EdXposed
This commit is contained in:
commit
57fd982979
|
|
@ -34,36 +34,32 @@ public class Main implements KeepAll {
|
|||
int[][] rlimits, int mountExternal, String seInfo,
|
||||
String niceName, int[] fdsToClose, int[] fdsToIgnore,
|
||||
boolean startChildZygote, String instructionSet,
|
||||
String appDataDir, boolean isBlackWhiteListMode,
|
||||
boolean isDynamicModulesMode) {
|
||||
String appDataDir) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
forkAndSpecializePramsStr = String.format(
|
||||
"Zygote#forkAndSpecialize(%d, %d, %s, %d, %s, %d, %s, %s, %s, %s, %s, %s, %s)",
|
||||
uid, gid, Arrays.toString(gids), debugFlags, Arrays.toString(rlimits),
|
||||
mountExternal, seInfo, niceName, Arrays.toString(fdsToClose),
|
||||
Arrays.toString(fdsToIgnore), startChildZygote, instructionSet, appDataDir,
|
||||
isDynamicModulesMode);
|
||||
Arrays.toString(fdsToIgnore), startChildZygote, instructionSet, appDataDir);
|
||||
}
|
||||
if (isBlackWhiteListMode) {
|
||||
if (isBlackWhiteListEnabled()) {
|
||||
BlackWhiteListProxy.forkAndSpecializePre(uid, gid, gids, debugFlags, rlimits,
|
||||
mountExternal, seInfo, niceName, fdsToClose, fdsToIgnore, startChildZygote,
|
||||
instructionSet, appDataDir, isDynamicModulesMode);
|
||||
instructionSet, appDataDir);
|
||||
} else {
|
||||
NormalProxy.forkAndSpecializePre(uid, gid, gids, debugFlags, rlimits, mountExternal,
|
||||
seInfo, niceName, fdsToClose, fdsToIgnore, startChildZygote, instructionSet,
|
||||
appDataDir, isDynamicModulesMode);
|
||||
appDataDir);
|
||||
}
|
||||
}
|
||||
|
||||
public static void forkAndSpecializePost(int pid, String appDataDir,
|
||||
boolean isBlackWhiteListMode,
|
||||
boolean isDynamicModulesMode) {
|
||||
public static void forkAndSpecializePost(int pid, String appDataDir) {
|
||||
if (pid == 0) {
|
||||
Utils.logD(forkAndSpecializePramsStr + " = " + Process.myPid());
|
||||
if (isBlackWhiteListMode) {
|
||||
BlackWhiteListProxy.forkAndSpecializePost(pid, appDataDir, isDynamicModulesMode);
|
||||
if (isBlackWhiteListEnabled()) {
|
||||
BlackWhiteListProxy.forkAndSpecializePost(pid, appDataDir);
|
||||
} else {
|
||||
NormalProxy.forkAndSpecializePost(pid, appDataDir, isDynamicModulesMode);
|
||||
NormalProxy.forkAndSpecializePost(pid, appDataDir);
|
||||
}
|
||||
} else {
|
||||
// in zygote process, res is child zygote pid
|
||||
|
|
@ -72,30 +68,28 @@ public class Main implements KeepAll {
|
|||
}
|
||||
|
||||
public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits,
|
||||
long permittedCapabilities, long effectiveCapabilities,
|
||||
boolean isBlackWhiteListMode, boolean isDynamicModulesMode) {
|
||||
long permittedCapabilities, long effectiveCapabilities) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
forkSystemServerPramsStr = String.format("Zygote#forkSystemServer(%d, %d, %s, %d, %s, %d, %d)",
|
||||
uid, gid, Arrays.toString(gids), debugFlags, Arrays.toString(rlimits),
|
||||
permittedCapabilities, effectiveCapabilities);
|
||||
}
|
||||
if (isBlackWhiteListMode) {
|
||||
if (isBlackWhiteListEnabled()) {
|
||||
BlackWhiteListProxy.forkSystemServerPre(uid, gid, gids, debugFlags, rlimits,
|
||||
permittedCapabilities, effectiveCapabilities, isDynamicModulesMode);
|
||||
permittedCapabilities, effectiveCapabilities);
|
||||
} else {
|
||||
NormalProxy.forkSystemServerPre(uid, gid, gids, debugFlags, rlimits,
|
||||
permittedCapabilities, effectiveCapabilities, isDynamicModulesMode);
|
||||
permittedCapabilities, effectiveCapabilities);
|
||||
}
|
||||
}
|
||||
|
||||
public static void forkSystemServerPost(int pid, boolean isBlackWhiteListMode,
|
||||
boolean isDynamicModulesMode) {
|
||||
public static void forkSystemServerPost(int pid) {
|
||||
if (pid == 0) {
|
||||
Utils.logD(forkSystemServerPramsStr + " = " + Process.myPid());
|
||||
if (isBlackWhiteListMode) {
|
||||
BlackWhiteListProxy.forkSystemServerPost(pid, isDynamicModulesMode);
|
||||
if (isBlackWhiteListEnabled()) {
|
||||
BlackWhiteListProxy.forkSystemServerPost(pid);
|
||||
} else {
|
||||
NormalProxy.forkSystemServerPost(pid, isDynamicModulesMode);
|
||||
NormalProxy.forkSystemServerPost(pid);
|
||||
}
|
||||
} else {
|
||||
// in zygote process, res is child zygote pid
|
||||
|
|
@ -118,6 +112,10 @@ public class Main implements KeepAll {
|
|||
|
||||
public static native String getInstallerPkgName();
|
||||
|
||||
public static native boolean isBlackWhiteListEnabled();
|
||||
|
||||
public static native boolean isDynamicModulesEnabled();
|
||||
|
||||
// prevent from fatal error caused by holding not whitelisted file descriptors when forking zygote
|
||||
// https://github.com/rovo89/Xposed/commit/b3ba245ad04cd485699fb1d2ebde7117e58214ff
|
||||
public static native void closeFilesBeforeForkNative();
|
||||
|
|
@ -125,4 +123,8 @@ public class Main implements KeepAll {
|
|||
public static native void reopenFilesAfterForkNative();
|
||||
|
||||
public static native void deoptMethodNative(Object object);
|
||||
|
||||
public static native long suspendAllThreads();
|
||||
|
||||
public static native void resumeAllThreads(long obj);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.elderdrivers.riru.xposed.core;
|
||||
|
||||
import com.elderdrivers.riru.xposed.Main;
|
||||
import com.elderdrivers.riru.xposed.entry.hooker.OnePlusWorkAroundHooker;
|
||||
import com.elderdrivers.riru.xposed.util.Utils;
|
||||
|
||||
|
|
@ -111,8 +112,13 @@ public class HookMain {
|
|||
if (backup != null) {
|
||||
HookMethodResolver.resolveMethod(hook, backup);
|
||||
}
|
||||
if (!backupAndHookNative(target, hook, backup)) {
|
||||
throw new RuntimeException("Failed to hook " + target + " with " + hook);
|
||||
long obj = Main.suspendAllThreads();
|
||||
try {
|
||||
if (!backupAndHookNative(target, hook, backup)) {
|
||||
throw new RuntimeException("Failed to hook " + target + " with " + hook);
|
||||
}
|
||||
} finally {
|
||||
Main.resumeAllThreads(obj);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,15 +2,19 @@ package com.elderdrivers.riru.xposed.entry;
|
|||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.elderdrivers.riru.xposed.config.InstallerChooser;
|
||||
import com.elderdrivers.riru.xposed.Main;
|
||||
import com.elderdrivers.riru.xposed.core.HookMain;
|
||||
import com.elderdrivers.riru.xposed.entry.bootstrap.AppBootstrapHookInfo;
|
||||
import com.elderdrivers.riru.xposed.entry.bootstrap.SysBootstrapHookInfo;
|
||||
import com.elderdrivers.riru.xposed.entry.bootstrap.SysInnerHookInfo;
|
||||
import com.elderdrivers.riru.xposed.entry.hooker.SystemMainHooker;
|
||||
import com.elderdrivers.riru.xposed.util.InlinedMethodCallers;
|
||||
import com.elderdrivers.riru.xposed.util.Utils;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import de.robv.android.xposed.XposedBridge;
|
||||
import de.robv.android.xposed.XposedHelpers;
|
||||
import de.robv.android.xposed.XposedInit;
|
||||
|
||||
public class Router {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import android.app.ActivityThread;
|
|||
|
||||
import com.elderdrivers.riru.common.KeepMembers;
|
||||
import com.elderdrivers.riru.xposed.entry.Router;
|
||||
import com.elderdrivers.riru.xposed.util.PrebuiltMethodsDeopter;
|
||||
|
||||
import de.robv.android.xposed.XposedBridge;
|
||||
|
||||
|
|
@ -30,6 +31,8 @@ public class SystemMainHooker implements KeepMembers {
|
|||
try {
|
||||
// get system_server classLoader
|
||||
systemServerCL = Thread.currentThread().getContextClassLoader();
|
||||
// deopt methods in SYSTEMSERVERCLASSPATH
|
||||
PrebuiltMethodsDeopter.deoptSystemServerMethods(systemServerCL);
|
||||
Router.startSystemServerHook();
|
||||
} catch (Throwable t) {
|
||||
logE("error when hooking systemMain", t);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.elderdrivers.riru.xposed.proxy.yahfa;
|
|||
import com.elderdrivers.riru.xposed.Main;
|
||||
import com.elderdrivers.riru.xposed.config.ConfigManager;
|
||||
import com.elderdrivers.riru.xposed.entry.Router;
|
||||
import com.elderdrivers.riru.xposed.util.PrebuiltMethodsDeopter;
|
||||
|
||||
import static com.elderdrivers.riru.xposed.util.FileUtils.getDataPathPrefix;
|
||||
|
||||
|
|
@ -12,16 +13,22 @@ public class BlackWhiteListProxy {
|
|||
int[][] rlimits, int mountExternal, String seInfo,
|
||||
String niceName, int[] fdsToClose, int[] fdsToIgnore,
|
||||
boolean startChildZygote, String instructionSet,
|
||||
String appDataDir, boolean isDynamicModulesMode) {
|
||||
String appDataDir) {
|
||||
// always enter here, make sure secondary zygote's modules is loaded only once
|
||||
// when isDynamicModulesMode is not on
|
||||
final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled();
|
||||
ConfigManager.setDynamicModulesMode(isDynamicModulesMode);
|
||||
PrebuiltMethodsDeopter.deoptBootMethods(); // do it once for secondary zygote
|
||||
if (!isDynamicModulesMode) {
|
||||
Router.loadModulesSafely();
|
||||
Main.closeFilesBeforeForkNative();
|
||||
}
|
||||
}
|
||||
|
||||
public static void forkAndSpecializePost(int pid, String appDataDir,
|
||||
boolean isDynamicModulesMode) {
|
||||
public static void forkAndSpecializePost(int pid, String appDataDir) {
|
||||
// when this process is in white list or not in black list
|
||||
// installBootstrapHooks -> loadModules if needed
|
||||
final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled();
|
||||
if (!isDynamicModulesMode) {
|
||||
Main.reopenFilesAfterForkNative();
|
||||
}
|
||||
|
|
@ -34,16 +41,25 @@ public class BlackWhiteListProxy {
|
|||
|
||||
public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags,
|
||||
int[][] rlimits, long permittedCapabilities,
|
||||
long effectiveCapabilities,
|
||||
boolean isDynamicModulesMode) {
|
||||
long effectiveCapabilities) {
|
||||
// we always enter here whether black/white list is on or not
|
||||
final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled();
|
||||
ConfigManager.setDynamicModulesMode(isDynamicModulesMode);
|
||||
PrebuiltMethodsDeopter.deoptBootMethods(); // do it once for main zygote
|
||||
// we never install bootstrap hooks here in black/white list mode
|
||||
// because installed hooks would be propagated to all child processes of main zygote
|
||||
// hence we cannot install hooks for processes like com.android.phone process who are
|
||||
// not from forkAndSpecialize as a side effect
|
||||
if (!isDynamicModulesMode) {
|
||||
Router.loadModulesSafely();
|
||||
Main.closeFilesBeforeForkNative();
|
||||
}
|
||||
}
|
||||
|
||||
public static void forkSystemServerPost(int pid, boolean isDynamicModulesMode) {
|
||||
public static void forkSystemServerPost(int pid) {
|
||||
// should only here when system_server is in white list or not in black list
|
||||
// installBootstrapHooks -> loadModules if needed
|
||||
final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled();
|
||||
if (!isDynamicModulesMode) {
|
||||
Main.reopenFilesAfterForkNative();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.elderdrivers.riru.xposed.Main;
|
|||
import com.elderdrivers.riru.xposed.config.ConfigManager;
|
||||
import com.elderdrivers.riru.xposed.dexmaker.DynamicBridge;
|
||||
import com.elderdrivers.riru.xposed.entry.Router;
|
||||
import com.elderdrivers.riru.xposed.util.PrebuiltMethodsDeopter;
|
||||
|
||||
import static com.elderdrivers.riru.xposed.util.FileUtils.getDataPathPrefix;
|
||||
|
||||
|
|
@ -13,9 +14,11 @@ public class NormalProxy {
|
|||
int[][] rlimits, int mountExternal, String seInfo,
|
||||
String niceName, int[] fdsToClose, int[] fdsToIgnore,
|
||||
boolean startChildZygote, String instructionSet,
|
||||
String appDataDir, boolean isDynamicModulesMode) {
|
||||
String appDataDir) {
|
||||
final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled();
|
||||
Main.appDataDir = appDataDir;
|
||||
ConfigManager.setDynamicModulesMode(isDynamicModulesMode);
|
||||
PrebuiltMethodsDeopter.deoptBootMethods(); // do it once for secondary zygote
|
||||
Router.prepare(false);
|
||||
// install bootstrap hooks for secondary zygote
|
||||
Router.installBootstrapHooks(false);
|
||||
|
|
@ -24,7 +27,7 @@ public class NormalProxy {
|
|||
Main.closeFilesBeforeForkNative();
|
||||
}
|
||||
|
||||
public static void forkAndSpecializePost(int pid, String appDataDir, boolean isDynamicModulesMode) {
|
||||
public static void forkAndSpecializePost(int pid, String appDataDir) {
|
||||
// TODO consider processes without forkAndSpecializePost called
|
||||
Main.reopenFilesAfterForkNative();
|
||||
Router.onEnterChildProcess();
|
||||
|
|
@ -34,11 +37,12 @@ public class NormalProxy {
|
|||
}
|
||||
|
||||
public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits,
|
||||
long permittedCapabilities, long effectiveCapabilities,
|
||||
boolean isDynamicModulesMode) {
|
||||
long permittedCapabilities, long effectiveCapabilities) {
|
||||
final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled();
|
||||
Main.appDataDir = getDataPathPrefix() + "android";
|
||||
ConfigManager.setDynamicModulesMode(isDynamicModulesMode);
|
||||
Router.prepare(true);
|
||||
PrebuiltMethodsDeopter.deoptBootMethods(); // do it once for main zygote
|
||||
// install bootstrap hooks for main zygote as early as possible
|
||||
// in case we miss some processes not forked via forkAndSpecialize
|
||||
// for instance com.android.phone
|
||||
|
|
@ -50,7 +54,7 @@ public class NormalProxy {
|
|||
Main.closeFilesBeforeForkNative();
|
||||
}
|
||||
|
||||
public static void forkSystemServerPost(int pid, boolean isDynamicModulesMode) {
|
||||
public static void forkSystemServerPost(int pid) {
|
||||
// in system_server process
|
||||
Main.reopenFilesAfterForkNative();
|
||||
Router.onEnterChildProcess();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
package com.elderdrivers.riru.xposed.util;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Providing a whitelist of methods which are the callers of the target methods we want to hook.
|
||||
* Because the target methods are inlined into the callers, we deoptimize the callers to
|
||||
* run in intercept mode to make target methods hookable.
|
||||
* <p>
|
||||
* Only for methods which are included in pre-compiled framework codes.
|
||||
* TODO recompile system apps and priv-apps since their original dex files are available
|
||||
*/
|
||||
public class InlinedMethodCallers {
|
||||
|
||||
public static final String KEY_BOOT_IMAGE = "boot_image";
|
||||
public static final String KEY_SYSTEM_SERVER = "system_server";
|
||||
|
||||
/**
|
||||
* Key should be {@link #KEY_BOOT_IMAGE}, {@link #KEY_SYSTEM_SERVER}, or a package name
|
||||
* of system apps or priv-apps i.e. com.android.systemui
|
||||
*/
|
||||
private static final HashMap<String, String[][]> CALLERS = new HashMap<>();
|
||||
|
||||
/**
|
||||
* format for each row: {className, methodName, methodSig}
|
||||
*/
|
||||
private static final String[][] BOOT_IMAGE = {
|
||||
// callers of Application#attach(Context)
|
||||
{"android.app.Instrumentation", "newApplication", "(Ljava/lang/ClassLoader;Ljava/lang/String;Landroid/content/Context;)Landroid/app/Application;"}
|
||||
};
|
||||
|
||||
private static final String[][] SYSTEM_SERVER = {};
|
||||
|
||||
private static final String[][] SYSTEM_UI = {};
|
||||
|
||||
static {
|
||||
CALLERS.put(KEY_BOOT_IMAGE, BOOT_IMAGE);
|
||||
CALLERS.put(KEY_SYSTEM_SERVER, SYSTEM_SERVER);
|
||||
CALLERS.put("com.android.systemui", SYSTEM_UI);
|
||||
}
|
||||
|
||||
public static HashMap<String, String[][]> getAll() {
|
||||
return CALLERS;
|
||||
}
|
||||
|
||||
public static String[][] get(String where) {
|
||||
return CALLERS.get(where);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
package com.elderdrivers.riru.xposed.util;
|
||||
|
||||
import com.elderdrivers.riru.xposed.Main;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import de.robv.android.xposed.XposedHelpers;
|
||||
|
||||
import static com.elderdrivers.riru.xposed.util.InlinedMethodCallers.KEY_BOOT_IMAGE;
|
||||
import static com.elderdrivers.riru.xposed.util.InlinedMethodCallers.KEY_SYSTEM_SERVER;
|
||||
|
||||
public class PrebuiltMethodsDeopter {
|
||||
|
||||
public static void deoptMethods(String where, ClassLoader cl) {
|
||||
String[][] callers = InlinedMethodCallers.get(where);
|
||||
if (callers == null) {
|
||||
return;
|
||||
}
|
||||
for (String[] caller : callers) {
|
||||
try {
|
||||
Object method = Main.findMethodNative(
|
||||
XposedHelpers.findClass(caller[0], cl), caller[1], caller[2]);
|
||||
if (method != null) {
|
||||
Main.deoptMethodNative(method);
|
||||
}
|
||||
} catch (Throwable throwable) {
|
||||
Utils.logE("error when deopting method: " + Arrays.toString(caller), throwable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void deoptBootMethods() {
|
||||
deoptMethods(KEY_BOOT_IMAGE, null);
|
||||
}
|
||||
|
||||
public static void deoptSystemServerMethods(ClassLoader sysCL) {
|
||||
deoptMethods(KEY_SYSTEM_SERVER, sysCL);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,9 @@ package de.robv.android.xposed.callbacks;
|
|||
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.elderdrivers.riru.xposed.entry.Router;
|
||||
import com.elderdrivers.riru.xposed.util.PrebuiltMethodsDeopter;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import de.robv.android.xposed.XposedBridge;
|
||||
|
|
@ -98,6 +101,14 @@ public abstract class XCallback implements Comparable<XCallback> {
|
|||
|
||||
/** @hide */
|
||||
public static void callAll(Param param) {
|
||||
|
||||
if (param instanceof XC_LoadPackage.LoadPackageParam) {
|
||||
// deopt methods in system apps or priv-apps, this would be not necessary
|
||||
// only if we found out how to recompile their apks
|
||||
XC_LoadPackage.LoadPackageParam lpp = (XC_LoadPackage.LoadPackageParam) param;
|
||||
PrebuiltMethodsDeopter.deoptMethods(lpp.packageName, lpp.classLoader);
|
||||
}
|
||||
|
||||
if (param.callbacks == null)
|
||||
throw new IllegalStateException("This object was not created for use with callAll");
|
||||
|
||||
|
|
|
|||
|
|
@ -50,9 +50,8 @@ void onNativeForkSystemServerPre(JNIEnv *env, jclass clazz, uid_t uid, gid_t gid
|
|||
}
|
||||
prepareJavaEnv(env);
|
||||
// jump to java code
|
||||
findAndCall(env, "forkSystemServerPre", "(II[II[[IJJZZ)V", uid, gid, gids, runtime_flags,
|
||||
rlimits, permittedCapabilities, effectiveCapabilities,
|
||||
is_black_white_list_mode, is_dynamic_modules_mode);
|
||||
findAndCall(env, "forkSystemServerPre", "(II[II[[IJJ)V", uid, gid, gids, runtime_flags,
|
||||
rlimits, permittedCapabilities, effectiveCapabilities);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -63,8 +62,7 @@ int onNativeForkSystemServerPost(JNIEnv *env, jclass clazz, jint res) {
|
|||
}
|
||||
prepareJavaEnv(env);
|
||||
// only do work in child since findAndCall would print log
|
||||
findAndCall(env, "forkSystemServerPost", "(IZZ)V", res,
|
||||
is_black_white_list_enabled(), is_dynamic_modules_enabled());
|
||||
findAndCall(env, "forkSystemServerPost", "(I)V", res);
|
||||
} else {
|
||||
// in zygote process, res is child zygote pid
|
||||
// don't print log here, see https://github.com/RikkaApps/Riru/blob/77adfd6a4a6a81bfd20569c910bc4854f2f84f5e/riru-core/jni/main/jni_native_method.cpp#L55-L66
|
||||
|
|
@ -94,11 +92,10 @@ void onNativeForkAndSpecializePre(JNIEnv *env, jclass clazz,
|
|||
}
|
||||
prepareJavaEnv(env);
|
||||
findAndCall(env, "forkAndSpecializePre",
|
||||
"(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;ZZ)V",
|
||||
"(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;)V",
|
||||
uid, gid, gids, runtime_flags, rlimits,
|
||||
_mount_external, se_info, se_name, fdsToClose, fdsToIgnore,
|
||||
is_child_zygote, instructionSet, appDataDir,
|
||||
is_black_white_list_mode, is_dynamic_modules_mode);
|
||||
is_child_zygote, instructionSet, appDataDir);
|
||||
}
|
||||
|
||||
int onNativeForkAndSpecializePost(JNIEnv *env, jclass clazz, jint res) {
|
||||
|
|
@ -107,8 +104,7 @@ int onNativeForkAndSpecializePost(JNIEnv *env, jclass clazz, jint res) {
|
|||
return 0;
|
||||
}
|
||||
prepareJavaEnv(env);
|
||||
findAndCall(env, "forkAndSpecializePost", "(ILjava/lang/String;ZZ)V", res, sAppDataDir,
|
||||
is_black_white_list_enabled(), is_dynamic_modules_enabled());
|
||||
findAndCall(env, "forkAndSpecializePost", "(ILjava/lang/String;)V", res, sAppDataDir);
|
||||
} else {
|
||||
// in zygote process, res is child zygote pid
|
||||
// don't print log here, see https://github.com/RikkaApps/Riru/blob/77adfd6a4a6a81bfd20569c910bc4854f2f84f5e/riru-core/jni/main/jni_native_method.cpp#L55-L66
|
||||
|
|
|
|||
|
|
@ -20,13 +20,13 @@ jobject gInjectDexClassLoader;
|
|||
|
||||
static bool isInited = false;
|
||||
|
||||
static FileDescriptorTable* gClosedFdTable = nullptr;
|
||||
static FileDescriptorTable *gClosedFdTable = nullptr;
|
||||
|
||||
void closeFilesBeforeForkNative(JNIEnv*, jclass) {
|
||||
void closeFilesBeforeForkNative(JNIEnv *, jclass) {
|
||||
gClosedFdTable = FileDescriptorTable::Create();
|
||||
}
|
||||
|
||||
void reopenFilesAfterForkNative(JNIEnv*, jclass) {
|
||||
void reopenFilesAfterForkNative(JNIEnv *, jclass) {
|
||||
if (!gClosedFdTable) {
|
||||
LOGE("gClosedFdTable is null when reopening files");
|
||||
return;
|
||||
|
|
@ -36,6 +36,22 @@ void reopenFilesAfterForkNative(JNIEnv*, jclass) {
|
|||
gClosedFdTable = nullptr;
|
||||
}
|
||||
|
||||
jlong suspendAllThreads(JNIEnv *, jclass) {
|
||||
if (!suspendAll) {
|
||||
return 0;
|
||||
}
|
||||
ScopedSuspendAll *suspendAllObj = (ScopedSuspendAll *) malloc(sizeof(ScopedSuspendAll));
|
||||
suspendAll(suspendAllObj, "edxp_stop_gc", false);
|
||||
return reinterpret_cast<jlong>(suspendAllObj);
|
||||
}
|
||||
|
||||
void resumeAllThreads(JNIEnv *, jclass, jlong obj) {
|
||||
if (!resumeAll) {
|
||||
return;
|
||||
}
|
||||
resumeAll(reinterpret_cast<ScopedSuspendAll *>(obj));
|
||||
}
|
||||
|
||||
static JNINativeMethod hookMethods[] = {
|
||||
{
|
||||
"init",
|
||||
|
|
@ -58,16 +74,28 @@ static JNINativeMethod hookMethods[] = {
|
|||
(void *) Java_lab_galaxy_yahfa_HookMain_ensureMethodCached
|
||||
},
|
||||
{
|
||||
"getInstallerPkgName", "()Ljava/lang/String;", (void *)get_installer_pkg_name
|
||||
"isBlackWhiteListEnabled", "()Z", (void *) is_black_white_list_enabled
|
||||
},
|
||||
{
|
||||
"closeFilesBeforeForkNative", "()V", (void *)closeFilesBeforeForkNative
|
||||
"isDynamicModulesEnabled", "()Z", (void *) is_dynamic_modules_enabled
|
||||
},
|
||||
{
|
||||
"reopenFilesAfterForkNative", "()V", (void *)reopenFilesAfterForkNative
|
||||
"getInstallerPkgName", "()Ljava/lang/String;", (void *) get_installer_pkg_name
|
||||
},
|
||||
{
|
||||
"deoptMethodNative", "(Ljava/lang/Object;)V", (void *)deoptimize_method
|
||||
"closeFilesBeforeForkNative", "()V", (void *) closeFilesBeforeForkNative
|
||||
},
|
||||
{
|
||||
"reopenFilesAfterForkNative", "()V", (void *) reopenFilesAfterForkNative
|
||||
},
|
||||
{
|
||||
"deoptMethodNative", "(Ljava/lang/Object;)V", (void *) deoptimize_method
|
||||
},
|
||||
{
|
||||
"suspendAllThreads", "()J", (void *) suspendAllThreads
|
||||
},
|
||||
{
|
||||
"resumeAllThreads", "(J)V", (void *) resumeAllThreads
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -106,7 +134,7 @@ void loadDexAndInit(JNIEnv *env, const char *dexPath) {
|
|||
jclass entry_class = findClassFromLoader(env, myClassLoader, ENTRY_CLASS_NAME);
|
||||
if (NULL != entry_class) {
|
||||
LOGD("HookEntry Class %p", entry_class);
|
||||
env->RegisterNatives(entry_class, hookMethods, 8);
|
||||
env->RegisterNatives(entry_class, hookMethods, 12);
|
||||
isInited = true;
|
||||
LOGD("RegisterNatives succeed for HookEntry.");
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -212,6 +212,19 @@ void hookRuntime(int api_level, void *artHandle, void (*hookFun)(void *, void *,
|
|||
}
|
||||
}
|
||||
|
||||
void (*suspendAll)(ScopedSuspendAll*, const char*, bool) = nullptr;
|
||||
void (*resumeAll)(ScopedSuspendAll*) = nullptr;
|
||||
|
||||
void getSuspendSyms(int api_level, void *artHandle, void (*hookFun)(void *, void *, void **)) {
|
||||
if (api_level < ANDROID_N) {
|
||||
return;
|
||||
}
|
||||
suspendAll = reinterpret_cast<void (*)(ScopedSuspendAll*,const char*, bool)>(dlsym(artHandle,
|
||||
"_ZN3art16ScopedSuspendAllC2EPKcb"));
|
||||
resumeAll = reinterpret_cast<void (*)(ScopedSuspendAll*)>(dlsym(artHandle,
|
||||
"_ZN3art16ScopedSuspendAllD2Ev"));
|
||||
}
|
||||
|
||||
void install_inline_hooks() {
|
||||
if (inlineHooksInstalled) {
|
||||
LOGI("inline hooks installed, skip");
|
||||
|
|
@ -243,6 +256,7 @@ void install_inline_hooks() {
|
|||
}
|
||||
hookRuntime(api_level, artHandle, hookFun);
|
||||
hookInstrumentation(api_level, artHandle, hookFun);
|
||||
getSuspendSyms(api_level, artHandle, hookFun);
|
||||
hookIsInSamePackage(api_level, artHandle, hookFun);
|
||||
if (disableHiddenAPIPolicyImpl(api_level, artHandle, hookFun)) {
|
||||
LOGI("disableHiddenAPIPolicyImpl done.");
|
||||
|
|
|
|||
|
|
@ -19,6 +19,13 @@ static constexpr const char *kLibWhalePath = "/system/lib/libwhale.so";
|
|||
static ret (*old_##func)(__VA_ARGS__); \
|
||||
static ret new_##func(__VA_ARGS__)
|
||||
|
||||
class ScopedSuspendAll {
|
||||
};
|
||||
|
||||
extern void (*suspendAll)(ScopedSuspendAll *, const char *, bool);
|
||||
|
||||
extern void (*resumeAll)(ScopedSuspendAll *);
|
||||
|
||||
void install_inline_hooks();
|
||||
|
||||
void deoptimize_method(JNIEnv *env, jclass clazz, jobject method);
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ supolicy --live "allow system_server system_server process {execmem}"
|
|||
supolicy --live "allow coredomain coredomain process {execmem}"
|
||||
|
||||
# read configs set in our app
|
||||
supolicy --live "allow {zygote system_server} app_data_file * *"
|
||||
supolicy --live "allow coredomain app_data_file * *"
|
||||
supolicy --live "attradd {system_app platform_app} mlstrustedsubject"
|
||||
|
||||
# read module apk file in zygote
|
||||
|
|
|
|||
Loading…
Reference in New Issue