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,
|
int[][] rlimits, int mountExternal, String seInfo,
|
||||||
String niceName, int[] fdsToClose, int[] fdsToIgnore,
|
String niceName, int[] fdsToClose, int[] fdsToIgnore,
|
||||||
boolean startChildZygote, String instructionSet,
|
boolean startChildZygote, String instructionSet,
|
||||||
String appDataDir, boolean isBlackWhiteListMode,
|
String appDataDir) {
|
||||||
boolean isDynamicModulesMode) {
|
|
||||||
if (BuildConfig.DEBUG) {
|
if (BuildConfig.DEBUG) {
|
||||||
forkAndSpecializePramsStr = String.format(
|
forkAndSpecializePramsStr = String.format(
|
||||||
"Zygote#forkAndSpecialize(%d, %d, %s, %d, %s, %d, %s, %s, %s, %s, %s, %s, %s)",
|
"Zygote#forkAndSpecialize(%d, %d, %s, %d, %s, %d, %s, %s, %s, %s, %s, %s, %s)",
|
||||||
uid, gid, Arrays.toString(gids), debugFlags, Arrays.toString(rlimits),
|
uid, gid, Arrays.toString(gids), debugFlags, Arrays.toString(rlimits),
|
||||||
mountExternal, seInfo, niceName, Arrays.toString(fdsToClose),
|
mountExternal, seInfo, niceName, Arrays.toString(fdsToClose),
|
||||||
Arrays.toString(fdsToIgnore), startChildZygote, instructionSet, appDataDir,
|
Arrays.toString(fdsToIgnore), startChildZygote, instructionSet, appDataDir);
|
||||||
isDynamicModulesMode);
|
|
||||||
}
|
}
|
||||||
if (isBlackWhiteListMode) {
|
if (isBlackWhiteListEnabled()) {
|
||||||
BlackWhiteListProxy.forkAndSpecializePre(uid, gid, gids, debugFlags, rlimits,
|
BlackWhiteListProxy.forkAndSpecializePre(uid, gid, gids, debugFlags, rlimits,
|
||||||
mountExternal, seInfo, niceName, fdsToClose, fdsToIgnore, startChildZygote,
|
mountExternal, seInfo, niceName, fdsToClose, fdsToIgnore, startChildZygote,
|
||||||
instructionSet, appDataDir, isDynamicModulesMode);
|
instructionSet, appDataDir);
|
||||||
} else {
|
} else {
|
||||||
NormalProxy.forkAndSpecializePre(uid, gid, gids, debugFlags, rlimits, mountExternal,
|
NormalProxy.forkAndSpecializePre(uid, gid, gids, debugFlags, rlimits, mountExternal,
|
||||||
seInfo, niceName, fdsToClose, fdsToIgnore, startChildZygote, instructionSet,
|
seInfo, niceName, fdsToClose, fdsToIgnore, startChildZygote, instructionSet,
|
||||||
appDataDir, isDynamicModulesMode);
|
appDataDir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void forkAndSpecializePost(int pid, String appDataDir,
|
public static void forkAndSpecializePost(int pid, String appDataDir) {
|
||||||
boolean isBlackWhiteListMode,
|
|
||||||
boolean isDynamicModulesMode) {
|
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
Utils.logD(forkAndSpecializePramsStr + " = " + Process.myPid());
|
Utils.logD(forkAndSpecializePramsStr + " = " + Process.myPid());
|
||||||
if (isBlackWhiteListMode) {
|
if (isBlackWhiteListEnabled()) {
|
||||||
BlackWhiteListProxy.forkAndSpecializePost(pid, appDataDir, isDynamicModulesMode);
|
BlackWhiteListProxy.forkAndSpecializePost(pid, appDataDir);
|
||||||
} else {
|
} else {
|
||||||
NormalProxy.forkAndSpecializePost(pid, appDataDir, isDynamicModulesMode);
|
NormalProxy.forkAndSpecializePost(pid, appDataDir);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// in zygote process, res is child zygote pid
|
// 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,
|
public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits,
|
||||||
long permittedCapabilities, long effectiveCapabilities,
|
long permittedCapabilities, long effectiveCapabilities) {
|
||||||
boolean isBlackWhiteListMode, boolean isDynamicModulesMode) {
|
|
||||||
if (BuildConfig.DEBUG) {
|
if (BuildConfig.DEBUG) {
|
||||||
forkSystemServerPramsStr = String.format("Zygote#forkSystemServer(%d, %d, %s, %d, %s, %d, %d)",
|
forkSystemServerPramsStr = String.format("Zygote#forkSystemServer(%d, %d, %s, %d, %s, %d, %d)",
|
||||||
uid, gid, Arrays.toString(gids), debugFlags, Arrays.toString(rlimits),
|
uid, gid, Arrays.toString(gids), debugFlags, Arrays.toString(rlimits),
|
||||||
permittedCapabilities, effectiveCapabilities);
|
permittedCapabilities, effectiveCapabilities);
|
||||||
}
|
}
|
||||||
if (isBlackWhiteListMode) {
|
if (isBlackWhiteListEnabled()) {
|
||||||
BlackWhiteListProxy.forkSystemServerPre(uid, gid, gids, debugFlags, rlimits,
|
BlackWhiteListProxy.forkSystemServerPre(uid, gid, gids, debugFlags, rlimits,
|
||||||
permittedCapabilities, effectiveCapabilities, isDynamicModulesMode);
|
permittedCapabilities, effectiveCapabilities);
|
||||||
} else {
|
} else {
|
||||||
NormalProxy.forkSystemServerPre(uid, gid, gids, debugFlags, rlimits,
|
NormalProxy.forkSystemServerPre(uid, gid, gids, debugFlags, rlimits,
|
||||||
permittedCapabilities, effectiveCapabilities, isDynamicModulesMode);
|
permittedCapabilities, effectiveCapabilities);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void forkSystemServerPost(int pid, boolean isBlackWhiteListMode,
|
public static void forkSystemServerPost(int pid) {
|
||||||
boolean isDynamicModulesMode) {
|
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
Utils.logD(forkSystemServerPramsStr + " = " + Process.myPid());
|
Utils.logD(forkSystemServerPramsStr + " = " + Process.myPid());
|
||||||
if (isBlackWhiteListMode) {
|
if (isBlackWhiteListEnabled()) {
|
||||||
BlackWhiteListProxy.forkSystemServerPost(pid, isDynamicModulesMode);
|
BlackWhiteListProxy.forkSystemServerPost(pid);
|
||||||
} else {
|
} else {
|
||||||
NormalProxy.forkSystemServerPost(pid, isDynamicModulesMode);
|
NormalProxy.forkSystemServerPost(pid);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// in zygote process, res is child zygote pid
|
// 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 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
|
// prevent from fatal error caused by holding not whitelisted file descriptors when forking zygote
|
||||||
// https://github.com/rovo89/Xposed/commit/b3ba245ad04cd485699fb1d2ebde7117e58214ff
|
// https://github.com/rovo89/Xposed/commit/b3ba245ad04cd485699fb1d2ebde7117e58214ff
|
||||||
public static native void closeFilesBeforeForkNative();
|
public static native void closeFilesBeforeForkNative();
|
||||||
|
|
@ -125,4 +123,8 @@ public class Main implements KeepAll {
|
||||||
public static native void reopenFilesAfterForkNative();
|
public static native void reopenFilesAfterForkNative();
|
||||||
|
|
||||||
public static native void deoptMethodNative(Object object);
|
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;
|
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.entry.hooker.OnePlusWorkAroundHooker;
|
||||||
import com.elderdrivers.riru.xposed.util.Utils;
|
import com.elderdrivers.riru.xposed.util.Utils;
|
||||||
|
|
||||||
|
|
@ -111,9 +112,14 @@ public class HookMain {
|
||||||
if (backup != null) {
|
if (backup != null) {
|
||||||
HookMethodResolver.resolveMethod(hook, backup);
|
HookMethodResolver.resolveMethod(hook, backup);
|
||||||
}
|
}
|
||||||
|
long obj = Main.suspendAllThreads();
|
||||||
|
try {
|
||||||
if (!backupAndHookNative(target, hook, backup)) {
|
if (!backupAndHookNative(target, hook, backup)) {
|
||||||
throw new RuntimeException("Failed to hook " + target + " with " + hook);
|
throw new RuntimeException("Failed to hook " + target + " with " + hook);
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
Main.resumeAllThreads(obj);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object findMethod(Class cls, String methodName, String methodSig) {
|
public static Object findMethod(Class cls, String methodName, String methodSig) {
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,19 @@ package com.elderdrivers.riru.xposed.entry;
|
||||||
|
|
||||||
import android.text.TextUtils;
|
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.core.HookMain;
|
||||||
import com.elderdrivers.riru.xposed.entry.bootstrap.AppBootstrapHookInfo;
|
import com.elderdrivers.riru.xposed.entry.bootstrap.AppBootstrapHookInfo;
|
||||||
import com.elderdrivers.riru.xposed.entry.bootstrap.SysBootstrapHookInfo;
|
import com.elderdrivers.riru.xposed.entry.bootstrap.SysBootstrapHookInfo;
|
||||||
import com.elderdrivers.riru.xposed.entry.bootstrap.SysInnerHookInfo;
|
import com.elderdrivers.riru.xposed.entry.bootstrap.SysInnerHookInfo;
|
||||||
import com.elderdrivers.riru.xposed.entry.hooker.SystemMainHooker;
|
import com.elderdrivers.riru.xposed.entry.hooker.SystemMainHooker;
|
||||||
|
import com.elderdrivers.riru.xposed.util.InlinedMethodCallers;
|
||||||
import com.elderdrivers.riru.xposed.util.Utils;
|
import com.elderdrivers.riru.xposed.util.Utils;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import de.robv.android.xposed.XposedBridge;
|
import de.robv.android.xposed.XposedBridge;
|
||||||
|
import de.robv.android.xposed.XposedHelpers;
|
||||||
import de.robv.android.xposed.XposedInit;
|
import de.robv.android.xposed.XposedInit;
|
||||||
|
|
||||||
public class Router {
|
public class Router {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import android.app.ActivityThread;
|
||||||
|
|
||||||
import com.elderdrivers.riru.common.KeepMembers;
|
import com.elderdrivers.riru.common.KeepMembers;
|
||||||
import com.elderdrivers.riru.xposed.entry.Router;
|
import com.elderdrivers.riru.xposed.entry.Router;
|
||||||
|
import com.elderdrivers.riru.xposed.util.PrebuiltMethodsDeopter;
|
||||||
|
|
||||||
import de.robv.android.xposed.XposedBridge;
|
import de.robv.android.xposed.XposedBridge;
|
||||||
|
|
||||||
|
|
@ -30,6 +31,8 @@ public class SystemMainHooker implements KeepMembers {
|
||||||
try {
|
try {
|
||||||
// get system_server classLoader
|
// get system_server classLoader
|
||||||
systemServerCL = Thread.currentThread().getContextClassLoader();
|
systemServerCL = Thread.currentThread().getContextClassLoader();
|
||||||
|
// deopt methods in SYSTEMSERVERCLASSPATH
|
||||||
|
PrebuiltMethodsDeopter.deoptSystemServerMethods(systemServerCL);
|
||||||
Router.startSystemServerHook();
|
Router.startSystemServerHook();
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
logE("error when hooking systemMain", 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.Main;
|
||||||
import com.elderdrivers.riru.xposed.config.ConfigManager;
|
import com.elderdrivers.riru.xposed.config.ConfigManager;
|
||||||
import com.elderdrivers.riru.xposed.entry.Router;
|
import com.elderdrivers.riru.xposed.entry.Router;
|
||||||
|
import com.elderdrivers.riru.xposed.util.PrebuiltMethodsDeopter;
|
||||||
|
|
||||||
import static com.elderdrivers.riru.xposed.util.FileUtils.getDataPathPrefix;
|
import static com.elderdrivers.riru.xposed.util.FileUtils.getDataPathPrefix;
|
||||||
|
|
||||||
|
|
@ -12,16 +13,22 @@ public class BlackWhiteListProxy {
|
||||||
int[][] rlimits, int mountExternal, String seInfo,
|
int[][] rlimits, int mountExternal, String seInfo,
|
||||||
String niceName, int[] fdsToClose, int[] fdsToIgnore,
|
String niceName, int[] fdsToClose, int[] fdsToIgnore,
|
||||||
boolean startChildZygote, String instructionSet,
|
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);
|
ConfigManager.setDynamicModulesMode(isDynamicModulesMode);
|
||||||
|
PrebuiltMethodsDeopter.deoptBootMethods(); // do it once for secondary zygote
|
||||||
if (!isDynamicModulesMode) {
|
if (!isDynamicModulesMode) {
|
||||||
Router.loadModulesSafely();
|
Router.loadModulesSafely();
|
||||||
Main.closeFilesBeforeForkNative();
|
Main.closeFilesBeforeForkNative();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void forkAndSpecializePost(int pid, String appDataDir,
|
public static void forkAndSpecializePost(int pid, String appDataDir) {
|
||||||
boolean isDynamicModulesMode) {
|
// when this process is in white list or not in black list
|
||||||
|
// installBootstrapHooks -> loadModules if needed
|
||||||
|
final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled();
|
||||||
if (!isDynamicModulesMode) {
|
if (!isDynamicModulesMode) {
|
||||||
Main.reopenFilesAfterForkNative();
|
Main.reopenFilesAfterForkNative();
|
||||||
}
|
}
|
||||||
|
|
@ -34,16 +41,25 @@ public class BlackWhiteListProxy {
|
||||||
|
|
||||||
public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags,
|
public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags,
|
||||||
int[][] rlimits, long permittedCapabilities,
|
int[][] rlimits, long permittedCapabilities,
|
||||||
long effectiveCapabilities,
|
long effectiveCapabilities) {
|
||||||
boolean isDynamicModulesMode) {
|
// we always enter here whether black/white list is on or not
|
||||||
|
final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled();
|
||||||
ConfigManager.setDynamicModulesMode(isDynamicModulesMode);
|
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) {
|
if (!isDynamicModulesMode) {
|
||||||
Router.loadModulesSafely();
|
Router.loadModulesSafely();
|
||||||
Main.closeFilesBeforeForkNative();
|
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) {
|
if (!isDynamicModulesMode) {
|
||||||
Main.reopenFilesAfterForkNative();
|
Main.reopenFilesAfterForkNative();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import com.elderdrivers.riru.xposed.Main;
|
||||||
import com.elderdrivers.riru.xposed.config.ConfigManager;
|
import com.elderdrivers.riru.xposed.config.ConfigManager;
|
||||||
import com.elderdrivers.riru.xposed.dexmaker.DynamicBridge;
|
import com.elderdrivers.riru.xposed.dexmaker.DynamicBridge;
|
||||||
import com.elderdrivers.riru.xposed.entry.Router;
|
import com.elderdrivers.riru.xposed.entry.Router;
|
||||||
|
import com.elderdrivers.riru.xposed.util.PrebuiltMethodsDeopter;
|
||||||
|
|
||||||
import static com.elderdrivers.riru.xposed.util.FileUtils.getDataPathPrefix;
|
import static com.elderdrivers.riru.xposed.util.FileUtils.getDataPathPrefix;
|
||||||
|
|
||||||
|
|
@ -13,9 +14,11 @@ public class NormalProxy {
|
||||||
int[][] rlimits, int mountExternal, String seInfo,
|
int[][] rlimits, int mountExternal, String seInfo,
|
||||||
String niceName, int[] fdsToClose, int[] fdsToIgnore,
|
String niceName, int[] fdsToClose, int[] fdsToIgnore,
|
||||||
boolean startChildZygote, String instructionSet,
|
boolean startChildZygote, String instructionSet,
|
||||||
String appDataDir, boolean isDynamicModulesMode) {
|
String appDataDir) {
|
||||||
|
final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled();
|
||||||
Main.appDataDir = appDataDir;
|
Main.appDataDir = appDataDir;
|
||||||
ConfigManager.setDynamicModulesMode(isDynamicModulesMode);
|
ConfigManager.setDynamicModulesMode(isDynamicModulesMode);
|
||||||
|
PrebuiltMethodsDeopter.deoptBootMethods(); // do it once for secondary zygote
|
||||||
Router.prepare(false);
|
Router.prepare(false);
|
||||||
// install bootstrap hooks for secondary zygote
|
// install bootstrap hooks for secondary zygote
|
||||||
Router.installBootstrapHooks(false);
|
Router.installBootstrapHooks(false);
|
||||||
|
|
@ -24,7 +27,7 @@ public class NormalProxy {
|
||||||
Main.closeFilesBeforeForkNative();
|
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
|
// TODO consider processes without forkAndSpecializePost called
|
||||||
Main.reopenFilesAfterForkNative();
|
Main.reopenFilesAfterForkNative();
|
||||||
Router.onEnterChildProcess();
|
Router.onEnterChildProcess();
|
||||||
|
|
@ -34,11 +37,12 @@ public class NormalProxy {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits,
|
public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits,
|
||||||
long permittedCapabilities, long effectiveCapabilities,
|
long permittedCapabilities, long effectiveCapabilities) {
|
||||||
boolean isDynamicModulesMode) {
|
final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled();
|
||||||
Main.appDataDir = getDataPathPrefix() + "android";
|
Main.appDataDir = getDataPathPrefix() + "android";
|
||||||
ConfigManager.setDynamicModulesMode(isDynamicModulesMode);
|
ConfigManager.setDynamicModulesMode(isDynamicModulesMode);
|
||||||
Router.prepare(true);
|
Router.prepare(true);
|
||||||
|
PrebuiltMethodsDeopter.deoptBootMethods(); // do it once for main zygote
|
||||||
// install bootstrap hooks for main zygote as early as possible
|
// install bootstrap hooks for main zygote as early as possible
|
||||||
// in case we miss some processes not forked via forkAndSpecialize
|
// in case we miss some processes not forked via forkAndSpecialize
|
||||||
// for instance com.android.phone
|
// for instance com.android.phone
|
||||||
|
|
@ -50,7 +54,7 @@ public class NormalProxy {
|
||||||
Main.closeFilesBeforeForkNative();
|
Main.closeFilesBeforeForkNative();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void forkSystemServerPost(int pid, boolean isDynamicModulesMode) {
|
public static void forkSystemServerPost(int pid) {
|
||||||
// in system_server process
|
// in system_server process
|
||||||
Main.reopenFilesAfterForkNative();
|
Main.reopenFilesAfterForkNative();
|
||||||
Router.onEnterChildProcess();
|
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 android.os.Bundle;
|
||||||
|
|
||||||
|
import com.elderdrivers.riru.xposed.entry.Router;
|
||||||
|
import com.elderdrivers.riru.xposed.util.PrebuiltMethodsDeopter;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
import de.robv.android.xposed.XposedBridge;
|
import de.robv.android.xposed.XposedBridge;
|
||||||
|
|
@ -98,6 +101,14 @@ public abstract class XCallback implements Comparable<XCallback> {
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public static void callAll(Param param) {
|
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)
|
if (param.callbacks == null)
|
||||||
throw new IllegalStateException("This object was not created for use with callAll");
|
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);
|
prepareJavaEnv(env);
|
||||||
// jump to java code
|
// jump to java code
|
||||||
findAndCall(env, "forkSystemServerPre", "(II[II[[IJJZZ)V", uid, gid, gids, runtime_flags,
|
findAndCall(env, "forkSystemServerPre", "(II[II[[IJJ)V", uid, gid, gids, runtime_flags,
|
||||||
rlimits, permittedCapabilities, effectiveCapabilities,
|
rlimits, permittedCapabilities, effectiveCapabilities);
|
||||||
is_black_white_list_mode, is_dynamic_modules_mode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -63,8 +62,7 @@ int onNativeForkSystemServerPost(JNIEnv *env, jclass clazz, jint res) {
|
||||||
}
|
}
|
||||||
prepareJavaEnv(env);
|
prepareJavaEnv(env);
|
||||||
// only do work in child since findAndCall would print log
|
// only do work in child since findAndCall would print log
|
||||||
findAndCall(env, "forkSystemServerPost", "(IZZ)V", res,
|
findAndCall(env, "forkSystemServerPost", "(I)V", res);
|
||||||
is_black_white_list_enabled(), is_dynamic_modules_enabled());
|
|
||||||
} else {
|
} else {
|
||||||
// in zygote process, res is child zygote pid
|
// 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
|
// 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);
|
prepareJavaEnv(env);
|
||||||
findAndCall(env, "forkAndSpecializePre",
|
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,
|
uid, gid, gids, runtime_flags, rlimits,
|
||||||
_mount_external, se_info, se_name, fdsToClose, fdsToIgnore,
|
_mount_external, se_info, se_name, fdsToClose, fdsToIgnore,
|
||||||
is_child_zygote, instructionSet, appDataDir,
|
is_child_zygote, instructionSet, appDataDir);
|
||||||
is_black_white_list_mode, is_dynamic_modules_mode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int onNativeForkAndSpecializePost(JNIEnv *env, jclass clazz, jint res) {
|
int onNativeForkAndSpecializePost(JNIEnv *env, jclass clazz, jint res) {
|
||||||
|
|
@ -107,8 +104,7 @@ int onNativeForkAndSpecializePost(JNIEnv *env, jclass clazz, jint res) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
prepareJavaEnv(env);
|
prepareJavaEnv(env);
|
||||||
findAndCall(env, "forkAndSpecializePost", "(ILjava/lang/String;ZZ)V", res, sAppDataDir,
|
findAndCall(env, "forkAndSpecializePost", "(ILjava/lang/String;)V", res, sAppDataDir);
|
||||||
is_black_white_list_enabled(), is_dynamic_modules_enabled());
|
|
||||||
} else {
|
} else {
|
||||||
// in zygote process, res is child zygote pid
|
// 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
|
// 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 bool isInited = false;
|
||||||
|
|
||||||
static FileDescriptorTable* gClosedFdTable = nullptr;
|
static FileDescriptorTable *gClosedFdTable = nullptr;
|
||||||
|
|
||||||
void closeFilesBeforeForkNative(JNIEnv*, jclass) {
|
void closeFilesBeforeForkNative(JNIEnv *, jclass) {
|
||||||
gClosedFdTable = FileDescriptorTable::Create();
|
gClosedFdTable = FileDescriptorTable::Create();
|
||||||
}
|
}
|
||||||
|
|
||||||
void reopenFilesAfterForkNative(JNIEnv*, jclass) {
|
void reopenFilesAfterForkNative(JNIEnv *, jclass) {
|
||||||
if (!gClosedFdTable) {
|
if (!gClosedFdTable) {
|
||||||
LOGE("gClosedFdTable is null when reopening files");
|
LOGE("gClosedFdTable is null when reopening files");
|
||||||
return;
|
return;
|
||||||
|
|
@ -36,6 +36,22 @@ void reopenFilesAfterForkNative(JNIEnv*, jclass) {
|
||||||
gClosedFdTable = nullptr;
|
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[] = {
|
static JNINativeMethod hookMethods[] = {
|
||||||
{
|
{
|
||||||
"init",
|
"init",
|
||||||
|
|
@ -58,16 +74,28 @@ static JNINativeMethod hookMethods[] = {
|
||||||
(void *) Java_lab_galaxy_yahfa_HookMain_ensureMethodCached
|
(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);
|
jclass entry_class = findClassFromLoader(env, myClassLoader, ENTRY_CLASS_NAME);
|
||||||
if (NULL != entry_class) {
|
if (NULL != entry_class) {
|
||||||
LOGD("HookEntry Class %p", entry_class);
|
LOGD("HookEntry Class %p", entry_class);
|
||||||
env->RegisterNatives(entry_class, hookMethods, 8);
|
env->RegisterNatives(entry_class, hookMethods, 12);
|
||||||
isInited = true;
|
isInited = true;
|
||||||
LOGD("RegisterNatives succeed for HookEntry.");
|
LOGD("RegisterNatives succeed for HookEntry.");
|
||||||
} else {
|
} 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() {
|
void install_inline_hooks() {
|
||||||
if (inlineHooksInstalled) {
|
if (inlineHooksInstalled) {
|
||||||
LOGI("inline hooks installed, skip");
|
LOGI("inline hooks installed, skip");
|
||||||
|
|
@ -243,6 +256,7 @@ void install_inline_hooks() {
|
||||||
}
|
}
|
||||||
hookRuntime(api_level, artHandle, hookFun);
|
hookRuntime(api_level, artHandle, hookFun);
|
||||||
hookInstrumentation(api_level, artHandle, hookFun);
|
hookInstrumentation(api_level, artHandle, hookFun);
|
||||||
|
getSuspendSyms(api_level, artHandle, hookFun);
|
||||||
hookIsInSamePackage(api_level, artHandle, hookFun);
|
hookIsInSamePackage(api_level, artHandle, hookFun);
|
||||||
if (disableHiddenAPIPolicyImpl(api_level, artHandle, hookFun)) {
|
if (disableHiddenAPIPolicyImpl(api_level, artHandle, hookFun)) {
|
||||||
LOGI("disableHiddenAPIPolicyImpl done.");
|
LOGI("disableHiddenAPIPolicyImpl done.");
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,13 @@ static constexpr const char *kLibWhalePath = "/system/lib/libwhale.so";
|
||||||
static ret (*old_##func)(__VA_ARGS__); \
|
static ret (*old_##func)(__VA_ARGS__); \
|
||||||
static ret new_##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 install_inline_hooks();
|
||||||
|
|
||||||
void deoptimize_method(JNIEnv *env, jclass clazz, jobject method);
|
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}"
|
supolicy --live "allow coredomain coredomain process {execmem}"
|
||||||
|
|
||||||
# read configs set in our app
|
# 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"
|
supolicy --live "attradd {system_app platform_app} mlstrustedsubject"
|
||||||
|
|
||||||
# read module apk file in zygote
|
# read module apk file in zygote
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue