From c38affbf3a12aa8032beb537dce19e6830e30ebf Mon Sep 17 00:00:00 2001 From: solohsu Date: Mon, 3 Jun 2019 23:58:56 +0800 Subject: [PATCH] Refactor Java code --- edxp-common/build.gradle | 1 + .../riru/edxp/_hooker/impl/HandleBindApp.java | 40 ++-- .../riru/edxp/_hooker/impl/LoadedApkCstr.java | 76 +++++++ .../edxp/_hooker/impl/OneplusWorkaround.java | 33 ++-- .../_hooker/impl/StartBootstrapServices.java | 36 ++-- .../riru/edxp/_hooker/impl/SystemMain.java | 33 ++++ .../_hooker/yahfa/HandleBindAppHooker.java | 28 +++ .../yahfa/LoadedApkConstructorHooker.java | 44 +++++ .../yahfa/OnePlusWorkAroundHooker.java | 35 ++++ .../yahfa/StartBootstrapServicesHooker.java | 28 +++ .../edxp/_hooker/yahfa/SystemMainHooker.java | 34 ++++ .../riru/edxp/config/ConfigManager.java | 29 +-- .../riru/edxp/core/BaseEdxpImpl.java | 62 ++++++ .../elderdrivers/riru/edxp/core/EdxpImpl.java | 40 ++++ .../elderdrivers/riru/edxp/core}/Main.java | 92 ++++++--- .../elderdrivers/riru/edxp/core/Proxy.java | 21 ++ .../riru/edxp/core/yahfa}/HookMain.java | 11 +- .../edxp/core/yahfa}/HookMethodResolver.java | 7 +- .../elderdrivers/riru/edxp/entry/Hook.java | 4 + .../riru/edxp/entry/HookImpl.java | 5 + .../entry/yahfa}/AppBootstrapHookInfo.java | 8 +- .../entry/yahfa}/SysBootstrapHookInfo.java | 10 +- .../edxp/entry/yahfa}/SysInnerHookInfo.java | 4 +- .../edxp/entry/yahfa}/WorkAroundHookInfo.java | 4 +- .../riru/edxp/proxy/BaseProxy.java | 17 ++ .../riru/edxp/proxy/BaseRouter.java | 110 +++++++++++ .../riru/edxp}/proxy/BlackWhiteListProxy.java | 66 ++++--- .../riru/edxp/proxy/NormalProxy.java | 75 +++++++ .../elderdrivers/riru/edxp/proxy/Router.java | 30 +++ .../elderdrivers/riru/edxp/util/Hookers.java | 17 ++ edxp-core/build.gradle | 4 +- .../cpp/external/yahfa/include/HookMain.h | 13 +- edxp-core/src/main/cpp/main/include/config.h | 2 +- .../src/main/cpp/main/src/jni/edxp_yahfa.cpp | 4 - .../common/util_functions.sh | 2 +- edxp-sandhook/build.gradle | 4 +- .../sandhook/_hooker/HandleBindAppHooker.java | 112 ----------- .../_hooker/LoadedApkConstructorHooker.java | 111 ----------- .../_hooker/OnePlusWorkAroundHooker.java | 55 ------ .../_hooker/StartBootstrapServicesHooker.java | 80 -------- .../sandhook/config/SandHookEdxpConfig.java | 1 - .../sandhook/config/SandHookProvider.java | 1 - .../riru/edxp/sandhook/core/HookMain.java | 185 ------------------ .../sandhook/core/HookMethodResolver.java | 156 --------------- .../edxp/sandhook/core/SandHookEdxpImpl.java | 44 +++++ .../edxp/sandhook/core/SandHookRouter.java | 64 ++++++ .../edxp/sandhook/dexmaker/DexMakerUtils.java | 7 +- .../edxp/sandhook/dexmaker/DynamicBridge.java | 9 +- .../sandhook/dexmaker/HookerDexMaker.java | 3 +- .../{bootstrap => }/AppBootstrapHookInfo.java | 8 +- .../riru/edxp/sandhook/entry/Router.java | 159 --------------- .../{bootstrap => }/SysBootstrapHookInfo.java | 10 +- .../{bootstrap => }/SysInnerHookInfo.java | 4 +- .../{bootstrap => }/WorkAroundHookInfo.java | 4 +- .../sandhook/hooker/HandleBindAppHooker.java | 46 +++++ .../hooker/LoadedApkConstructorHooker.java | 58 ++++++ .../hooker/OnePlusWorkAroundHooker.java | 49 +++++ .../hooker/StartBootstrapServicesHooker.java | 42 ++++ .../{_hooker => hooker}/SystemMainHooker.java | 30 ++- .../sandhook/proxy/BlackWhiteListProxy.java | 137 ------------- .../riru/edxp/sandhook/proxy/NormalProxy.java | 73 ------- .../sandhook/xposedcompat/XposedCompat.java | 10 +- .../com.elderdrivers.riru.edxp.core.EdxpImpl | 1 + edxp-whale/build.gradle | 4 +- .../java/com/elderdrivers/riru/edxp/Main.java | 106 ---------- .../_hooker/LoadedApkConstructorHooker.java | 99 ---------- .../_hooker/OnePlusWorkAroundHooker.java | 41 ---- .../_hooker/StartBootstrapServicesHooker.java | 66 ------- .../edxp/whale/_hooker/SystemMainHooker.java | 43 ---- .../edxp/whale/config/WhaleEdxpConfig.java | 1 - .../edxp/whale/config/WhaleHookProvider.java | 1 - .../riru/edxp/whale/core/HookMain.java | 185 ------------------ .../riru/edxp/whale/core/WhaleEdxpImpl.java | 32 +++ .../riru/edxp/whale/core/WhaleRouter.java | 22 +++ .../riru/edxp/whale/dexmaker/DexLog.java | 37 ---- .../riru/edxp/whale/dexmaker/MethodInfo.java | 94 --------- .../riru/edxp/whale/entry/Router.java | 134 ------------- .../entry/bootstrap/SysBootstrapHookInfo.java | 16 -- .../entry/bootstrap/SysInnerHookInfo.java | 10 - .../riru/edxp/whale/proxy/NormalProxy.java | 73 ------- .../com.elderdrivers.riru.edxp.core.EdxpImpl | 1 + edxp-yahfa/build.gradle | 4 +- .../java/com/elderdrivers/riru/edxp/Main.java | 106 ---------- .../yahfa/_hooker/HandleBindAppHooker.java | 96 --------- .../_hooker/LoadedApkConstructorHooker.java | 99 ---------- .../edxp/yahfa/_hooker/SystemMainHooker.java | 43 ---- .../edxp/yahfa/config/YahfaEdxpConfig.java | 1 - .../edxp/yahfa/core/HookMethodResolver.java | 156 --------------- .../riru/edxp/yahfa/core/YahfaEdxpImpl.java | 56 ++++++ .../riru/edxp/yahfa/core/YahfaRouter.java | 23 +++ .../edxp/yahfa/dexmaker/DexMakerUtils.java | 7 +- .../edxp/yahfa/dexmaker/DynamicBridge.java | 11 +- .../edxp/yahfa/dexmaker/HookerDexMaker.java | 3 +- .../riru/edxp/yahfa/entry/Router.java | 135 ------------- .../entry/bootstrap/AppBootstrapHookInfo.java | 14 -- .../entry/bootstrap/WorkAroundHookInfo.java | 10 - .../edxp/yahfa/proxy/BlackWhiteListProxy.java | 137 ------------- .../riru/edxp/yahfa/proxy/NormalProxy.java | 72 ------- .../com.elderdrivers.riru.edxp.core.EdxpImpl | 1 + 99 files changed, 1338 insertions(+), 3089 deletions(-) rename edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/_hooker/HandleBindAppHooker.java => edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/HandleBindApp.java (74%) create mode 100644 edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/LoadedApkCstr.java rename edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/_hooker/OnePlusWorkAroundHooker.java => edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/OneplusWorkaround.java (51%) rename edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/_hooker/StartBootstrapServicesHooker.java => edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/StartBootstrapServices.java (60%) create mode 100644 edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/SystemMain.java create mode 100644 edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/HandleBindAppHooker.java create mode 100644 edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/LoadedApkConstructorHooker.java create mode 100644 edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/OnePlusWorkAroundHooker.java create mode 100644 edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/StartBootstrapServicesHooker.java create mode 100644 edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/SystemMainHooker.java create mode 100644 edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/BaseEdxpImpl.java create mode 100644 edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/EdxpImpl.java rename {edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp => edxp-common/src/main/java/com/elderdrivers/riru/edxp/core}/Main.java (60%) create mode 100644 edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/Proxy.java rename {edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/core => edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/yahfa}/HookMain.java (96%) rename {edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/core => edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/yahfa}/HookMethodResolver.java (95%) create mode 100644 edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/Hook.java create mode 100644 edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/HookImpl.java rename {edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/entry/bootstrap => edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa}/AppBootstrapHookInfo.java (58%) rename {edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/entry/bootstrap => edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa}/SysBootstrapHookInfo.java (55%) rename {edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/entry/bootstrap => edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa}/SysInnerHookInfo.java (65%) rename {edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/entry/bootstrap => edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa}/WorkAroundHookInfo.java (64%) create mode 100644 edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BaseProxy.java create mode 100644 edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BaseRouter.java rename {edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale => edxp-common/src/main/java/com/elderdrivers/riru/edxp}/proxy/BlackWhiteListProxy.java (65%) create mode 100644 edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/NormalProxy.java create mode 100644 edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/Router.java create mode 100644 edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/Hookers.java delete mode 100644 edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/_hooker/HandleBindAppHooker.java delete mode 100644 edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/_hooker/LoadedApkConstructorHooker.java delete mode 100644 edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/_hooker/OnePlusWorkAroundHooker.java delete mode 100644 edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/_hooker/StartBootstrapServicesHooker.java delete mode 100644 edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/core/HookMain.java delete mode 100644 edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/core/HookMethodResolver.java create mode 100644 edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/core/SandHookEdxpImpl.java create mode 100644 edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/core/SandHookRouter.java rename edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/{bootstrap => }/AppBootstrapHookInfo.java (63%) delete mode 100644 edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/Router.java rename edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/{bootstrap => }/SysBootstrapHookInfo.java (61%) rename edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/{bootstrap => }/SysInnerHookInfo.java (68%) rename edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/{bootstrap => }/WorkAroundHookInfo.java (68%) create mode 100644 edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/HandleBindAppHooker.java create mode 100644 edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/LoadedApkConstructorHooker.java create mode 100644 edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/OnePlusWorkAroundHooker.java create mode 100644 edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/StartBootstrapServicesHooker.java rename edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/{_hooker => hooker}/SystemMainHooker.java (54%) delete mode 100644 edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/proxy/BlackWhiteListProxy.java delete mode 100644 edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/proxy/NormalProxy.java create mode 100644 edxp-sandhook/src/main/resources/META-INF/services/com.elderdrivers.riru.edxp.core.EdxpImpl delete mode 100644 edxp-whale/src/main/java/com/elderdrivers/riru/edxp/Main.java delete mode 100644 edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/_hooker/LoadedApkConstructorHooker.java delete mode 100644 edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/_hooker/OnePlusWorkAroundHooker.java delete mode 100644 edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/_hooker/StartBootstrapServicesHooker.java delete mode 100644 edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/_hooker/SystemMainHooker.java delete mode 100644 edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/core/HookMain.java create mode 100644 edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/core/WhaleEdxpImpl.java create mode 100644 edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/core/WhaleRouter.java delete mode 100644 edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/dexmaker/DexLog.java delete mode 100644 edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/dexmaker/MethodInfo.java delete mode 100644 edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/entry/Router.java delete mode 100644 edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/entry/bootstrap/SysBootstrapHookInfo.java delete mode 100644 edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/entry/bootstrap/SysInnerHookInfo.java delete mode 100644 edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/proxy/NormalProxy.java create mode 100644 edxp-whale/src/main/resources/META-INF/services/com.elderdrivers.riru.edxp.core.EdxpImpl delete mode 100644 edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/Main.java delete mode 100644 edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/_hooker/HandleBindAppHooker.java delete mode 100644 edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/_hooker/LoadedApkConstructorHooker.java delete mode 100644 edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/_hooker/SystemMainHooker.java delete mode 100644 edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/core/HookMethodResolver.java create mode 100644 edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/core/YahfaEdxpImpl.java create mode 100644 edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/core/YahfaRouter.java delete mode 100644 edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/entry/Router.java delete mode 100644 edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/entry/bootstrap/AppBootstrapHookInfo.java delete mode 100644 edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/entry/bootstrap/WorkAroundHookInfo.java delete mode 100644 edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/proxy/BlackWhiteListProxy.java delete mode 100644 edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/proxy/NormalProxy.java create mode 100644 edxp-yahfa/src/main/resources/META-INF/services/com.elderdrivers.riru.edxp.core.EdxpImpl diff --git a/edxp-common/build.gradle b/edxp-common/build.gradle index 50985329..f07a4dda 100644 --- a/edxp-common/build.gradle +++ b/edxp-common/build.gradle @@ -23,6 +23,7 @@ dependencies { compileOnly project(':hiddenapi-stubs') implementation project(':xposed-bridge') compileOnly project(':dexmaker') + api "androidx.annotation:annotation:1.1.0-rc01" } diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/_hooker/HandleBindAppHooker.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/HandleBindApp.java similarity index 74% rename from edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/_hooker/HandleBindAppHooker.java rename to edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/HandleBindApp.java index 934bdde4..9e0d200c 100644 --- a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/_hooker/HandleBindAppHooker.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/HandleBindApp.java @@ -1,4 +1,4 @@ -package com.elderdrivers.riru.edxp.whale._hooker; +package com.elderdrivers.riru.edxp._hooker.impl; import android.app.ActivityThread; import android.app.LoadedApk; @@ -6,14 +6,14 @@ import android.content.ComponentName; import android.content.pm.ApplicationInfo; import android.content.res.CompatibilityInfo; -import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp.Main; +import com.elderdrivers.riru.edxp.config.ConfigManager; import com.elderdrivers.riru.edxp.hooker.SliceProviderFix; import com.elderdrivers.riru.edxp.hooker.XposedBlackListHooker; import com.elderdrivers.riru.edxp.hooker.XposedInstallerHooker; +import com.elderdrivers.riru.edxp.util.Hookers; import com.elderdrivers.riru.edxp.util.Utils; -import com.elderdrivers.riru.edxp.whale.entry.Router; +import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.XposedInit; @@ -25,26 +25,23 @@ import static com.elderdrivers.riru.edxp.hooker.XposedBlackListHooker.BLACK_LIST import static com.elderdrivers.riru.edxp.util.ClassLoaderUtils.replaceParentClassLoader; // normal process initialization (for new Activity, Service, BroadcastReceiver etc.) -public class HandleBindAppHooker implements KeepMembers { +public class HandleBindApp extends XC_MethodHook { - public static String className = "android.app.ActivityThread"; - public static String methodName = "handleBindApplication"; - public static String methodSig = "(Landroid/app/ActivityThread$AppBindData;)V"; - - public static void hook(Object thiz, Object bindData) { + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { if (XposedBlackListHooker.shouldDisableHooks("")) { - backup(thiz, bindData); return; } try { - Router.logD("ActivityThread#handleBindApplication() starts"); - ActivityThread activityThread = (ActivityThread) thiz; + Hookers.logD("ActivityThread#handleBindApplication() starts"); + ActivityThread activityThread = (ActivityThread) param.thisObject; + Object bindData = param.args[0]; ApplicationInfo appInfo = (ApplicationInfo) XposedHelpers.getObjectField(bindData, "appInfo"); // save app process name here for later use - Main.appProcessName = (String) XposedHelpers.getObjectField(bindData, "processName"); + ConfigManager.appProcessName = (String) XposedHelpers.getObjectField(bindData, "processName"); String reportedPackageName = appInfo.packageName.equals("android") ? "system" : appInfo.packageName; - Utils.logD("processName=" + Main.appProcessName + - ", packageName=" + reportedPackageName + ", appDataDir=" + Main.appDataDir); + Utils.logD("processName=" + ConfigManager.appProcessName + + ", packageName=" + reportedPackageName + ", appDataDir=" + ConfigManager.appDataDir); if (XposedBlackListHooker.shouldDisableHooks(reportedPackageName)) { return; @@ -52,7 +49,7 @@ public class HandleBindAppHooker implements KeepMembers { ComponentName instrumentationName = (ComponentName) XposedHelpers.getObjectField(bindData, "instrumentationName"); if (instrumentationName != null) { - Router.logD("Instrumentation detected, disabling framework for"); + Hookers.logD("Instrumentation detected, disabling framework for"); XposedBridge.disableHooks = true; return; } @@ -85,12 +82,7 @@ public class HandleBindAppHooker implements KeepMembers { SliceProviderFix.hook(); } } catch (Throwable t) { - Router.logE("error when hooking bindApp", t); - } finally { - backup(thiz, bindData); + Hookers.logE("error when hooking bindApp", t); } } - - public static void backup(Object thiz, Object bindData) { - } -} \ No newline at end of file +} diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/LoadedApkCstr.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/LoadedApkCstr.java new file mode 100644 index 00000000..394b0e02 --- /dev/null +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/LoadedApkCstr.java @@ -0,0 +1,76 @@ +package com.elderdrivers.riru.edxp._hooker.impl; + +import android.app.AndroidAppHelper; +import android.app.LoadedApk; +import android.util.Log; + +import com.elderdrivers.riru.edxp.hooker.XposedBlackListHooker; +import com.elderdrivers.riru.edxp.util.Hookers; + +import de.robv.android.xposed.XC_MethodHook; +import de.robv.android.xposed.XposedBridge; +import de.robv.android.xposed.XposedHelpers; +import de.robv.android.xposed.XposedInit; +import de.robv.android.xposed.callbacks.XC_LoadPackage; + +import static com.elderdrivers.riru.edxp.util.ClassLoaderUtils.replaceParentClassLoader; + +// when a package is loaded for an existing process, trigger the callbacks as well +// ed: remove resources related hooking +public class LoadedApkCstr extends XC_MethodHook { + + @Override + protected void afterHookedMethod(MethodHookParam param) throws Throwable { + if (XposedBlackListHooker.shouldDisableHooks("")) { + return; + } + + Hookers.logD("LoadedApk# starts"); + + try { + LoadedApk loadedApk = (LoadedApk) param.thisObject; + String packageName = loadedApk.getPackageName(); + Object mAppDir = XposedHelpers.getObjectField(loadedApk, "mAppDir"); + Hookers.logD("LoadedApk# ends: " + mAppDir); + + if (XposedBlackListHooker.shouldDisableHooks(packageName)) { + return; + } + + if (packageName.equals("android")) { + Hookers.logD("LoadedApk# is android, skip: " + mAppDir); + return; + } + + // mIncludeCode checking should go ahead of loadedPackagesInProcess added checking + if (!XposedHelpers.getBooleanField(loadedApk, "mIncludeCode")) { + Hookers.logD("LoadedApk# mIncludeCode == false: " + mAppDir); + return; + } + + if (!XposedInit.loadedPackagesInProcess.add(packageName)) { + Hookers.logD("LoadedApk# has been loaded before, skip: " + mAppDir); + return; + } + + // OnePlus magic... + if (Log.getStackTraceString(new Throwable()). + contains("android.app.ActivityThread$ApplicationThread.schedulePreload")) { + Hookers.logD("LoadedApk# maybe oneplus's custom opt, skip"); + return; + } + + replaceParentClassLoader(loadedApk.getClassLoader()); + + XC_LoadPackage.LoadPackageParam lpparam = new XC_LoadPackage.LoadPackageParam(XposedBridge.sLoadedPackageCallbacks); + lpparam.packageName = packageName; + lpparam.processName = AndroidAppHelper.currentProcessName(); + lpparam.classLoader = loadedApk.getClassLoader(); + lpparam.appInfo = loadedApk.getApplicationInfo(); + lpparam.isFirstApplication = false; + XC_LoadPackage.callAll(lpparam); + } catch (Throwable t) { + Hookers.logE("error when hooking LoadedApk.", t); + } + } +} diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/_hooker/OnePlusWorkAroundHooker.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/OneplusWorkaround.java similarity index 51% rename from edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/_hooker/OnePlusWorkAroundHooker.java rename to edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/OneplusWorkaround.java index 3da4402a..cccc23e2 100644 --- a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/_hooker/OnePlusWorkAroundHooker.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/OneplusWorkaround.java @@ -1,13 +1,14 @@ -package com.elderdrivers.riru.edxp.yahfa._hooker; +package com.elderdrivers.riru.edxp._hooker.impl; -import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp.Main; -import com.elderdrivers.riru.edxp.yahfa.entry.Router; +import com.elderdrivers.riru.edxp.core.Main; +import com.elderdrivers.riru.edxp.util.Hookers; +import dalvik.system.BaseDexClassLoader; +import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedBridge; /** - * On OnePlus stock roms (Android Pie), {@link dalvik.system.BaseDexClassLoader#findClass(String)} + * On OnePlus stock roms (Android Pie), {@link BaseDexClassLoader#findClass(String)} * will open /dev/binder to communicate with PackageManagerService to check whether * current package name inCompatConfigList, which is an OnePlus OEM feature enabled only when * system prop "persist.sys.oem.region" set to "CN".(detail of related source code: @@ -21,21 +22,15 @@ import de.robv.android.xposed.XposedBridge; * open of /dev/binder and we haven't found side effects yet. * Other roms might share the same problems but not reported too. */ -public class OnePlusWorkAroundHooker implements KeepMembers { +public class OneplusWorkaround extends XC_MethodHook { - public static String className = "dalvik.system.BaseDexClassLoader"; - public static String methodName = "inCompatConfigList"; - public static String methodSig = "(ILjava/lang/String;)Z"; - - public static boolean hook(int type, String packageName) { - if (XposedBridge.disableHooks || Router.forkCompleted) { - return backup(type, packageName); + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + if (XposedBridge.disableHooks || Main.getEdxpImpl().getRouter().isForkCompleted()) { + return; } - Router.logD("BaseDexClassLoader#inCompatConfigList() starts"); - return false; + Hookers.logD("BaseDexClassLoader#inCompatConfigList() starts"); + param.setResult(false); } - public static boolean backup(int type, String packageName) { - return false; - } -} \ No newline at end of file +} diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/_hooker/StartBootstrapServicesHooker.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/StartBootstrapServices.java similarity index 60% rename from edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/_hooker/StartBootstrapServicesHooker.java rename to edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/StartBootstrapServices.java index 5965c06a..41cbfb0a 100644 --- a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/_hooker/StartBootstrapServicesHooker.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/StartBootstrapServices.java @@ -1,10 +1,10 @@ -package com.elderdrivers.riru.edxp.yahfa._hooker; +package com.elderdrivers.riru.edxp._hooker.impl; import android.os.Build; -import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp.yahfa.entry.Router; +import com.elderdrivers.riru.edxp.util.Hookers; +import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XC_MethodReplacement; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; @@ -15,15 +15,11 @@ import static com.elderdrivers.riru.edxp.util.ClassLoaderUtils.replaceParentClas import static com.elderdrivers.riru.edxp.util.Utils.logD; import static de.robv.android.xposed.XposedHelpers.findAndHookMethod; -public class StartBootstrapServicesHooker implements KeepMembers { - public static String className = "com.android.server.SystemServer"; - public static String methodName = "startBootstrapServices"; - public static String methodSig = "()V"; - - public static void hook(Object systemServer) { +public class StartBootstrapServices extends XC_MethodHook { + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { if (XposedBridge.disableHooks) { - backup(systemServer); return; } @@ -32,35 +28,33 @@ public class StartBootstrapServicesHooker implements KeepMembers { try { XposedInit.loadedPackagesInProcess.add("android"); - replaceParentClassLoader(SystemMainHooker.systemServerCL); + replaceParentClassLoader(SystemMain.systemServerCL); XC_LoadPackage.LoadPackageParam lpparam = new XC_LoadPackage.LoadPackageParam(XposedBridge.sLoadedPackageCallbacks); lpparam.packageName = "android"; lpparam.processName = "android"; // it's actually system_server, but other functions return this as well - lpparam.classLoader = SystemMainHooker.systemServerCL; + lpparam.classLoader = SystemMain.systemServerCL; lpparam.appInfo = null; lpparam.isFirstApplication = true; XC_LoadPackage.callAll(lpparam); // Huawei try { - findAndHookMethod("com.android.server.pm.HwPackageManagerService", SystemMainHooker.systemServerCL, "isOdexMode", XC_MethodReplacement.returnConstant(false)); + findAndHookMethod("com.android.server.pm.HwPackageManagerService", + SystemMain.systemServerCL, "isOdexMode", + XC_MethodReplacement.returnConstant(false)); } catch (XposedHelpers.ClassNotFoundError | NoSuchMethodError ignored) { } try { String className = "com.android.server.pm." + (Build.VERSION.SDK_INT >= 23 ? "PackageDexOptimizer" : "PackageManagerService"); - findAndHookMethod(className, SystemMainHooker.systemServerCL, "dexEntryExists", String.class, XC_MethodReplacement.returnConstant(true)); + findAndHookMethod(className, SystemMain.systemServerCL, + "dexEntryExists", String.class, + XC_MethodReplacement.returnConstant(true)); } catch (XposedHelpers.ClassNotFoundError | NoSuchMethodError ignored) { } } catch (Throwable t) { - Router.logE("error when hooking startBootstrapServices", t); - } finally { - backup(systemServer); + Hookers.logE("error when hooking startBootstrapServices", t); } } - - public static void backup(Object systemServer) { - - } } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/SystemMain.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/SystemMain.java new file mode 100644 index 00000000..2d0a3802 --- /dev/null +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/SystemMain.java @@ -0,0 +1,33 @@ +package com.elderdrivers.riru.edxp._hooker.impl; + +import com.elderdrivers.riru.edxp.core.Main; +import com.elderdrivers.riru.edxp.deopt.PrebuiltMethodsDeopter; +import com.elderdrivers.riru.edxp.util.Hookers; + +import de.robv.android.xposed.XC_MethodHook; +import de.robv.android.xposed.XposedBridge; + +// system_server initialization +// ed: only support sdk >= 21 for now +public class SystemMain extends XC_MethodHook { + + public static volatile ClassLoader systemServerCL; + + @Override + protected void afterHookedMethod(MethodHookParam param) throws Throwable { + if (XposedBridge.disableHooks) { + return; + } + Hookers.logD("ActivityThread#systemMain() starts"); + try { + // get system_server classLoader + systemServerCL = Thread.currentThread().getContextClassLoader(); + // deopt methods in SYSTEMSERVERCLASSPATH + PrebuiltMethodsDeopter.deoptSystemServerMethods(systemServerCL); + Main.getEdxpImpl().getRouter().startSystemServerHook(); + } catch (Throwable t) { + Hookers.logE("error when hooking systemMain", t); + } + } + +} diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/HandleBindAppHooker.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/HandleBindAppHooker.java new file mode 100644 index 00000000..c203f31b --- /dev/null +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/HandleBindAppHooker.java @@ -0,0 +1,28 @@ +package com.elderdrivers.riru.edxp._hooker.yahfa; + +import com.elderdrivers.riru.common.KeepMembers; +import com.elderdrivers.riru.edxp._hooker.impl.HandleBindApp; + +import de.robv.android.xposed.XC_MethodHook; + +public class HandleBindAppHooker implements KeepMembers { + + public static String className = "android.app.ActivityThread"; + public static String methodName = "handleBindApplication"; + public static String methodSig = "(Landroid/app/ActivityThread$AppBindData;)V"; + + public static void hook(final Object thiz, final Object bindData) throws Throwable { + final XC_MethodHook methodHook = new HandleBindApp(); + final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam(); + param.thisObject = thiz; + param.args = new Object[]{bindData}; + methodHook.callBeforeHookedMethod(param); + if (!param.returnEarly) { + backup(thiz, bindData); + } + methodHook.callAfterHookedMethod(param); + } + + public static void backup(Object thiz, Object bindData) { + } +} \ No newline at end of file diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/LoadedApkConstructorHooker.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/LoadedApkConstructorHooker.java new file mode 100644 index 00000000..d499f2bf --- /dev/null +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/LoadedApkConstructorHooker.java @@ -0,0 +1,44 @@ +package com.elderdrivers.riru.edxp._hooker.yahfa; + +import android.app.ActivityThread; +import android.content.pm.ApplicationInfo; +import android.content.res.CompatibilityInfo; + +import com.elderdrivers.riru.common.KeepMembers; +import com.elderdrivers.riru.edxp._hooker.impl.LoadedApkCstr; + +import de.robv.android.xposed.XC_MethodHook; + +public class LoadedApkConstructorHooker implements KeepMembers { + public static String className = "android.app.LoadedApk"; + public static String methodName = ""; + public static String methodSig = "(Landroid/app/ActivityThread;" + + "Landroid/content/pm/ApplicationInfo;" + + "Landroid/content/res/CompatibilityInfo;" + + "Ljava/lang/ClassLoader;ZZZ)V"; + + public static void hook(Object thiz, ActivityThread activityThread, + ApplicationInfo aInfo, CompatibilityInfo compatInfo, + ClassLoader baseLoader, boolean securityViolation, + boolean includeCode, boolean registerPackage) throws Throwable { + + final XC_MethodHook methodHook = new LoadedApkCstr(); + final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam(); + param.thisObject = thiz; + param.args = new Object[]{activityThread, aInfo, compatInfo, baseLoader, securityViolation, + includeCode, registerPackage}; + methodHook.callBeforeHookedMethod(param); + if (!param.returnEarly) { + backup(thiz, activityThread, aInfo, compatInfo, baseLoader, securityViolation, + includeCode, registerPackage); + } + methodHook.callAfterHookedMethod(param); + } + + public static void backup(Object thiz, ActivityThread activityThread, + ApplicationInfo aInfo, CompatibilityInfo compatInfo, + ClassLoader baseLoader, boolean securityViolation, + boolean includeCode, boolean registerPackage) { + + } +} \ No newline at end of file diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/OnePlusWorkAroundHooker.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/OnePlusWorkAroundHooker.java new file mode 100644 index 00000000..2fb6b3d0 --- /dev/null +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/OnePlusWorkAroundHooker.java @@ -0,0 +1,35 @@ +package com.elderdrivers.riru.edxp._hooker.yahfa; + +import com.elderdrivers.riru.common.KeepMembers; +import com.elderdrivers.riru.edxp._hooker.impl.OneplusWorkaround; +import com.elderdrivers.riru.edxp.core.yahfa.HookMain; + +import de.robv.android.xposed.XC_MethodHook; + +public class OnePlusWorkAroundHooker implements KeepMembers { + + static { + HookMain.addHookItemWhiteList(OnePlusWorkAroundHooker.class.getName()); + } + + public static String className = "dalvik.system.BaseDexClassLoader"; + public static String methodName = "inCompatConfigList"; + public static String methodSig = "(ILjava/lang/String;)Z"; + + public static boolean hook(int type, String packageName) throws Throwable { + final XC_MethodHook methodHook = new OneplusWorkaround(); + final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam(); + param.thisObject = null; + param.args = new Object[]{type, packageName}; + methodHook.callBeforeHookedMethod(param); + if (!param.returnEarly) { + param.setResult(backup(type, packageName)); + } + methodHook.callAfterHookedMethod(param); + return (boolean) param.getResult(); + } + + public static boolean backup(int type, String packageName) { + return false; + } +} \ No newline at end of file diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/StartBootstrapServicesHooker.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/StartBootstrapServicesHooker.java new file mode 100644 index 00000000..17f1f519 --- /dev/null +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/StartBootstrapServicesHooker.java @@ -0,0 +1,28 @@ +package com.elderdrivers.riru.edxp._hooker.yahfa; + +import com.elderdrivers.riru.common.KeepMembers; +import com.elderdrivers.riru.edxp._hooker.impl.StartBootstrapServices; + +import de.robv.android.xposed.XC_MethodHook; + +public class StartBootstrapServicesHooker implements KeepMembers { + public static String className = "com.android.server.SystemServer"; + public static String methodName = "startBootstrapServices"; + public static String methodSig = "()V"; + + public static void hook(Object systemServer) throws Throwable { + final XC_MethodHook methodHook = new StartBootstrapServices(); + final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam(); + param.thisObject = systemServer; + param.args = new Object[]{}; + methodHook.callBeforeHookedMethod(param); + if (!param.returnEarly) { + backup(systemServer); + } + methodHook.callAfterHookedMethod(param); + } + + public static void backup(Object systemServer) { + + } +} diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/SystemMainHooker.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/SystemMainHooker.java new file mode 100644 index 00000000..9a8b7bd5 --- /dev/null +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/yahfa/SystemMainHooker.java @@ -0,0 +1,34 @@ +package com.elderdrivers.riru.edxp._hooker.yahfa; + +import android.app.ActivityThread; + +import com.elderdrivers.riru.common.KeepMembers; +import com.elderdrivers.riru.edxp._hooker.impl.OneplusWorkaround; + +import de.robv.android.xposed.XC_MethodHook; + +public class SystemMainHooker implements KeepMembers { + + public static String className = "android.app.ActivityThread"; + public static String methodName = "systemMain"; + public static String methodSig = "()Landroid/app/ActivityThread;"; + + public static ClassLoader systemServerCL; + + public static ActivityThread hook() throws Throwable { + final XC_MethodHook methodHook = new OneplusWorkaround(); + final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam(); + param.thisObject = null; + param.args = new Object[]{}; + methodHook.callBeforeHookedMethod(param); + if (!param.returnEarly) { + param.setResult(backup()); + } + methodHook.callAfterHookedMethod(param); + return (ActivityThread) param.getResult(); + } + + public static ActivityThread backup() { + return null; + } +} \ No newline at end of file diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/config/ConfigManager.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/config/ConfigManager.java index 013b14b0..cf579877 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/config/ConfigManager.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/config/ConfigManager.java @@ -1,27 +1,19 @@ package com.elderdrivers.riru.edxp.config; -import java.util.Collections; import java.util.HashMap; -import java.util.Set; import de.robv.android.xposed.SELinuxHelper; import static com.elderdrivers.riru.edxp.config.InstallerChooser.INSTALLER_DATA_BASE_DIR; -import static com.elderdrivers.riru.edxp.config.InstallerChooser.INSTALLER_PACKAGE_NAME; public class ConfigManager { - private static final String BLACK_LIST_PATH = INSTALLER_DATA_BASE_DIR + "conf/blacklist/"; - private static final String WHITE_LIST_PATH = INSTALLER_DATA_BASE_DIR + "conf/whitelist/"; - private static final String COMPAT_LIST_PATH = INSTALLER_DATA_BASE_DIR + "conf/compatlist/"; - private static final String USE_WHITE_LIST = INSTALLER_DATA_BASE_DIR + "conf/usewhitelist"; - private static final String DYNAMIC_MODULES = INSTALLER_DATA_BASE_DIR + "conf/dynamicmodules"; - private static final Set WHITE_LIST = Collections.singleton(INSTALLER_PACKAGE_NAME); - private static final HashMap compatModeCache = new HashMap<>(); + public static String appDataDir = ""; + public static String niceName = ""; + public static String appProcessName = ""; - public static boolean shouldUseWhitelist() { - return isFileExists(USE_WHITE_LIST); - } + private static final String COMPAT_LIST_PATH = INSTALLER_DATA_BASE_DIR + "conf/compatlist/"; + private static final HashMap compatModeCache = new HashMap<>(); public static boolean shouldUseCompatMode(String packageName) { Boolean result; @@ -34,17 +26,6 @@ public class ConfigManager { return result; } - public static boolean shouldHook(String packageName) { - if (WHITE_LIST.contains(packageName)) { - return true; - } - if (shouldUseWhitelist()) { - return isFileExists(WHITE_LIST_PATH + packageName); - } else { - return !isFileExists(BLACK_LIST_PATH + packageName); - } - } - private static boolean isFileExists(String path) { return SELinuxHelper.getAppDataFileService().checkFileExists(path); } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/BaseEdxpImpl.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/BaseEdxpImpl.java new file mode 100644 index 00000000..8b7593c2 --- /dev/null +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/BaseEdxpImpl.java @@ -0,0 +1,62 @@ +package com.elderdrivers.riru.edxp.core; + +import androidx.annotation.NonNull; + +import com.elderdrivers.riru.edxp.proxy.BlackWhiteListProxy; +import com.elderdrivers.riru.edxp.proxy.NormalProxy; +import com.elderdrivers.riru.edxp.proxy.Router; + +public abstract class BaseEdxpImpl implements EdxpImpl { + + protected Proxy mBlackWhiteListProxy; + protected Proxy mNormalProxy; + protected Router mRouter; + + protected boolean mInitialized = false; + + protected void setInitialized() { + mInitialized = true; + } + + @Override + public boolean isInitialized() { + return mInitialized; + } + + @NonNull + @Override + public Proxy getBlackWhiteListProxy() { + if (mBlackWhiteListProxy == null) { + mBlackWhiteListProxy = createBlackWhiteListProxy(); + } + return mBlackWhiteListProxy; + } + + @NonNull + @Override + public Proxy getNormalProxy() { + if (mNormalProxy == null) { + mNormalProxy = createNormalProxy(); + } + return mNormalProxy; + } + + @NonNull + @Override + public Router getRouter() { + if (mRouter == null) { + mRouter = createRouter(); + } + return mRouter; + } + + protected Proxy createBlackWhiteListProxy() { + return new BlackWhiteListProxy(getRouter()); + } + + protected Proxy createNormalProxy() { + return new NormalProxy(getRouter()); + } + + protected abstract Router createRouter(); +} diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/EdxpImpl.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/EdxpImpl.java new file mode 100644 index 00000000..33260594 --- /dev/null +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/EdxpImpl.java @@ -0,0 +1,40 @@ +package com.elderdrivers.riru.edxp.core; + +import androidx.annotation.IntDef; +import androidx.annotation.NonNull; + +import com.elderdrivers.riru.common.KeepAll; +import com.elderdrivers.riru.edxp.proxy.Router; + +import java.lang.annotation.Retention; + +import static java.lang.annotation.RetentionPolicy.SOURCE; + +public interface EdxpImpl extends KeepAll { + + int NONE = 0; + int YAHFA = 1; + int SANDHOOK = 2; + int WHALE = 3; + + @NonNull + Proxy getNormalProxy(); + + @NonNull + Proxy getBlackWhiteListProxy(); + + @NonNull + Router getRouter(); + + @Variant + int getVariant(); + + void init(); + + boolean isInitialized(); + + @Retention(SOURCE) + @IntDef({NONE, YAHFA, SANDHOOK, WHALE}) + @interface Variant { + } +} diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/Main.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/Main.java similarity index 60% rename from edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/Main.java rename to edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/Main.java index 6979ece7..31bdc641 100644 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/Main.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/Main.java @@ -1,44 +1,30 @@ -package com.elderdrivers.riru.edxp; +package com.elderdrivers.riru.edxp.core; import android.annotation.SuppressLint; -import android.os.Build; import android.os.Process; import com.elderdrivers.riru.common.KeepAll; +import com.elderdrivers.riru.edxp.BuildConfig; import com.elderdrivers.riru.edxp.config.ConfigManager; -import com.elderdrivers.riru.edxp.config.InstallerChooser; -import com.elderdrivers.riru.edxp.core.Yahfa; -import com.elderdrivers.riru.edxp.sandhook.BuildConfig; -import com.elderdrivers.riru.edxp.sandhook.core.HookMethodResolver; -import com.elderdrivers.riru.edxp.sandhook.entry.Router; -import com.elderdrivers.riru.edxp.sandhook.proxy.BlackWhiteListProxy; -import com.elderdrivers.riru.edxp.sandhook.proxy.NormalProxy; import com.elderdrivers.riru.edxp.util.Utils; -import com.swift.sandhook.xposedcompat.XposedCompat; -import com.swift.sandhook.xposedcompat.methodgen.SandHookXposedBridge; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.Arrays; +import java.util.Iterator; +import java.util.ServiceLoader; +import java.util.concurrent.atomic.AtomicReference; @SuppressLint("DefaultLocale") public class Main implements KeepAll { - public static String appDataDir = ""; - public static String niceName = ""; - public static String appProcessName = ""; private static String forkAndSpecializePramsStr = ""; private static String forkSystemServerPramsStr = ""; - static { - Yahfa.init(Build.VERSION.SDK_INT); - HookMethodResolver.init(); - Router.injectConfig(); - InstallerChooser.setInstallerPackageName(ConfigManager.getInstallerPackageName()); - SandHookXposedBridge.init(); - } + private static final AtomicReference edxpImplRef = new AtomicReference<>(null); - public static void setAppDataDir(String appDataDir) { - Main.appDataDir = appDataDir; - XposedCompat.appDataDir = appDataDir; + static { + loadEdxpImpls(); } /////////////////////////////////////////////////////////////////////////////////////////////// @@ -50,6 +36,10 @@ public class Main implements KeepAll { String niceName, int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir) { + final EdxpImpl edxp = getEdxpImpl(); + if (edxp == null || !edxp.isInitialized()) { + return; + } if (BuildConfig.DEBUG) { forkAndSpecializePramsStr = String.format( "Zygote#forkAndSpecialize(%d, %d, %s, %d, %s, %d, %s, %s, %s, %s, %s, %s, %s)", @@ -57,24 +47,29 @@ public class Main implements KeepAll { mountExternal, seInfo, niceName, Arrays.toString(fdsToClose), Arrays.toString(fdsToIgnore), startChildZygote, instructionSet, appDataDir); } + if (ConfigManager.isBlackWhiteListEnabled()) { - BlackWhiteListProxy.forkAndSpecializePre(uid, gid, gids, debugFlags, rlimits, + edxp.getBlackWhiteListProxy().forkAndSpecializePre(uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose, fdsToIgnore, startChildZygote, instructionSet, appDataDir); } else { - NormalProxy.forkAndSpecializePre(uid, gid, gids, debugFlags, rlimits, mountExternal, + edxp.getNormalProxy().forkAndSpecializePre(uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose, fdsToIgnore, startChildZygote, instructionSet, appDataDir); } } public static void forkAndSpecializePost(int pid, String appDataDir, String niceName) { + final EdxpImpl edxp = getEdxpImpl(); + if (edxp == null || !edxp.isInitialized()) { + return; + } if (pid == 0) { Utils.logD(forkAndSpecializePramsStr + " = " + Process.myPid()); if (ConfigManager.isBlackWhiteListEnabled()) { - BlackWhiteListProxy.forkAndSpecializePost(pid, appDataDir, niceName); + edxp.getBlackWhiteListProxy().forkAndSpecializePost(pid, appDataDir, niceName); } else { - NormalProxy.forkAndSpecializePost(pid, appDataDir, niceName); + edxp.getNormalProxy().forkAndSpecializePost(pid, appDataDir, niceName); } } else { // in zygote process, res is child zygote pid @@ -84,27 +79,35 @@ public class Main implements KeepAll { public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) { + final EdxpImpl edxp = getEdxpImpl(); + if (edxp == null || !edxp.isInitialized()) { + return; + } 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 (ConfigManager.isBlackWhiteListEnabled()) { - BlackWhiteListProxy.forkSystemServerPre(uid, gid, gids, debugFlags, rlimits, + edxp.getBlackWhiteListProxy().forkSystemServerPre(uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities); } else { - NormalProxy.forkSystemServerPre(uid, gid, gids, debugFlags, rlimits, + edxp.getNormalProxy().forkSystemServerPre(uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities); } } public static void forkSystemServerPost(int pid) { + final EdxpImpl edxp = getEdxpImpl(); + if (edxp == null || !edxp.isInitialized()) { + return; + } if (pid == 0) { Utils.logD(forkSystemServerPramsStr + " = " + Process.myPid()); if (ConfigManager.isBlackWhiteListEnabled()) { - BlackWhiteListProxy.forkSystemServerPost(pid); + edxp.getBlackWhiteListProxy().forkSystemServerPost(pid); } else { - NormalProxy.forkSystemServerPost(pid); + edxp.getNormalProxy().forkSystemServerPost(pid); } } else { // in zygote process, res is child zygote pid @@ -112,4 +115,29 @@ public class Main implements KeepAll { } } + public static synchronized boolean setEdxpImpl(EdxpImpl edxp) { + return edxpImplRef.compareAndSet(null, edxp); + } + + public static synchronized EdxpImpl getEdxpImpl() { + return edxpImplRef.get(); + } + + private static void loadEdxpImpls() { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + Iterator iterator = ServiceLoader.load( + EdxpImpl.class, Main.class.getClassLoader()).iterator(); + try { + while (iterator.hasNext()) { + iterator.next(); + } + } catch (Throwable t) { + // Do nothing + } + return null; + } + }); + } + } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/Proxy.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/Proxy.java new file mode 100644 index 00000000..c0518a3b --- /dev/null +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/Proxy.java @@ -0,0 +1,21 @@ +package com.elderdrivers.riru.edxp.core; + +import com.elderdrivers.riru.common.KeepAll; + +public interface Proxy extends KeepAll { + + boolean init(); + + void forkAndSpecializePre(int uid, int gid, int[] gids, int debugFlags, + int[][] rlimits, int mountExternal, String seInfo, + String niceName, int[] fdsToClose, int[] fdsToIgnore, + boolean startChildZygote, String instructionSet, + String appDataDir); + + void forkAndSpecializePost(int pid, String appDataDir, String niceName); + + void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, + long permittedCapabilities, long effectiveCapabilities); + + void forkSystemServerPost(int pid); +} diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/core/HookMain.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/yahfa/HookMain.java similarity index 96% rename from edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/core/HookMain.java rename to edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/yahfa/HookMain.java index 59a4a7ba..d41a4b1a 100644 --- a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/core/HookMain.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/yahfa/HookMain.java @@ -1,23 +1,26 @@ -package com.elderdrivers.riru.edxp.yahfa.core; +package com.elderdrivers.riru.edxp.core.yahfa; import com.elderdrivers.riru.edxp.art.Heap; import com.elderdrivers.riru.edxp.core.Yahfa; import com.elderdrivers.riru.edxp.util.Utils; -import com.elderdrivers.riru.edxp.yahfa._hooker.OnePlusWorkAroundHooker; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; +import java.util.HashSet; import java.util.Set; import de.robv.android.xposed.XposedHelpers; public class HookMain { - private static Set hookItemWhiteList = Collections.singleton(OnePlusWorkAroundHooker.class.getName()); + private static final Set hookItemWhiteList = new HashSet(); + + public static void addHookItemWhiteList(String className) { + hookItemWhiteList.add(className); + } public static void doHookDefault(ClassLoader patchClassLoader, ClassLoader originClassLoader, String hookInfoClassName) { try { diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/core/HookMethodResolver.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/yahfa/HookMethodResolver.java similarity index 95% rename from edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/core/HookMethodResolver.java rename to edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/yahfa/HookMethodResolver.java index b7f5a17c..d9545051 100644 --- a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/core/HookMethodResolver.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/yahfa/HookMethodResolver.java @@ -1,8 +1,7 @@ -package com.elderdrivers.riru.edxp.whale.core; +package com.elderdrivers.riru.edxp.core.yahfa; import android.os.Build; -import com.elderdrivers.riru.edxp.Main; import com.elderdrivers.riru.edxp.core.Yahfa; import com.elderdrivers.riru.edxp.util.Utils; @@ -113,12 +112,12 @@ public class HookMethodResolver { Object artMethod = artMethodField.get(backup); int dexMethodIndex = (int) dexMethodIndexField.get(artMethod); Object resolvedMethods = resolvedMethodsField.get(dexCache); - ((Object[])resolvedMethods)[dexMethodIndex] = artMethod; + ((Object[]) resolvedMethods)[dexMethodIndex] = artMethod; } else { int dexMethodIndex = (int) dexMethodIndexField.get(backup); Object resolvedMethods = resolvedMethodsField.get(dexCache); long artMethod = (long) artMethodField.get(backup); - ((long[])resolvedMethods)[dexMethodIndex] = artMethod; + ((long[]) resolvedMethods)[dexMethodIndex] = artMethod; } } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/Hook.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/Hook.java new file mode 100644 index 00000000..06d65505 --- /dev/null +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/Hook.java @@ -0,0 +1,4 @@ +package com.elderdrivers.riru.edxp.entry; + +public interface Hook { +} diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/HookImpl.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/HookImpl.java new file mode 100644 index 00000000..6dae3896 --- /dev/null +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/HookImpl.java @@ -0,0 +1,5 @@ +package com.elderdrivers.riru.edxp.entry; + +public class HookImpl implements Hook { + +} diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/entry/bootstrap/AppBootstrapHookInfo.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/AppBootstrapHookInfo.java similarity index 58% rename from edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/entry/bootstrap/AppBootstrapHookInfo.java rename to edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/AppBootstrapHookInfo.java index 251a2727..c76b47af 100644 --- a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/entry/bootstrap/AppBootstrapHookInfo.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/AppBootstrapHookInfo.java @@ -1,9 +1,9 @@ -package com.elderdrivers.riru.edxp.whale.entry.bootstrap; +package com.elderdrivers.riru.edxp.entry.yahfa; import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp.whale._hooker.HandleBindAppHooker; -import com.elderdrivers.riru.edxp.whale._hooker.LoadedApkConstructorHooker; -import com.elderdrivers.riru.edxp.whale._hooker.OnePlusWorkAroundHooker; +import com.elderdrivers.riru.edxp._hooker.yahfa.HandleBindAppHooker; +import com.elderdrivers.riru.edxp._hooker.yahfa.LoadedApkConstructorHooker; +import com.elderdrivers.riru.edxp._hooker.yahfa.OnePlusWorkAroundHooker; public class AppBootstrapHookInfo implements KeepMembers { public static String[] hookItemNames = { diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/entry/bootstrap/SysBootstrapHookInfo.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/SysBootstrapHookInfo.java similarity index 55% rename from edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/entry/bootstrap/SysBootstrapHookInfo.java rename to edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/SysBootstrapHookInfo.java index 06f53248..68656961 100644 --- a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/entry/bootstrap/SysBootstrapHookInfo.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/SysBootstrapHookInfo.java @@ -1,10 +1,10 @@ -package com.elderdrivers.riru.edxp.yahfa.entry.bootstrap; +package com.elderdrivers.riru.edxp.entry.yahfa; import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp.yahfa._hooker.HandleBindAppHooker; -import com.elderdrivers.riru.edxp.yahfa._hooker.LoadedApkConstructorHooker; -import com.elderdrivers.riru.edxp.yahfa._hooker.OnePlusWorkAroundHooker; -import com.elderdrivers.riru.edxp.yahfa._hooker.SystemMainHooker; +import com.elderdrivers.riru.edxp._hooker.yahfa.HandleBindAppHooker; +import com.elderdrivers.riru.edxp._hooker.yahfa.LoadedApkConstructorHooker; +import com.elderdrivers.riru.edxp._hooker.yahfa.OnePlusWorkAroundHooker; +import com.elderdrivers.riru.edxp._hooker.yahfa.SystemMainHooker; public class SysBootstrapHookInfo implements KeepMembers { public static String[] hookItemNames = { diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/entry/bootstrap/SysInnerHookInfo.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/SysInnerHookInfo.java similarity index 65% rename from edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/entry/bootstrap/SysInnerHookInfo.java rename to edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/SysInnerHookInfo.java index 176dd744..19400753 100644 --- a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/entry/bootstrap/SysInnerHookInfo.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/SysInnerHookInfo.java @@ -1,7 +1,7 @@ -package com.elderdrivers.riru.edxp.yahfa.entry.bootstrap; +package com.elderdrivers.riru.edxp.entry.yahfa; import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp.yahfa._hooker.StartBootstrapServicesHooker; +import com.elderdrivers.riru.edxp._hooker.yahfa.StartBootstrapServicesHooker; public class SysInnerHookInfo implements KeepMembers { public static String[] hookItemNames = { diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/entry/bootstrap/WorkAroundHookInfo.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/WorkAroundHookInfo.java similarity index 64% rename from edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/entry/bootstrap/WorkAroundHookInfo.java rename to edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/WorkAroundHookInfo.java index 8fe859e2..ecf36e5e 100644 --- a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/entry/bootstrap/WorkAroundHookInfo.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/entry/yahfa/WorkAroundHookInfo.java @@ -1,7 +1,7 @@ -package com.elderdrivers.riru.edxp.whale.entry.bootstrap; +package com.elderdrivers.riru.edxp.entry.yahfa; import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp.whale._hooker.OnePlusWorkAroundHooker; +import com.elderdrivers.riru.edxp._hooker.yahfa.OnePlusWorkAroundHooker; public class WorkAroundHookInfo implements KeepMembers { public static String[] hookItemNames = { diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BaseProxy.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BaseProxy.java new file mode 100644 index 00000000..fbdd851a --- /dev/null +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BaseProxy.java @@ -0,0 +1,17 @@ +package com.elderdrivers.riru.edxp.proxy; + +import com.elderdrivers.riru.edxp.core.Proxy; + +public abstract class BaseProxy implements Proxy { + + protected Router mRouter; + + public BaseProxy(Router router) { + mRouter = router; + } + + @Override + public boolean init() { + return true; + } +} diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BaseRouter.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BaseRouter.java new file mode 100644 index 00000000..c50a8c68 --- /dev/null +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BaseRouter.java @@ -0,0 +1,110 @@ +package com.elderdrivers.riru.edxp.proxy; + +import android.text.TextUtils; + +import com.elderdrivers.riru.edxp._hooker.yahfa.SystemMainHooker; +import com.elderdrivers.riru.edxp.core.yahfa.HookMain; +import com.elderdrivers.riru.edxp.entry.yahfa.AppBootstrapHookInfo; +import com.elderdrivers.riru.edxp.entry.yahfa.SysBootstrapHookInfo; +import com.elderdrivers.riru.edxp.entry.yahfa.SysInnerHookInfo; +import com.elderdrivers.riru.edxp.entry.yahfa.WorkAroundHookInfo; +import com.elderdrivers.riru.edxp.util.Utils; + +import java.util.concurrent.atomic.AtomicBoolean; + +import de.robv.android.xposed.XposedBridge; +import de.robv.android.xposed.XposedInit; + +public abstract class BaseRouter implements Router { + + protected volatile boolean forkCompleted = false; + + protected volatile AtomicBoolean bootstrapHooked = new AtomicBoolean(false); + + public void initResourcesHook() { + startWorkAroundHook(); // for OnePlus devices + XposedBridge.initXResources(); + } + + public void prepare(boolean isSystem) { + // this flag is needed when loadModules + XposedInit.startsSystemServer = isSystem; + } + + public void onForkStart() { + forkCompleted = false; + } + + public void onForkFinish() { + forkCompleted = true; + } + + public boolean isForkCompleted() { + return forkCompleted; + } + + public void installBootstrapHooks(boolean isSystem) { + // Initialize the Xposed framework + try { + if (!bootstrapHooked.compareAndSet(false, true)) { + return; + } + startBootstrapHook(isSystem); + XposedInit.initForZygote(isSystem); + } catch (Throwable t) { + Utils.logE("error during Xposed initialization", t); + XposedBridge.disableHooks = true; + } + } + + public void loadModulesSafely(boolean isInZygote) { + try { + // FIXME some coredomain app can't reading modules.list + XposedInit.loadModules(isInZygote); + } catch (Exception exception) { + Utils.logE("error loading module list", exception); + } + } + + public String parsePackageName(String appDataDir) { + if (TextUtils.isEmpty(appDataDir)) { + return ""; + } + int lastIndex = appDataDir.lastIndexOf("/"); + if (lastIndex < 1) { + return ""; + } + return appDataDir.substring(lastIndex + 1); + } + + + public void startBootstrapHook(boolean isSystem) { + Utils.logD("startBootstrapHook starts: isSystem = " + isSystem); + ClassLoader classLoader = XposedBridge.BOOTCLASSLOADER; + if (isSystem) { + HookMain.doHookDefault( + BaseRouter.class.getClassLoader(), + classLoader, + SysBootstrapHookInfo.class.getName()); + } else { + HookMain.doHookDefault( + BaseRouter.class.getClassLoader(), + classLoader, + AppBootstrapHookInfo.class.getName()); + } + } + + public void startSystemServerHook() { + HookMain.doHookDefault( + BaseRouter.class.getClassLoader(), + SystemMainHooker.systemServerCL, + SysInnerHookInfo.class.getName()); + } + + public void startWorkAroundHook() { + HookMain.doHookDefault( + BaseRouter.class.getClassLoader(), + XposedBridge.BOOTCLASSLOADER, + WorkAroundHookInfo.class.getName()); + } +} diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/proxy/BlackWhiteListProxy.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BlackWhiteListProxy.java similarity index 65% rename from edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/proxy/BlackWhiteListProxy.java rename to edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BlackWhiteListProxy.java index d8e97686..7abfa1ff 100644 --- a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/proxy/BlackWhiteListProxy.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BlackWhiteListProxy.java @@ -1,14 +1,12 @@ -package com.elderdrivers.riru.edxp.whale.proxy; +package com.elderdrivers.riru.edxp.proxy; import android.text.TextUtils; -import com.elderdrivers.riru.edxp.Main; import com.elderdrivers.riru.edxp.config.ConfigManager; import com.elderdrivers.riru.edxp.deopt.PrebuiltMethodsDeopter; import com.elderdrivers.riru.edxp.framework.Zygote; import com.elderdrivers.riru.edxp.util.ProcessUtils; import com.elderdrivers.riru.edxp.util.Utils; -import com.elderdrivers.riru.edxp.whale.entry.Router; import de.robv.android.xposed.XposedBridge; @@ -33,13 +31,17 @@ import static com.elderdrivers.riru.edxp.util.FileUtils.getDataPathPrefix; * 2. Dynamic mode: * to be continued */ -public class BlackWhiteListProxy { +public class BlackWhiteListProxy extends BaseProxy { - public static void forkAndSpecializePre(int uid, int gid, int[] gids, int debugFlags, - int[][] rlimits, int mountExternal, String seInfo, - String niceName, int[] fdsToClose, int[] fdsToIgnore, - boolean startChildZygote, String instructionSet, - String appDataDir) { + public BlackWhiteListProxy(Router router) { + super(router); + } + + public void forkAndSpecializePre(int uid, int gid, int[] gids, int debugFlags, + int[][] rlimits, int mountExternal, String seInfo, + String niceName, int[] fdsToClose, int[] fdsToIgnore, + boolean startChildZygote, String instructionSet, + String appDataDir) { final boolean isDynamicModulesMode = ConfigManager.isDynamicModulesEnabled(); if (isDynamicModulesMode) { // should never happen @@ -49,13 +51,13 @@ public class BlackWhiteListProxy { onForkPreForNonDynamicMode(false); } - public static void forkAndSpecializePost(int pid, String appDataDir, String niceName) { + public void forkAndSpecializePost(int pid, String appDataDir, String niceName) { onForkPostCommon(false, appDataDir, niceName); } - public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, - int[][] rlimits, long permittedCapabilities, - long effectiveCapabilities) { + public void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, + int[][] rlimits, long permittedCapabilities, + long effectiveCapabilities) { final boolean isDynamicModulesMode = ConfigManager.isDynamicModulesEnabled(); if (isDynamicModulesMode) { // should never happen @@ -65,59 +67,59 @@ public class BlackWhiteListProxy { onForkPreForNonDynamicMode(true); } - public static void forkSystemServerPost(int pid) { + public void forkSystemServerPost(int pid) { onForkPostCommon(true, getDataPathPrefix() + "android", "system_server"); } /** * Some details are different between main zygote and secondary zygote. */ - private static void onForkPreForNonDynamicMode(boolean isSystemServer) { - Router.onForkStart(); - Router.initResourcesHook(); + private void onForkPreForNonDynamicMode(boolean isSystemServer) { + mRouter.onForkStart(); + mRouter.initResourcesHook(); // set startsSystemServer flag used when loadModules - Router.prepare(isSystemServer); + mRouter.prepare(isSystemServer); // deoptBootMethods once for all child processes of zygote PrebuiltMethodsDeopter.deoptBootMethods(); // we never install bootstrap hooks here in black/white list mode except workaround hooks // because installed hooks would be propagated to all child processes of zygote - Router.startWorkAroundHook(); + mRouter.startWorkAroundHook(); // loadModules once for all child processes of zygote // TODO maybe just save initZygote callbacks and call them when whitelisted process forked? - Router.loadModulesSafely(true); + mRouter.loadModulesSafely(true); Zygote.closeFilesBeforeFork(); } - private static void onForkPostCommon(boolean isSystemServer, String appDataDir, String niceName) { - Main.appDataDir = appDataDir; - Main.niceName = niceName; + private void onForkPostCommon(boolean isSystemServer, String appDataDir, String niceName) { + ConfigManager.appDataDir = appDataDir; + ConfigManager.niceName = niceName; final boolean isDynamicModulesMode = ConfigManager.isDynamicModulesEnabled(); if (!isDynamicModulesMode) { Zygote.reopenFilesAfterFork(); } - Router.onEnterChildProcess(); + mRouter.onEnterChildProcess(); if (!checkNeedHook(appDataDir, niceName)) { // if is blacklisted, just stop here - Router.onForkFinish(); + mRouter.onForkFinish(); return; } if (isDynamicModulesMode) { - Router.initResourcesHook(); + mRouter.initResourcesHook(); } - Router.prepare(isSystemServer); + mRouter.prepare(isSystemServer); PrebuiltMethodsDeopter.deoptBootMethods(); - Router.installBootstrapHooks(isSystemServer); + mRouter.installBootstrapHooks(isSystemServer); if (isDynamicModulesMode) { - Router.loadModulesSafely(false); + mRouter.loadModulesSafely(false); } - Router.onForkFinish(); + mRouter.onForkFinish(); } - private static boolean checkNeedHook(String appDataDir, String niceName) { + private boolean checkNeedHook(String appDataDir, String niceName) { boolean needHook; if (TextUtils.isEmpty(appDataDir)) { Utils.logE("niceName:" + niceName + ", procName:" - + ProcessUtils.getCurrentProcessName(Main.appProcessName) + ", appDataDir is null, blacklisted!"); + + ProcessUtils.getCurrentProcessName(ConfigManager.appProcessName) + ", appDataDir is null, blacklisted!"); needHook = false; } else { // FIXME some process cannot read app_data_file because of MLS, e.g. bluetooth diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/NormalProxy.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/NormalProxy.java new file mode 100644 index 00000000..68c46233 --- /dev/null +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/NormalProxy.java @@ -0,0 +1,75 @@ +package com.elderdrivers.riru.edxp.proxy; + +import com.elderdrivers.riru.edxp.config.ConfigManager; +import com.elderdrivers.riru.edxp.deopt.PrebuiltMethodsDeopter; +import com.elderdrivers.riru.edxp.framework.Zygote; + +import static com.elderdrivers.riru.edxp.util.FileUtils.getDataPathPrefix; + +public class NormalProxy extends BaseProxy { + + public NormalProxy(Router router) { + super(router); + } + + public void forkAndSpecializePre(int uid, int gid, int[] gids, int debugFlags, + int[][] rlimits, int mountExternal, String seInfo, + String niceName, int[] fdsToClose, int[] fdsToIgnore, + boolean startChildZygote, String instructionSet, + String appDataDir) { + // mainly for secondary zygote + mRouter.onForkStart(); + mRouter.initResourcesHook(); + // call this to ensure the flag is set to false ASAP + mRouter.prepare(false); + PrebuiltMethodsDeopter.deoptBootMethods(); // do it once for secondary zygote + // install bootstrap hooks for secondary zygote + mRouter.installBootstrapHooks(false); + // only load modules for secondary zygote + mRouter.loadModulesSafely(true); + Zygote.closeFilesBeforeFork(); + } + + public void forkAndSpecializePost(int pid, String appDataDir, String niceName) { + // TODO consider processes without forkAndSpecializePost called + ConfigManager.appDataDir = appDataDir; + ConfigManager.niceName = niceName; + mRouter.prepare(false); + Zygote.reopenFilesAfterFork(); + mRouter.onEnterChildProcess(); + // load modules for each app process on its forked if dynamic modules mode is on + mRouter.loadModulesSafely(false); + mRouter.onForkFinish(); + } + + public void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, + long permittedCapabilities, long effectiveCapabilities) { + mRouter.onForkStart(); + mRouter.initResourcesHook(); + // set startsSystemServer flag used when loadModules + mRouter.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 + mRouter.installBootstrapHooks(true); + // loadModules have to be executed in zygote even isDynamicModules is false + // because if not global hooks installed in initZygote might not be + // propagated to processes not forked via forkAndSpecialize + mRouter.loadModulesSafely(true); + Zygote.closeFilesBeforeFork(); + } + + public void forkSystemServerPost(int pid) { + // in system_server process + ConfigManager.appDataDir = getDataPathPrefix() + "android"; + ConfigManager.niceName = "system_server"; + mRouter.prepare(true); + Zygote.reopenFilesAfterFork(); + mRouter.onEnterChildProcess(); + // reload module list if dynamic mode is on + mRouter.loadModulesSafely(false); + mRouter.onForkFinish(); + } + +} diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/Router.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/Router.java new file mode 100644 index 00000000..223524dc --- /dev/null +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/Router.java @@ -0,0 +1,30 @@ +package com.elderdrivers.riru.edxp.proxy; + +public interface Router { + + void initResourcesHook(); + + void prepare(boolean isSystem); + + String parsePackageName(String appDataDir); + + void installBootstrapHooks(boolean isSystem); + + void loadModulesSafely(boolean isInZygote); + + void startBootstrapHook(boolean isSystem); + + void startSystemServerHook(); + + void startWorkAroundHook(); + + void onForkStart(); + + void onForkFinish(); + + void onEnterChildProcess(); + + void injectConfig(); + + boolean isForkCompleted(); +} diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/Hookers.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/Hookers.java new file mode 100644 index 00000000..c7f13793 --- /dev/null +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/Hookers.java @@ -0,0 +1,17 @@ +package com.elderdrivers.riru.edxp.util; + +import android.app.AndroidAppHelper; + +public class Hookers { + + public static void logD(String prefix) { + Utils.logD(String.format("%s: pkg=%s, prc=%s", prefix, AndroidAppHelper.currentPackageName(), + AndroidAppHelper.currentProcessName())); + } + + public static void logE(String prefix, Throwable throwable) { + Utils.logE(String.format("%s: pkg=%s, prc=%s", prefix, AndroidAppHelper.currentPackageName(), + AndroidAppHelper.currentProcessName()), throwable); + } + +} diff --git a/edxp-core/build.gradle b/edxp-core/build.gradle index 28a8bb5f..23987389 100644 --- a/edxp-core/build.gradle +++ b/edxp-core/build.gradle @@ -3,10 +3,10 @@ import org.gradle.internal.os.OperatingSystem apply plugin: 'com.android.library' -version "v0.4.3.0_alpha" +version "v0.4.3.2_alpha" ext { - versionCode = "4300" + versionCode = "4320" module_name = "EdXposed" jar_dest_dir = "${projectDir}/template_override/system/framework/" is_windows = OperatingSystem.current().isWindows() diff --git a/edxp-core/src/main/cpp/external/yahfa/include/HookMain.h b/edxp-core/src/main/cpp/external/yahfa/include/HookMain.h index 2aff8bee..6847da10 100644 --- a/edxp-core/src/main/cpp/external/yahfa/include/HookMain.h +++ b/edxp-core/src/main/cpp/external/yahfa/include/HookMain.h @@ -3,10 +3,15 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + void Java_lab_galaxy_yahfa_HookMain_init(JNIEnv *env, jclass clazz, jint sdkVersion); jobject Java_lab_galaxy_yahfa_HookMain_findMethodNative(JNIEnv *env, jclass clazz, - jclass targetClass, jstring methodName, jstring methodSig); + jclass targetClass, jstring methodName, + jstring methodSig); jboolean Java_lab_galaxy_yahfa_HookMain_backupAndHookNative(JNIEnv *env, jclass clazz, jobject target, jobject hook, @@ -18,6 +23,10 @@ void Java_lab_galaxy_yahfa_HookMain_ensureMethodCached(JNIEnv *env, jclass clazz void setNonCompilable(void *method); -static void* getResolvedMethodsAddr(JNIEnv*, jobject); +static void *getResolvedMethodsAddr(JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif #endif // HOOK_MAIN_H \ No newline at end of file diff --git a/edxp-core/src/main/cpp/main/include/config.h b/edxp-core/src/main/cpp/main/include/config.h index abf85568..c9a6c2c9 100644 --- a/edxp-core/src/main/cpp/main/include/config.h +++ b/edxp-core/src/main/cpp/main/include/config.h @@ -20,7 +20,7 @@ namespace edxp { static constexpr const char *kInjectDexPath = "/system/framework/edxp.jar:" "/system/framework/eddalvikdx.jar:" "/system/framework/eddexmaker.jar"; - static constexpr const char *kEntryClassName = "com.elderdrivers.riru.edxp.Main"; + static constexpr const char *kEntryClassName = "com.elderdrivers.riru.edxp.core.Main"; static constexpr const char *kSandHookClassName = "com.swift.sandhook.SandHook"; static constexpr const char *kSandHookNeverCallClassName = "com.swift.sandhook.ClassNeverCall"; diff --git a/edxp-core/src/main/cpp/main/src/jni/edxp_yahfa.cpp b/edxp-core/src/main/cpp/main/src/jni/edxp_yahfa.cpp index fa3b623f..f9b4cbcb 100644 --- a/edxp-core/src/main/cpp/main/src/jni/edxp_yahfa.cpp +++ b/edxp-core/src/main/cpp/main/src/jni/edxp_yahfa.cpp @@ -1,9 +1,5 @@ -extern "C" -{ #include "HookMain.h" -} - #include #include "jni.h" #include "native_util.h" diff --git a/edxp-core/template_override/common/util_functions.sh b/edxp-core/template_override/common/util_functions.sh index d4b00e65..bef67bf1 100644 --- a/edxp-core/template_override/common/util_functions.sh +++ b/edxp-core/template_override/common/util_functions.sh @@ -1,6 +1,6 @@ #!/system/bin/sh -EDXP_VERSION="0.4.3.0_alpha (4300)" +EDXP_VERSION="0.4.3.2_alpha (4320)" ANDROID_SDK=`getprop ro.build.version.sdk` BUILD_DESC=`getprop ro.build.description` PRODUCT=`getprop ro.build.product` diff --git a/edxp-sandhook/build.gradle b/edxp-sandhook/build.gradle index a26f6132..b377eddc 100644 --- a/edxp-sandhook/build.gradle +++ b/edxp-sandhook/build.gradle @@ -12,6 +12,7 @@ android { targetSdkVersion 28 versionCode 1 versionName "1.0" + multiDexEnabled true } buildTypes { @@ -61,7 +62,8 @@ afterEvaluate { task("makeAndCopy${variantNameCapped}", type: Jar, dependsOn: "assemble${variantNameCapped}") { dependsOn tasks.getByPath(":edxp-common:copyCommonProperties") - from "${buildDir}/intermediates/transforms/dexMerger/${variantNameLowered}/0/" + from "${buildDir}/intermediates/transforms/dexMerger/${variantNameLowered}/0/", + "${projectDir}/src/main/resources/" destinationDir file(myTemplatePath + "system/framework/") baseName "edxp" doLast { diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/_hooker/HandleBindAppHooker.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/_hooker/HandleBindAppHooker.java deleted file mode 100644 index 00613ac3..00000000 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/_hooker/HandleBindAppHooker.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.elderdrivers.riru.edxp.sandhook._hooker; - -import android.app.ActivityThread; -import android.app.LoadedApk; -import android.content.ComponentName; -import android.content.pm.ApplicationInfo; -import android.content.res.CompatibilityInfo; - -import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp.Main; -import com.elderdrivers.riru.edxp.hooker.SliceProviderFix; -import com.elderdrivers.riru.edxp.hooker.XposedBlackListHooker; -import com.elderdrivers.riru.edxp.hooker.XposedInstallerHooker; -import com.elderdrivers.riru.edxp.sandhook.entry.Router; -import com.elderdrivers.riru.edxp.util.Utils; -import com.swift.sandhook.SandHook; -import com.swift.sandhook.annotation.HookClass; -import com.swift.sandhook.annotation.HookMethod; -import com.swift.sandhook.annotation.HookMethodBackup; -import com.swift.sandhook.annotation.Param; -import com.swift.sandhook.annotation.SkipParamCheck; -import com.swift.sandhook.annotation.ThisObject; - -import java.lang.reflect.Method; - -import de.robv.android.xposed.XposedBridge; -import de.robv.android.xposed.XposedHelpers; -import de.robv.android.xposed.XposedInit; -import de.robv.android.xposed.callbacks.XC_LoadPackage; - -import static com.elderdrivers.riru.edxp.config.InstallerChooser.INSTALLER_PACKAGE_NAME; -import static com.elderdrivers.riru.edxp.hooker.SliceProviderFix.SYSTEMUI_PACKAGE_NAME; -import static com.elderdrivers.riru.edxp.hooker.XposedBlackListHooker.BLACK_LIST_PACKAGE_NAME; -import static com.elderdrivers.riru.edxp.util.ClassLoaderUtils.replaceParentClassLoader; - -// normal process initialization (for new Activity, Service, BroadcastReceiver etc.) -@HookClass(ActivityThread.class) -public class HandleBindAppHooker implements KeepMembers { - - public static String className = "android.app.ActivityThread"; - public static String methodName = "handleBindApplication"; - public static String methodSig = "(Landroid/app/ActivityThread$AppBindData;)V"; - - @HookMethodBackup("handleBindApplication") - @SkipParamCheck - static Method backup; - - @HookMethod("handleBindApplication") - public static void hook(@ThisObject ActivityThread thiz, @Param("android.app.ActivityThread$AppBindData") Object bindData) throws Throwable { - if (XposedBlackListHooker.shouldDisableHooks("")) { - backup(thiz, bindData); - return; - } - try { - Router.logD("ActivityThread#handleBindApplication() starts"); - ActivityThread activityThread = (ActivityThread) thiz; - ApplicationInfo appInfo = (ApplicationInfo) XposedHelpers.getObjectField(bindData, "appInfo"); - // save app process name here for later use - Main.appProcessName = (String) XposedHelpers.getObjectField(bindData, "processName"); - String reportedPackageName = appInfo.packageName.equals("android") ? "system" : appInfo.packageName; - Utils.logD("processName=" + Main.appProcessName + - ", packageName=" + reportedPackageName + ", appDataDir=" + Main.appDataDir); - - if (XposedBlackListHooker.shouldDisableHooks(reportedPackageName)) { - return; - } - - ComponentName instrumentationName = (ComponentName) XposedHelpers.getObjectField(bindData, "instrumentationName"); - if (instrumentationName != null) { - Router.logD("Instrumentation detected, disabling framework for"); - XposedBridge.disableHooks = true; - return; - } - CompatibilityInfo compatInfo = (CompatibilityInfo) XposedHelpers.getObjectField(bindData, "compatInfo"); - if (appInfo.sourceDir == null) { - return; - } - - XposedHelpers.setObjectField(activityThread, "mBoundApplication", bindData); - XposedInit.loadedPackagesInProcess.add(reportedPackageName); - LoadedApk loadedApk = activityThread.getPackageInfoNoCheck(appInfo, compatInfo); - - replaceParentClassLoader(loadedApk.getClassLoader()); - - XC_LoadPackage.LoadPackageParam lpparam = new XC_LoadPackage.LoadPackageParam(XposedBridge.sLoadedPackageCallbacks); - lpparam.packageName = reportedPackageName; - lpparam.processName = (String) XposedHelpers.getObjectField(bindData, "processName"); - lpparam.classLoader = loadedApk.getClassLoader(); - lpparam.appInfo = appInfo; - lpparam.isFirstApplication = true; - XC_LoadPackage.callAll(lpparam); - - if (reportedPackageName.equals(INSTALLER_PACKAGE_NAME)) { - XposedInstallerHooker.hookXposedInstaller(lpparam.classLoader); - } - if (reportedPackageName.equals(BLACK_LIST_PACKAGE_NAME)) { - XposedBlackListHooker.hook(lpparam.classLoader); - } - if (reportedPackageName.equals(SYSTEMUI_PACKAGE_NAME)) { - SliceProviderFix.hook(); - } - } catch (Throwable t) { - Router.logE("error when hooking bindApp", t); - } finally { - backup(thiz, bindData); - } - } - - public static void backup(Object thiz, Object bindData) throws Throwable { - SandHook.callOriginByBackup(backup, thiz, bindData); - } -} \ No newline at end of file diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/_hooker/LoadedApkConstructorHooker.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/_hooker/LoadedApkConstructorHooker.java deleted file mode 100644 index 87f9c854..00000000 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/_hooker/LoadedApkConstructorHooker.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.elderdrivers.riru.edxp.sandhook._hooker; - -import android.app.ActivityThread; -import android.app.AndroidAppHelper; -import android.app.LoadedApk; -import android.content.pm.ApplicationInfo; -import android.content.res.CompatibilityInfo; -import android.util.Log; - -import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp.hooker.XposedBlackListHooker; -import com.elderdrivers.riru.edxp.sandhook.entry.Router; -import com.swift.sandhook.SandHook; -import com.swift.sandhook.annotation.HookClass; -import com.swift.sandhook.annotation.HookMethod; -import com.swift.sandhook.annotation.HookMethodBackup; -import com.swift.sandhook.annotation.SkipParamCheck; -import com.swift.sandhook.annotation.ThisObject; - -import java.lang.reflect.Method; - -import de.robv.android.xposed.XposedBridge; -import de.robv.android.xposed.XposedHelpers; -import de.robv.android.xposed.XposedInit; -import de.robv.android.xposed.callbacks.XC_LoadPackage; - -import static com.elderdrivers.riru.edxp.util.ClassLoaderUtils.replaceParentClassLoader; - -// when a package is loaded for an existing process, trigger the callbacks as well -// ed: remove resources related hooking -@HookClass(LoadedApk.class) -public class LoadedApkConstructorHooker implements KeepMembers { - public static String className = "android.app.LoadedApk"; - public static String methodName = ""; - public static String methodSig = "(Landroid/app/ActivityThread;" + - "Landroid/content/pm/ApplicationInfo;" + - "Landroid/content/res/CompatibilityInfo;" + - "Ljava/lang/ClassLoader;ZZZ)V"; - - @HookMethodBackup - @SkipParamCheck - static Method backup; - - @HookMethod - public static void hook(@ThisObject Object thiz, ActivityThread activityThread, - ApplicationInfo aInfo, CompatibilityInfo compatInfo, - ClassLoader baseLoader, boolean securityViolation, - boolean includeCode, boolean registerPackage) throws Throwable { - - if (XposedBlackListHooker.shouldDisableHooks("")) { - backup(thiz, activityThread, aInfo, compatInfo, baseLoader, securityViolation, includeCode, registerPackage); - return; - } - - Router.logD("LoadedApk# starts"); - backup(thiz, activityThread, aInfo, compatInfo, baseLoader, securityViolation, includeCode, registerPackage); - - try { - LoadedApk loadedApk = (LoadedApk) thiz; - String packageName = loadedApk.getPackageName(); - Object mAppDir = XposedHelpers.getObjectField(thiz, "mAppDir"); - Router.logD("LoadedApk# ends: " + mAppDir); - - if (XposedBlackListHooker.shouldDisableHooks(packageName)) { - return; - } - - if (packageName.equals("android")) { - Router.logD("LoadedApk# is android, skip: " + mAppDir); - return; - } - - // mIncludeCode checking should go ahead of loadedPackagesInProcess added checking - if (!XposedHelpers.getBooleanField(loadedApk, "mIncludeCode")) { - Router.logD("LoadedApk# mIncludeCode == false: " + mAppDir); - return; - } - - if (!XposedInit.loadedPackagesInProcess.add(packageName)) { - Router.logD("LoadedApk# has been loaded before, skip: " + mAppDir); - return; - } - - // OnePlus magic... - if (Log.getStackTraceString(new Throwable()). - contains("android.app.ActivityThread$ApplicationThread.schedulePreload")) { - Router.logD("LoadedApk# maybe oneplus's custom opt, skip"); - return; - } - - replaceParentClassLoader(loadedApk.getClassLoader()); - - XC_LoadPackage.LoadPackageParam lpparam = new XC_LoadPackage.LoadPackageParam(XposedBridge.sLoadedPackageCallbacks); - lpparam.packageName = packageName; - lpparam.processName = AndroidAppHelper.currentProcessName(); - lpparam.classLoader = loadedApk.getClassLoader(); - lpparam.appInfo = loadedApk.getApplicationInfo(); - lpparam.isFirstApplication = false; - XC_LoadPackage.callAll(lpparam); - } catch (Throwable t) { - Router.logE("error when hooking LoadedApk.", t); - } - } - - public static void backup(Object thiz, ActivityThread activityThread, - ApplicationInfo aInfo, CompatibilityInfo compatInfo, - ClassLoader baseLoader, boolean securityViolation, - boolean includeCode, boolean registerPackage) throws Throwable { - SandHook.callOriginByBackup(backup, thiz, activityThread, aInfo, compatInfo, baseLoader, securityViolation, includeCode, registerPackage); - } -} \ No newline at end of file diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/_hooker/OnePlusWorkAroundHooker.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/_hooker/OnePlusWorkAroundHooker.java deleted file mode 100644 index 59559d38..00000000 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/_hooker/OnePlusWorkAroundHooker.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.elderdrivers.riru.edxp.sandhook._hooker; - -import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp.Main; -import com.elderdrivers.riru.edxp.sandhook.entry.Router; -import com.swift.sandhook.SandHook; -import com.swift.sandhook.annotation.HookClass; -import com.swift.sandhook.annotation.HookMethod; -import com.swift.sandhook.annotation.HookMethodBackup; -import com.swift.sandhook.annotation.SkipParamCheck; - -import java.lang.reflect.Method; - -import dalvik.system.BaseDexClassLoader; -import de.robv.android.xposed.XposedBridge; - -/** - * On OnePlus stock roms (Android Pie), {@link dalvik.system.BaseDexClassLoader#findClass(String)} - * will open /dev/binder to communicate with PackageManagerService to check whether - * current package name inCompatConfigList, which is an OnePlus OEM feature enabled only when - * system prop "persist.sys.oem.region" set to "CN".(detail of related source code: - * https://gist.github.com/solohsu/ecc07141759958fc096ba0781fac0a5f) - * If we invoke intZygoteCallbacks in - * {@link Main#forkAndSpecializePre}, where in zygote process, - * we would get a chance to invoke findclass, leaving fd of /dev/binder open in zygote process, - * which is not allowed because /dev/binder is not in predefined whitelist here: - * http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/jni/fd_utils.cpp#35 - * So we just hook BaseDexClassLoader#inCompatConfigList to return false to prevent - * open of /dev/binder and we haven't found side effects yet. - * Other roms might share the same problems but not reported too. - */ -@HookClass(BaseDexClassLoader.class) -public class OnePlusWorkAroundHooker implements KeepMembers { - - public static String className = "dalvik.system.BaseDexClassLoader"; - public static String methodName = "inCompatConfigList"; - public static String methodSig = "(ILjava/lang/String;)Z"; - - @HookMethodBackup("inCompatConfigList") - @SkipParamCheck - static Method backup; - - @HookMethod("inCompatConfigList") - public static boolean hook(int type, String packageName) throws Throwable { - if (XposedBridge.disableHooks || Router.forkCompleted) { - return backup(type, packageName); - } - Router.logD("BaseDexClassLoader#inCompatConfigList() starts"); - return false; - } - - public static boolean backup(int type, String packageName) throws Throwable { - return (boolean) SandHook.callOriginByBackup(backup, null, type, packageName); - } -} \ No newline at end of file diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/_hooker/StartBootstrapServicesHooker.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/_hooker/StartBootstrapServicesHooker.java deleted file mode 100644 index 2ebd3b73..00000000 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/_hooker/StartBootstrapServicesHooker.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.elderdrivers.riru.edxp.sandhook._hooker; - -import android.os.Build; - -import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp.sandhook.entry.Router; -import com.swift.sandhook.SandHook; -import com.swift.sandhook.annotation.HookMethod; -import com.swift.sandhook.annotation.HookMethodBackup; -import com.swift.sandhook.annotation.HookReflectClass; -import com.swift.sandhook.annotation.SkipParamCheck; -import com.swift.sandhook.annotation.ThisObject; - -import java.lang.reflect.Method; - -import de.robv.android.xposed.XC_MethodReplacement; -import de.robv.android.xposed.XposedBridge; -import de.robv.android.xposed.XposedHelpers; -import de.robv.android.xposed.XposedInit; -import de.robv.android.xposed.callbacks.XC_LoadPackage; - -import static com.elderdrivers.riru.edxp.util.ClassLoaderUtils.replaceParentClassLoader; -import static com.elderdrivers.riru.edxp.util.Utils.logD; -import static de.robv.android.xposed.XposedHelpers.findAndHookMethod; - -@HookReflectClass("com.android.server.SystemServer") -public class StartBootstrapServicesHooker implements KeepMembers { - public static String className = "com.android.server.SystemServer"; - public static String methodName = "startBootstrapServices"; - public static String methodSig = "()V"; - - @HookMethodBackup("startBootstrapServices") - @SkipParamCheck - static Method backup; - - @HookMethod("startBootstrapServices") - public static void hook(@ThisObject Object systemServer) throws Throwable { - - if (XposedBridge.disableHooks) { - backup(systemServer); - return; - } - - logD("SystemServer#startBootstrapServices() starts"); - - try { - XposedInit.loadedPackagesInProcess.add("android"); - - replaceParentClassLoader(SystemMainHooker.systemServerCL); - - XC_LoadPackage.LoadPackageParam lpparam = new XC_LoadPackage.LoadPackageParam(XposedBridge.sLoadedPackageCallbacks); - lpparam.packageName = "android"; - lpparam.processName = "android"; // it's actually system_server, but other functions return this as well - lpparam.classLoader = SystemMainHooker.systemServerCL; - lpparam.appInfo = null; - lpparam.isFirstApplication = true; - XC_LoadPackage.callAll(lpparam); - - // Huawei - try { - findAndHookMethod("com.android.server.pm.HwPackageManagerService", SystemMainHooker.systemServerCL, "isOdexMode", XC_MethodReplacement.returnConstant(false)); - } catch (XposedHelpers.ClassNotFoundError | NoSuchMethodError ignored) { - } - - try { - String className = "com.android.server.pm." + (Build.VERSION.SDK_INT >= 23 ? "PackageDexOptimizer" : "PackageManagerService"); - findAndHookMethod(className, SystemMainHooker.systemServerCL, "dexEntryExists", String.class, XC_MethodReplacement.returnConstant(true)); - } catch (XposedHelpers.ClassNotFoundError | NoSuchMethodError ignored) { - } - } catch (Throwable t) { - Router.logE("error when hooking startBootstrapServices", t); - } finally { - backup(systemServer); - } - } - - public static void backup(Object systemServer) throws Throwable { - SandHook.callOriginByBackup(backup, systemServer); - } -} diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/config/SandHookEdxpConfig.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/config/SandHookEdxpConfig.java index 894e4432..8d52e411 100644 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/config/SandHookEdxpConfig.java +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/config/SandHookEdxpConfig.java @@ -1,6 +1,5 @@ package com.elderdrivers.riru.edxp.sandhook.config; -import com.elderdrivers.riru.edxp.Main; import com.elderdrivers.riru.edxp.config.ConfigManager; import com.elderdrivers.riru.edxp.config.EdXpConfig; import com.elderdrivers.riru.edxp.config.InstallerChooser; diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/config/SandHookProvider.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/config/SandHookProvider.java index 1d5e0e4e..1a6079eb 100644 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/config/SandHookProvider.java +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/config/SandHookProvider.java @@ -2,7 +2,6 @@ package com.elderdrivers.riru.edxp.sandhook.config; import android.util.Log; -import com.elderdrivers.riru.edxp.Main; import com.elderdrivers.riru.edxp.art.ClassLinker; import com.elderdrivers.riru.edxp.config.BaseHookProvider; import com.elderdrivers.riru.edxp.core.ResourcesHook; diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/core/HookMain.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/core/HookMain.java deleted file mode 100644 index f86b64d5..00000000 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/core/HookMain.java +++ /dev/null @@ -1,185 +0,0 @@ -package com.elderdrivers.riru.edxp.sandhook.core; - -import com.elderdrivers.riru.edxp.art.Heap; -import com.elderdrivers.riru.edxp.core.Yahfa; -import com.elderdrivers.riru.edxp.util.Utils; -import com.elderdrivers.riru.edxp.Main; -import com.elderdrivers.riru.edxp.sandhook._hooker.OnePlusWorkAroundHooker; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Set; - -import de.robv.android.xposed.XposedHelpers; - -public class HookMain { - - private static Set hookItemWhiteList = Collections.singleton(OnePlusWorkAroundHooker.class.getName()); - - public static void doHookDefault(ClassLoader patchClassLoader, ClassLoader originClassLoader, String hookInfoClassName) { - try { - Class hookInfoClass = Class.forName(hookInfoClassName, true, patchClassLoader); - String[] hookItemNames = (String[]) hookInfoClass.getField("hookItemNames").get(null); - for (String hookItemName : hookItemNames) { - doHookItemDefault(patchClassLoader, hookItemName, originClassLoader); - } - } catch (Throwable e) { - Utils.logE("error when hooking all in: " + hookInfoClassName, e); - } - } - - private static void doHookItemDefault(ClassLoader patchClassLoader, String hookItemName, ClassLoader originClassLoader) { - try { - Utils.logD("Start hooking with item " + hookItemName); - Class hookItem = Class.forName(hookItemName, true, patchClassLoader); - - String className = (String) hookItem.getField("className").get(null); - String methodName = (String) hookItem.getField("methodName").get(null); - String methodSig = (String) hookItem.getField("methodSig").get(null); - - if (className == null || className.equals("")) { - Utils.logW("No target class. Skipping..."); - return; - } - Class clazz = null; - try { - clazz = Class.forName(className, true, originClassLoader); - } catch (ClassNotFoundException cnfe) { - Utils.logE(className + " not found in " + originClassLoader); - return; - } - if (Modifier.isAbstract(clazz.getModifiers())) { - Utils.logW("Hook may fail for abstract class: " + className); - } - - Method hook = null; - Method backup = null; - for (Method method : hookItem.getDeclaredMethods()) { - if (method.getName().equals("hook") && Modifier.isStatic(method.getModifiers())) { - hook = method; - } else if (method.getName().equals("backup") && Modifier.isStatic(method.getModifiers())) { - backup = method; - } - } - if (hook == null) { - Utils.logE("Cannot find hook for " + methodName); - return; - } - findAndBackupAndHook(clazz, methodName, methodSig, hook, backup); - } catch (Throwable e) { - if (!hookItemWhiteList.contains(hookItemName)) { - Utils.logE("error when hooking " + hookItemName, e); - } - } - } - - public static void findAndHook(Class targetClass, String methodName, String methodSig, Method hook) { - hook(findMethod(targetClass, methodName, methodSig), hook); - } - - public static void findAndBackupAndHook(Class targetClass, String methodName, String methodSig, - Method hook, Method backup) { - backupAndHook(findMethod(targetClass, methodName, methodSig), hook, backup); - } - - public static void hook(Object target, Method hook) { - backupAndHook(target, hook, null); - } - - public static void backupAndHook(Object target, Method hook, Method backup) { - Utils.logD(String.format("target=%s, hook=%s, backup=%s", target, hook, backup)); - if (target == null) { - throw new IllegalArgumentException("null target method"); - } - if (hook == null) { - throw new IllegalArgumentException("null hook method"); - } - - if (!Modifier.isStatic(hook.getModifiers())) { - throw new IllegalArgumentException("Hook must be a static method: " + hook); - } - checkCompatibleMethods(target, hook, "Original", "Hook"); - if (backup != null) { - if (!Modifier.isStatic(backup.getModifiers())) { - throw new IllegalArgumentException("Backup must be a static method: " + backup); - } - // backup is just a placeholder and the constraint could be less strict - checkCompatibleMethods(target, backup, "Original", "Backup"); - } - if (backup != null) { - HookMethodResolver.resolveMethod(hook, backup); - } - // make sure GC completed before hook - Thread currentThread = Thread.currentThread(); - int lastGcType = Heap.waitForGcToComplete( - XposedHelpers.getLongField(currentThread, "nativePeer")); - if (lastGcType < 0) { - Utils.logW("waitForGcToComplete failed, using fallback"); - Runtime.getRuntime().gc(); - } - if (!Yahfa.backupAndHookNative(target, hook, backup)) { - throw new RuntimeException("Failed to hook " + target + " with " + hook); - } - } - - public static Object findMethod(Class cls, String methodName, String methodSig) { - if (cls == null) { - throw new IllegalArgumentException("null class"); - } - if (methodName == null) { - throw new IllegalArgumentException("null method name"); - } - if (methodSig == null) { - throw new IllegalArgumentException("null method signature"); - } - return Yahfa.findMethodNative(cls, methodName, methodSig); - } - - private static void checkCompatibleMethods(Object original, Method replacement, String originalName, String replacementName) { - ArrayList> originalParams; - if (original instanceof Method) { - originalParams = new ArrayList<>(Arrays.asList(((Method) original).getParameterTypes())); - } else if (original instanceof Constructor) { - originalParams = new ArrayList<>(Arrays.asList(((Constructor) original).getParameterTypes())); - } else { - throw new IllegalArgumentException("Type of target method is wrong"); - } - - ArrayList> replacementParams = new ArrayList<>(Arrays.asList(replacement.getParameterTypes())); - - if (original instanceof Method - && !Modifier.isStatic(((Method) original).getModifiers())) { - originalParams.add(0, ((Method) original).getDeclaringClass()); - } else if (original instanceof Constructor) { - originalParams.add(0, ((Constructor) original).getDeclaringClass()); - } - - - if (!Modifier.isStatic(replacement.getModifiers())) { - replacementParams.add(0, replacement.getDeclaringClass()); - } - - if (original instanceof Method - && !replacement.getReturnType().isAssignableFrom(((Method) original).getReturnType())) { - throw new IllegalArgumentException("Incompatible return types. " + originalName + ": " + ((Method) original).getReturnType() + ", " + replacementName + ": " + replacement.getReturnType()); - } else if (original instanceof Constructor) { - if (replacement.getReturnType().equals(Void.class)) { - throw new IllegalArgumentException("Incompatible return types. " + "" + ": " + "V" + ", " + replacementName + ": " + replacement.getReturnType()); - } - } - - if (originalParams.size() != replacementParams.size()) { - throw new IllegalArgumentException("Number of arguments don't match. " + originalName + ": " + originalParams.size() + ", " + replacementName + ": " + replacementParams.size()); - } - - for (int i = 0; i < originalParams.size(); i++) { - if (!replacementParams.get(i).isAssignableFrom(originalParams.get(i))) { - throw new IllegalArgumentException("Incompatible argument #" + i + ": " + originalName + ": " + originalParams.get(i) + ", " + replacementName + ": " + replacementParams.get(i)); - } - } - } -} diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/core/HookMethodResolver.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/core/HookMethodResolver.java deleted file mode 100644 index 7e02fc1c..00000000 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/core/HookMethodResolver.java +++ /dev/null @@ -1,156 +0,0 @@ -package com.elderdrivers.riru.edxp.sandhook.core; - -import android.os.Build; - -import com.elderdrivers.riru.edxp.core.Yahfa; -import com.elderdrivers.riru.edxp.util.Utils; -import com.elderdrivers.riru.edxp.Main; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; - -/** - * create by Swift Gan on 14/01/2019 - * To ensure method in resolved cache - */ - -public class HookMethodResolver { - - public static Class artMethodClass; - - public static Field resolvedMethodsField; - public static Field dexCacheField; - public static Field dexMethodIndexField; - public static Field artMethodField; - - public static boolean canResolvedInJava = false; - public static boolean isArtMethod = false; - - public static long resolvedMethodsAddress = 0; - public static int dexMethodIndex = 0; - - public static Method testMethod; - public static Object testArtMethod; - - public static void init() { - checkSupport(); - } - - private static void checkSupport() { - try { - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - isArtMethod = false; - canResolvedInJava = false; - return; - } - - testMethod = HookMethodResolver.class.getDeclaredMethod("init"); - artMethodField = getField(Method.class, "artMethod"); - - testArtMethod = artMethodField.get(testMethod); - - if (hasJavaArtMethod() && testArtMethod.getClass() == artMethodClass) { - checkSupportForArtMethod(); - isArtMethod = true; - } else if (testArtMethod instanceof Long) { - checkSupportForArtMethodId(); - isArtMethod = false; - } else { - canResolvedInJava = false; - } - - } catch (Throwable throwable) { - Utils.logE("error when checkSupport", throwable); - } - } - - // may 5.0 - private static void checkSupportForArtMethod() throws Exception { - dexMethodIndexField = getField(artMethodClass, "dexMethodIndex"); - dexCacheField = getField(Class.class, "dexCache"); - Object dexCache = dexCacheField.get(testMethod.getDeclaringClass()); - resolvedMethodsField = getField(dexCache.getClass(), "resolvedMethods"); - if (resolvedMethodsField.get(dexCache) instanceof Object[]) { - canResolvedInJava = true; - } - } - - // may 6.0 - private static void checkSupportForArtMethodId() throws Exception { - dexMethodIndexField = getField(Method.class, "dexMethodIndex"); - dexMethodIndex = (int) dexMethodIndexField.get(testMethod); - dexCacheField = getField(Class.class, "dexCache"); - Object dexCache = dexCacheField.get(testMethod.getDeclaringClass()); - resolvedMethodsField = getField(dexCache.getClass(), "resolvedMethods"); - Object resolvedMethods = resolvedMethodsField.get(dexCache); - if (resolvedMethods instanceof Long) { - canResolvedInJava = false; - resolvedMethodsAddress = (long) resolvedMethods; - } else if (resolvedMethods instanceof long[]) { - canResolvedInJava = true; - } - } - - public static void resolveMethod(Method hook, Method backup) { - if (canResolvedInJava && artMethodField != null) { - // in java - try { - resolveInJava(hook, backup); - } catch (Exception e) { - // in native - resolveInNative(hook, backup); - } - } else { - // in native - resolveInNative(hook, backup); - } - } - - private static void resolveInJava(Method hook, Method backup) throws Exception { - Object dexCache = dexCacheField.get(hook.getDeclaringClass()); - if (isArtMethod) { - Object artMethod = artMethodField.get(backup); - int dexMethodIndex = (int) dexMethodIndexField.get(artMethod); - Object resolvedMethods = resolvedMethodsField.get(dexCache); - ((Object[])resolvedMethods)[dexMethodIndex] = artMethod; - } else { - int dexMethodIndex = (int) dexMethodIndexField.get(backup); - Object resolvedMethods = resolvedMethodsField.get(dexCache); - long artMethod = (long) artMethodField.get(backup); - ((long[])resolvedMethods)[dexMethodIndex] = artMethod; - } - } - - private static void resolveInNative(Method hook, Method backup) { - Yahfa.ensureMethodCached(hook, backup); - } - - public static Field getField(Class topClass, String fieldName) throws NoSuchFieldException { - while (topClass != null && topClass != Object.class) { - try { - Field field = topClass.getDeclaredField(fieldName); - field.setAccessible(true); - return field; - } catch (Exception e) { - } - topClass = topClass.getSuperclass(); - } - throw new NoSuchFieldException(fieldName); - } - - public static boolean hasJavaArtMethod() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - return false; - } - if (artMethodClass != null) - return true; - try { - artMethodClass = Class.forName("java.lang.reflect.ArtMethod"); - return true; - } catch (ClassNotFoundException e) { - return false; - } - } - -} \ No newline at end of file diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/core/SandHookEdxpImpl.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/core/SandHookEdxpImpl.java new file mode 100644 index 00000000..4ec3f91a --- /dev/null +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/core/SandHookEdxpImpl.java @@ -0,0 +1,44 @@ +package com.elderdrivers.riru.edxp.sandhook.core; + +import android.os.Build; + +import com.elderdrivers.riru.edxp.config.ConfigManager; +import com.elderdrivers.riru.edxp.config.InstallerChooser; +import com.elderdrivers.riru.edxp.core.BaseEdxpImpl; +import com.elderdrivers.riru.edxp.core.EdxpImpl; +import com.elderdrivers.riru.edxp.core.Main; +import com.elderdrivers.riru.edxp.core.Yahfa; +import com.elderdrivers.riru.edxp.core.yahfa.HookMethodResolver; +import com.swift.sandhook.xposedcompat.methodgen.SandHookXposedBridge; + +public class SandHookEdxpImpl extends BaseEdxpImpl { + + static { + final EdxpImpl edxpImpl = new SandHookEdxpImpl(); + if (Main.setEdxpImpl(edxpImpl)) { + edxpImpl.init(); + } + } + + @Override + protected com.elderdrivers.riru.edxp.proxy.Router createRouter() { + return new SandHookRouter(); + } + + @Variant + @Override + public int getVariant() { + return SANDHOOK; + } + + @Override + public void init() { + Yahfa.init(Build.VERSION.SDK_INT); + HookMethodResolver.init(); + getRouter().injectConfig(); + InstallerChooser.setInstallerPackageName(ConfigManager.getInstallerPackageName()); + SandHookXposedBridge.init(); + + setInitialized(); + } +} diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/core/SandHookRouter.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/core/SandHookRouter.java new file mode 100644 index 00000000..ae0ac965 --- /dev/null +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/core/SandHookRouter.java @@ -0,0 +1,64 @@ +package com.elderdrivers.riru.edxp.sandhook.core; + +import com.elderdrivers.riru.edxp.config.EdXpConfigGlobal; +import com.elderdrivers.riru.edxp.proxy.BaseRouter; +import com.elderdrivers.riru.edxp.sandhook.hooker.SystemMainHooker; +import com.elderdrivers.riru.edxp.sandhook.config.SandHookEdxpConfig; +import com.elderdrivers.riru.edxp.sandhook.config.SandHookProvider; +import com.elderdrivers.riru.edxp.sandhook.dexmaker.DynamicBridge; +import com.elderdrivers.riru.edxp.sandhook.entry.AppBootstrapHookInfo; +import com.elderdrivers.riru.edxp.sandhook.entry.SysBootstrapHookInfo; +import com.elderdrivers.riru.edxp.sandhook.entry.SysInnerHookInfo; +import com.elderdrivers.riru.edxp.sandhook.entry.WorkAroundHookInfo; +import com.elderdrivers.riru.edxp.util.Utils; +import com.swift.sandhook.xposedcompat.XposedCompat; + +import de.robv.android.xposed.XposedBridge; + +public class SandHookRouter extends BaseRouter { + + private static boolean useSandHook = false; + + public void startBootstrapHook(boolean isSystem) { + if (useSandHook) { + Utils.logD("startBootstrapHook starts: isSystem = " + isSystem); + ClassLoader classLoader = XposedBridge.BOOTCLASSLOADER; + if (isSystem) { + XposedCompat.addHookers(classLoader, SysBootstrapHookInfo.hookItems); + } else { + XposedCompat.addHookers(classLoader, AppBootstrapHookInfo.hookItems); + } + } else { + super.startBootstrapHook(isSystem); + } + } + + public void startSystemServerHook() { + if (useSandHook) { + XposedCompat.addHookers(SystemMainHooker.systemServerCL, SysInnerHookInfo.hookItems); + } else { + super.startSystemServerHook(); + } + } + + public void startWorkAroundHook() { + if (useSandHook) { + XposedCompat.addHookers(XposedBridge.BOOTCLASSLOADER, WorkAroundHookInfo.hookItems); + } else { + super.startWorkAroundHook(); + } + } + + public void onEnterChildProcess() { + DynamicBridge.onForkPost(); + //enable compile in child process + //SandHook.enableCompiler(!XposedInit.startsSystemServer); + } + + public void injectConfig() { + EdXpConfigGlobal.sConfig = new SandHookEdxpConfig(); + EdXpConfigGlobal.sHookProvider = new SandHookProvider(); + XposedBridge.log("using HookProvider: " + EdXpConfigGlobal.sHookProvider.getClass().getName()); + } + +} diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/dexmaker/DexMakerUtils.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/dexmaker/DexMakerUtils.java index 5ad71082..1069b545 100644 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/dexmaker/DexMakerUtils.java +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/dexmaker/DexMakerUtils.java @@ -5,8 +5,7 @@ import android.os.Build; import android.text.TextUtils; import com.elderdrivers.riru.edxp.config.ConfigManager; -import com.elderdrivers.riru.edxp.Main; -import com.elderdrivers.riru.edxp.sandhook.core.HookMain; +import com.elderdrivers.riru.edxp.core.yahfa.HookMain; import java.lang.reflect.Member; import java.security.MessageDigest; @@ -27,8 +26,8 @@ public class DexMakerUtils { } String packageName = AndroidAppHelper.currentPackageName(); if (TextUtils.isEmpty(packageName)) { //default to true - DexLog.w("packageName is empty, processName=" + Main.appProcessName - + ", appDataDir=" + Main.appDataDir); + DexLog.w("packageName is empty, processName=" + ConfigManager.appProcessName + + ", appDataDir=" + ConfigManager.appDataDir); return true; } return !ConfigManager.shouldUseCompatMode(packageName); diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/dexmaker/DynamicBridge.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/dexmaker/DynamicBridge.java index 2437185f..207c1e41 100644 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/dexmaker/DynamicBridge.java +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/dexmaker/DynamicBridge.java @@ -1,6 +1,6 @@ package com.elderdrivers.riru.edxp.sandhook.dexmaker; -import com.elderdrivers.riru.edxp.Main; +import com.elderdrivers.riru.edxp.config.ConfigManager; import java.io.File; import java.lang.reflect.Constructor; @@ -8,16 +8,15 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.util.HashMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; import de.robv.android.xposed.XposedBridge; +import static com.elderdrivers.riru.edxp.sandhook.dexmaker.DexMakerUtils.shouldUseInMemoryHook; import static com.elderdrivers.riru.edxp.util.FileUtils.getDataPathPrefix; import static com.elderdrivers.riru.edxp.util.FileUtils.getPackageName; import static com.elderdrivers.riru.edxp.util.ProcessUtils.getCurrentProcessName; -import static com.elderdrivers.riru.edxp.sandhook.dexmaker.DexMakerUtils.shouldUseInMemoryHook; public final class DynamicBridge { @@ -78,9 +77,9 @@ public final class DynamicBridge { try { // we always choose to use device encrypted storage data on android N and later // in case some app is installing hooks before phone is unlocked - String fixedAppDataDir = getDataPathPrefix() + getPackageName(Main.appDataDir) + "/"; + String fixedAppDataDir = getDataPathPrefix() + getPackageName(ConfigManager.appDataDir) + "/"; dexDir = new File(fixedAppDataDir, "/cache/edhookers/" - + getCurrentProcessName(Main.appProcessName).replace(":", "_") + "/"); + + getCurrentProcessName(ConfigManager.appProcessName).replace(":", "_") + "/"); dexDir.mkdirs(); } catch (Throwable throwable) { DexLog.e("error when init dex path", throwable); diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/dexmaker/HookerDexMaker.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/dexmaker/HookerDexMaker.java index dbff519a..d89048fc 100644 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/dexmaker/HookerDexMaker.java +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/dexmaker/HookerDexMaker.java @@ -4,9 +4,8 @@ import android.annotation.TargetApi; import android.os.Build; import android.text.TextUtils; -import com.elderdrivers.riru.edxp.Main; import com.elderdrivers.riru.edxp.core.Yahfa; -import com.elderdrivers.riru.edxp.sandhook.core.HookMain; +import com.elderdrivers.riru.edxp.core.yahfa.HookMain; import java.io.File; import java.lang.reflect.Constructor; diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/bootstrap/AppBootstrapHookInfo.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/AppBootstrapHookInfo.java similarity index 63% rename from edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/bootstrap/AppBootstrapHookInfo.java rename to edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/AppBootstrapHookInfo.java index 34856bf2..35d215ca 100644 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/bootstrap/AppBootstrapHookInfo.java +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/AppBootstrapHookInfo.java @@ -1,9 +1,9 @@ -package com.elderdrivers.riru.edxp.sandhook.entry.bootstrap; +package com.elderdrivers.riru.edxp.sandhook.entry; import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp.sandhook._hooker.HandleBindAppHooker; -import com.elderdrivers.riru.edxp.sandhook._hooker.LoadedApkConstructorHooker; -import com.elderdrivers.riru.edxp.sandhook._hooker.OnePlusWorkAroundHooker; +import com.elderdrivers.riru.edxp.sandhook.hooker.HandleBindAppHooker; +import com.elderdrivers.riru.edxp.sandhook.hooker.LoadedApkConstructorHooker; +import com.elderdrivers.riru.edxp.sandhook.hooker.OnePlusWorkAroundHooker; public class AppBootstrapHookInfo implements KeepMembers { public static String[] hookItemNames = { diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/Router.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/Router.java deleted file mode 100644 index d3cb802b..00000000 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/Router.java +++ /dev/null @@ -1,159 +0,0 @@ -package com.elderdrivers.riru.edxp.sandhook.entry; - -import android.app.AndroidAppHelper; -import android.text.TextUtils; - -import com.elderdrivers.riru.edxp.config.EdXpConfigGlobal; -import com.elderdrivers.riru.edxp.sandhook.config.SandHookEdxpConfig; -import com.elderdrivers.riru.edxp.sandhook.config.SandHookProvider; -import com.elderdrivers.riru.edxp.sandhook.core.HookMain; -import com.elderdrivers.riru.edxp.sandhook.dexmaker.DynamicBridge; -import com.elderdrivers.riru.edxp.sandhook.entry.bootstrap.AppBootstrapHookInfo; -import com.elderdrivers.riru.edxp.sandhook.entry.bootstrap.SysBootstrapHookInfo; -import com.elderdrivers.riru.edxp.sandhook.entry.bootstrap.SysInnerHookInfo; -import com.elderdrivers.riru.edxp.sandhook.entry.bootstrap.WorkAroundHookInfo; -import com.elderdrivers.riru.edxp.sandhook._hooker.SystemMainHooker; -import com.elderdrivers.riru.edxp.util.Utils; -import com.swift.sandhook.xposedcompat.XposedCompat; - -import java.util.concurrent.atomic.AtomicBoolean; - -import de.robv.android.xposed.XposedBridge; -import de.robv.android.xposed.XposedInit; - -import static de.robv.android.xposed.XposedInit.startsSystemServer; - -public class Router { - - public volatile static boolean forkCompleted = false; - - private static volatile AtomicBoolean bootstrapHooked = new AtomicBoolean(false); - - static boolean useSandHook = false; - - public static void initResourcesHook() { - startWorkAroundHook(); // for OnePlus devices - XposedBridge.initXResources(); - } - - public static void prepare(boolean isSystem) { - // this flag is needed when loadModules - startsSystemServer = isSystem; - } - - public static void checkHookState(String appDataDir) { - // determine whether allow xposed or not -// XposedBridge.disableHooks = ConfigManager.shouldHook(parsePackageName(appDataDir)); - } - - private static String parsePackageName(String appDataDir) { - if (TextUtils.isEmpty(appDataDir)) { - return ""; - } - int lastIndex = appDataDir.lastIndexOf("/"); - if (lastIndex < 1) { - return ""; - } - return appDataDir.substring(lastIndex + 1); - } - - public static void installBootstrapHooks(boolean isSystem) { - // Initialize the Xposed framework - try { - if (!bootstrapHooked.compareAndSet(false, true)) { - return; - } - Router.startBootstrapHook(isSystem); - XposedInit.initForZygote(isSystem); - //SandHookConfig.compiler = !isSystem; - } catch (Throwable t) { - Utils.logE("error during Xposed initialization", t); - XposedBridge.disableHooks = true; - } - } - - public static void loadModulesSafely(boolean isInZygote) { - try { - // FIXME some coredomain app can't reading modules.list - XposedInit.loadModules(isInZygote); - } catch (Exception exception) { - Utils.logE("error loading module list", exception); - } - } - - public static void startBootstrapHook(boolean isSystem) { - Utils.logD("startBootstrapHook starts: isSystem = " + isSystem); - ClassLoader classLoader = XposedBridge.BOOTCLASSLOADER; - if (isSystem) { - if (useSandHook) { - XposedCompat.addHookers(classLoader, SysBootstrapHookInfo.hookItems); - } else { - HookMain.doHookDefault( - Router.class.getClassLoader(), - classLoader, - SysBootstrapHookInfo.class.getName()); - } - } else { - if (useSandHook) { - XposedCompat.addHookers(classLoader, AppBootstrapHookInfo.hookItems); - } else { - HookMain.doHookDefault( - Router.class.getClassLoader(), - classLoader, - AppBootstrapHookInfo.class.getName()); - } - } - } - - public static void startSystemServerHook() { - if (useSandHook) { - XposedCompat.addHookers(SystemMainHooker.systemServerCL, SysInnerHookInfo.hookItems); - } else { - HookMain.doHookDefault( - Router.class.getClassLoader(), - SystemMainHooker.systemServerCL, - SysInnerHookInfo.class.getName()); - } - } - - public static void startWorkAroundHook() { - if (useSandHook) { - XposedCompat.addHookers(XposedBridge.BOOTCLASSLOADER, WorkAroundHookInfo.hookItems); - } else { - HookMain.doHookDefault( - Router.class.getClassLoader(), - XposedBridge.BOOTCLASSLOADER, - WorkAroundHookInfo.class.getName()); - } - } - - public static void onForkStart() { - forkCompleted = false; - } - - public static void onForkFinish() { - forkCompleted = true; - } - - public static void onEnterChildProcess() { - DynamicBridge.onForkPost(); - //enable compile in child process - //SandHook.enableCompiler(!XposedInit.startsSystemServer); - } - - public static void logD(String prefix) { - Utils.logD(String.format("%s: pkg=%s, prc=%s", prefix, AndroidAppHelper.currentPackageName(), - AndroidAppHelper.currentProcessName())); - } - - public static void logE(String prefix, Throwable throwable) { - Utils.logE(String.format("%s: pkg=%s, prc=%s", prefix, AndroidAppHelper.currentPackageName(), - AndroidAppHelper.currentProcessName()), throwable); - } - - public static void injectConfig() { - EdXpConfigGlobal.sConfig = new SandHookEdxpConfig(); - EdXpConfigGlobal.sHookProvider = new SandHookProvider(); - XposedBridge.log("using HookProvider: " + EdXpConfigGlobal.sHookProvider.getClass().getName()); - } -} diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/bootstrap/SysBootstrapHookInfo.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/SysBootstrapHookInfo.java similarity index 61% rename from edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/bootstrap/SysBootstrapHookInfo.java rename to edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/SysBootstrapHookInfo.java index c1abc6e5..434a9f34 100644 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/bootstrap/SysBootstrapHookInfo.java +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/SysBootstrapHookInfo.java @@ -1,10 +1,10 @@ -package com.elderdrivers.riru.edxp.sandhook.entry.bootstrap; +package com.elderdrivers.riru.edxp.sandhook.entry; import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp.sandhook._hooker.HandleBindAppHooker; -import com.elderdrivers.riru.edxp.sandhook._hooker.LoadedApkConstructorHooker; -import com.elderdrivers.riru.edxp.sandhook._hooker.OnePlusWorkAroundHooker; -import com.elderdrivers.riru.edxp.sandhook._hooker.SystemMainHooker; +import com.elderdrivers.riru.edxp.sandhook.hooker.HandleBindAppHooker; +import com.elderdrivers.riru.edxp.sandhook.hooker.LoadedApkConstructorHooker; +import com.elderdrivers.riru.edxp.sandhook.hooker.OnePlusWorkAroundHooker; +import com.elderdrivers.riru.edxp.sandhook.hooker.SystemMainHooker; public class SysBootstrapHookInfo implements KeepMembers { public static String[] hookItemNames = { diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/bootstrap/SysInnerHookInfo.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/SysInnerHookInfo.java similarity index 68% rename from edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/bootstrap/SysInnerHookInfo.java rename to edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/SysInnerHookInfo.java index e1178361..4c912089 100644 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/bootstrap/SysInnerHookInfo.java +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/SysInnerHookInfo.java @@ -1,7 +1,7 @@ -package com.elderdrivers.riru.edxp.sandhook.entry.bootstrap; +package com.elderdrivers.riru.edxp.sandhook.entry; import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp.sandhook._hooker.StartBootstrapServicesHooker; +import com.elderdrivers.riru.edxp.sandhook.hooker.StartBootstrapServicesHooker; public class SysInnerHookInfo implements KeepMembers { public static String[] hookItemNames = { diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/bootstrap/WorkAroundHookInfo.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/WorkAroundHookInfo.java similarity index 68% rename from edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/bootstrap/WorkAroundHookInfo.java rename to edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/WorkAroundHookInfo.java index 8a70e6f6..cb7031bb 100644 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/bootstrap/WorkAroundHookInfo.java +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/entry/WorkAroundHookInfo.java @@ -1,7 +1,7 @@ -package com.elderdrivers.riru.edxp.sandhook.entry.bootstrap; +package com.elderdrivers.riru.edxp.sandhook.entry; import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp.sandhook._hooker.OnePlusWorkAroundHooker; +import com.elderdrivers.riru.edxp.sandhook.hooker.OnePlusWorkAroundHooker; public class WorkAroundHookInfo implements KeepMembers { public static String[] hookItemNames = { diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/HandleBindAppHooker.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/HandleBindAppHooker.java new file mode 100644 index 00000000..60cb6fd2 --- /dev/null +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/HandleBindAppHooker.java @@ -0,0 +1,46 @@ +package com.elderdrivers.riru.edxp.sandhook.hooker; + +import android.app.ActivityThread; + +import com.elderdrivers.riru.common.KeepMembers; +import com.elderdrivers.riru.edxp._hooker.impl.HandleBindApp; +import com.swift.sandhook.SandHook; +import com.swift.sandhook.annotation.HookClass; +import com.swift.sandhook.annotation.HookMethod; +import com.swift.sandhook.annotation.HookMethodBackup; +import com.swift.sandhook.annotation.Param; +import com.swift.sandhook.annotation.SkipParamCheck; +import com.swift.sandhook.annotation.ThisObject; + +import java.lang.reflect.Method; + +import de.robv.android.xposed.XC_MethodHook; + +@HookClass(ActivityThread.class) +public class HandleBindAppHooker implements KeepMembers { + + public static String className = "android.app.ActivityThread"; + public static String methodName = "handleBindApplication"; + public static String methodSig = "(Landroid/app/ActivityThread$AppBindData;)V"; + + @HookMethodBackup("handleBindApplication") + @SkipParamCheck + static Method backup; + + @HookMethod("handleBindApplication") + public static void hook(@ThisObject ActivityThread thiz, @Param("android.app.ActivityThread$AppBindData") Object bindData) throws Throwable { + final XC_MethodHook methodHook = new HandleBindApp(); + final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam(); + param.thisObject = thiz; + param.args = new Object[]{bindData}; + methodHook.callBeforeHookedMethod(param); + if (!param.returnEarly) { + backup(thiz, bindData); + } + methodHook.callAfterHookedMethod(param); + } + + public static void backup(Object thiz, Object bindData) throws Throwable { + SandHook.callOriginByBackup(backup, thiz, bindData); + } +} \ No newline at end of file diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/LoadedApkConstructorHooker.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/LoadedApkConstructorHooker.java new file mode 100644 index 00000000..29c6d0e1 --- /dev/null +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/LoadedApkConstructorHooker.java @@ -0,0 +1,58 @@ +package com.elderdrivers.riru.edxp.sandhook.hooker; + +import android.app.ActivityThread; +import android.app.LoadedApk; +import android.content.pm.ApplicationInfo; +import android.content.res.CompatibilityInfo; + +import com.elderdrivers.riru.common.KeepMembers; +import com.elderdrivers.riru.edxp._hooker.impl.LoadedApkCstr; +import com.swift.sandhook.SandHook; +import com.swift.sandhook.annotation.HookClass; +import com.swift.sandhook.annotation.HookMethod; +import com.swift.sandhook.annotation.HookMethodBackup; +import com.swift.sandhook.annotation.SkipParamCheck; +import com.swift.sandhook.annotation.ThisObject; + +import java.lang.reflect.Method; + +import de.robv.android.xposed.XC_MethodHook; + +@HookClass(LoadedApk.class) +public class LoadedApkConstructorHooker implements KeepMembers { + public static String className = "android.app.LoadedApk"; + public static String methodName = ""; + public static String methodSig = "(Landroid/app/ActivityThread;" + + "Landroid/content/pm/ApplicationInfo;" + + "Landroid/content/res/CompatibilityInfo;" + + "Ljava/lang/ClassLoader;ZZZ)V"; + + @HookMethodBackup + @SkipParamCheck + static Method backup; + + @HookMethod + public static void hook(@ThisObject Object thiz, ActivityThread activityThread, + ApplicationInfo aInfo, CompatibilityInfo compatInfo, + ClassLoader baseLoader, boolean securityViolation, + boolean includeCode, boolean registerPackage) throws Throwable { + final XC_MethodHook methodHook = new LoadedApkCstr(); + final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam(); + param.thisObject = thiz; + param.args = new Object[]{activityThread, aInfo, compatInfo, baseLoader, securityViolation, + includeCode, registerPackage}; + methodHook.callBeforeHookedMethod(param); + if (!param.returnEarly) { + backup(thiz, activityThread, aInfo, compatInfo, baseLoader, securityViolation, + includeCode, registerPackage); + } + methodHook.callAfterHookedMethod(param); + } + + public static void backup(Object thiz, ActivityThread activityThread, + ApplicationInfo aInfo, CompatibilityInfo compatInfo, + ClassLoader baseLoader, boolean securityViolation, + boolean includeCode, boolean registerPackage) throws Throwable { + SandHook.callOriginByBackup(backup, thiz, activityThread, aInfo, compatInfo, baseLoader, securityViolation, includeCode, registerPackage); + } +} \ No newline at end of file diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/OnePlusWorkAroundHooker.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/OnePlusWorkAroundHooker.java new file mode 100644 index 00000000..48b0ba61 --- /dev/null +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/OnePlusWorkAroundHooker.java @@ -0,0 +1,49 @@ +package com.elderdrivers.riru.edxp.sandhook.hooker; + +import com.elderdrivers.riru.common.KeepMembers; +import com.elderdrivers.riru.edxp._hooker.impl.OneplusWorkaround; +import com.elderdrivers.riru.edxp.core.yahfa.HookMain; +import com.swift.sandhook.SandHook; +import com.swift.sandhook.annotation.HookClass; +import com.swift.sandhook.annotation.HookMethod; +import com.swift.sandhook.annotation.HookMethodBackup; +import com.swift.sandhook.annotation.SkipParamCheck; + +import java.lang.reflect.Method; + +import dalvik.system.BaseDexClassLoader; +import de.robv.android.xposed.XC_MethodHook; + +@HookClass(BaseDexClassLoader.class) +public class OnePlusWorkAroundHooker implements KeepMembers { + + static { + HookMain.addHookItemWhiteList(OnePlusWorkAroundHooker.class.getName()); + } + + public static String className = "dalvik.system.BaseDexClassLoader"; + public static String methodName = "inCompatConfigList"; + public static String methodSig = "(ILjava/lang/String;)Z"; + + @HookMethodBackup("inCompatConfigList") + @SkipParamCheck + static Method backup; + + @HookMethod("inCompatConfigList") + public static boolean hook(int type, String packageName) throws Throwable { + final XC_MethodHook methodHook = new OneplusWorkaround(); + final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam(); + param.thisObject = null; + param.args = new Object[]{type, packageName}; + methodHook.callBeforeHookedMethod(param); + if (!param.returnEarly) { + param.setResult(backup(type, packageName)); + } + methodHook.callAfterHookedMethod(param); + return (boolean) param.getResult(); + } + + public static boolean backup(int type, String packageName) throws Throwable { + return (boolean) SandHook.callOriginByBackup(backup, null, type, packageName); + } +} \ No newline at end of file diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/StartBootstrapServicesHooker.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/StartBootstrapServicesHooker.java new file mode 100644 index 00000000..d432d32e --- /dev/null +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/StartBootstrapServicesHooker.java @@ -0,0 +1,42 @@ +package com.elderdrivers.riru.edxp.sandhook.hooker; + +import com.elderdrivers.riru.common.KeepMembers; +import com.elderdrivers.riru.edxp._hooker.impl.StartBootstrapServices; +import com.swift.sandhook.SandHook; +import com.swift.sandhook.annotation.HookMethod; +import com.swift.sandhook.annotation.HookMethodBackup; +import com.swift.sandhook.annotation.HookReflectClass; +import com.swift.sandhook.annotation.SkipParamCheck; +import com.swift.sandhook.annotation.ThisObject; + +import java.lang.reflect.Method; + +import de.robv.android.xposed.XC_MethodHook; + +@HookReflectClass("com.android.server.SystemServer") +public class StartBootstrapServicesHooker implements KeepMembers { + public static String className = "com.android.server.SystemServer"; + public static String methodName = "startBootstrapServices"; + public static String methodSig = "()V"; + + @HookMethodBackup("startBootstrapServices") + @SkipParamCheck + static Method backup; + + @HookMethod("startBootstrapServices") + public static void hook(@ThisObject Object systemServer) throws Throwable { + final XC_MethodHook methodHook = new StartBootstrapServices(); + final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam(); + param.thisObject = systemServer; + param.args = new Object[]{}; + methodHook.callBeforeHookedMethod(param); + if (!param.returnEarly) { + backup(systemServer); + } + methodHook.callAfterHookedMethod(param); + } + + public static void backup(Object systemServer) throws Throwable { + SandHook.callOriginByBackup(backup, systemServer); + } +} diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/_hooker/SystemMainHooker.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/SystemMainHooker.java similarity index 54% rename from edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/_hooker/SystemMainHooker.java rename to edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/SystemMainHooker.java index d7fa2329..e0272c2b 100644 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/_hooker/SystemMainHooker.java +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/hooker/SystemMainHooker.java @@ -1,10 +1,9 @@ -package com.elderdrivers.riru.edxp.sandhook._hooker; +package com.elderdrivers.riru.edxp.sandhook.hooker; import android.app.ActivityThread; import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp.deopt.PrebuiltMethodsDeopter; -import com.elderdrivers.riru.edxp.sandhook.entry.Router; +import com.elderdrivers.riru.edxp._hooker.impl.OneplusWorkaround; import com.swift.sandhook.SandHook; import com.swift.sandhook.annotation.HookClass; import com.swift.sandhook.annotation.HookMethod; @@ -12,7 +11,7 @@ import com.swift.sandhook.annotation.HookMethodBackup; import java.lang.reflect.Method; -import de.robv.android.xposed.XposedBridge; +import de.robv.android.xposed.XC_MethodHook; // system_server initialization @@ -31,21 +30,16 @@ public class SystemMainHooker implements KeepMembers { @HookMethod("systemMain") public static ActivityThread hook() throws Throwable { - if (XposedBridge.disableHooks) { - return backup(); + final XC_MethodHook methodHook = new OneplusWorkaround(); + final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam(); + param.thisObject = null; + param.args = new Object[]{}; + methodHook.callBeforeHookedMethod(param); + if (!param.returnEarly) { + param.setResult(backup()); } - Router.logD("ActivityThread#systemMain() starts"); - ActivityThread activityThread = backup(); - try { - // get system_server classLoader - systemServerCL = Thread.currentThread().getContextClassLoader(); - // deopt methods in SYSTEMSERVERCLASSPATH - PrebuiltMethodsDeopter.deoptSystemServerMethods(systemServerCL); - Router.startSystemServerHook(); - } catch (Throwable t) { - Router.logE("error when hooking systemMain", t); - } - return activityThread; + methodHook.callAfterHookedMethod(param); + return (ActivityThread) param.getResult(); } public static ActivityThread backup() throws Throwable { diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/proxy/BlackWhiteListProxy.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/proxy/BlackWhiteListProxy.java deleted file mode 100644 index c251a21e..00000000 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/proxy/BlackWhiteListProxy.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.elderdrivers.riru.edxp.sandhook.proxy; - -import android.text.TextUtils; - -import com.elderdrivers.riru.edxp.Main; -import com.elderdrivers.riru.edxp.config.ConfigManager; -import com.elderdrivers.riru.edxp.deopt.PrebuiltMethodsDeopter; -import com.elderdrivers.riru.edxp.framework.Zygote; -import com.elderdrivers.riru.edxp.sandhook.entry.Router; -import com.elderdrivers.riru.edxp.util.ProcessUtils; -import com.elderdrivers.riru.edxp.util.Utils; - -import de.robv.android.xposed.XposedBridge; - -import static com.elderdrivers.riru.edxp.util.FileUtils.getDataPathPrefix; - -/** - * 1. Non dynamic mode - * - system_server is whitelisted - * * for all child processes of main zygote - * What've been done in main zygote pre-forking system_server - * 1) non dynamic flag set (no need to reset) - * 2) boot image methods deopted (no need to redo) - * 3) startSystemServer flag set to true (need to reset) - * 4) workaround hooks installed (need to redo) - * 5) module list loaded and initZygote called (no need to redo) - * 6) close all fds (no need to redo because of 5)) - * * for all child processes of secondary zygote - * 1) do the same things pre-forking first child process - * - system_server is blacklisted: - * * for all child processes of both main zygote and secondary zygote - * 1) do the same things pre-forking first child process - * 2. Dynamic mode: - * to be continued - */ -public class BlackWhiteListProxy { - - public static void forkAndSpecializePre(int uid, int gid, int[] gids, int debugFlags, - int[][] rlimits, int mountExternal, String seInfo, - String niceName, int[] fdsToClose, int[] fdsToIgnore, - boolean startChildZygote, String instructionSet, - String appDataDir) { - final boolean isDynamicModulesMode = ConfigManager.isDynamicModulesEnabled(); - if (isDynamicModulesMode) { - // should never happen - return; - } - // only enter here when isDynamicModulesMode is off - onForkPreForNonDynamicMode(false); - } - - public static void forkAndSpecializePost(int pid, String appDataDir, String niceName) { - onForkPostCommon(false, appDataDir, niceName); - } - - public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, - int[][] rlimits, long permittedCapabilities, - long effectiveCapabilities) { - final boolean isDynamicModulesMode = ConfigManager.isDynamicModulesEnabled(); - if (isDynamicModulesMode) { - // should never happen - return; - } - // only enter here when isDynamicModulesMode is off - onForkPreForNonDynamicMode(true); - } - - public static void forkSystemServerPost(int pid) { - onForkPostCommon(true, getDataPathPrefix() + "android", "system_server"); - } - - /** - * Some details are different between main zygote and secondary zygote. - */ - private static void onForkPreForNonDynamicMode(boolean isSystemServer) { - Router.onForkStart(); - Router.initResourcesHook(); - // set startsSystemServer flag used when loadModules - Router.prepare(isSystemServer); - // deoptBootMethods once for all child processes of zygote - PrebuiltMethodsDeopter.deoptBootMethods(); - // we never install bootstrap hooks here in black/white list mode except workaround hooks - // because installed hooks would be propagated to all child processes of zygote - Router.startWorkAroundHook(); - // loadModules once for all child processes of zygote - // TODO maybe just save initZygote callbacks and call them when whitelisted process forked? - Router.loadModulesSafely(true); - Zygote.closeFilesBeforeFork(); - } - - private static void onForkPostCommon(boolean isSystemServer, String appDataDir, String niceName) { - Main.setAppDataDir(appDataDir); - Main.niceName = niceName; - final boolean isDynamicModulesMode = ConfigManager.isDynamicModulesEnabled(); - if (!isDynamicModulesMode) { - Zygote.reopenFilesAfterFork(); - } - Router.onEnterChildProcess(); - if (!checkNeedHook(appDataDir, niceName)) { - // if is blacklisted, just stop here - Router.onForkFinish(); - return; - } - if (isDynamicModulesMode) { - Router.initResourcesHook(); - } - Router.prepare(isSystemServer); - PrebuiltMethodsDeopter.deoptBootMethods(); - Router.installBootstrapHooks(isSystemServer); - if (isDynamicModulesMode) { - Router.loadModulesSafely(false); - } - Router.onForkFinish(); - } - - private static boolean checkNeedHook(String appDataDir, String niceName) { - boolean needHook; - if (TextUtils.isEmpty(appDataDir)) { - Utils.logE("niceName:" + niceName + ", procName:" - + ProcessUtils.getCurrentProcessName(Main.appProcessName) + ", appDataDir is null, blacklisted!"); - needHook = false; - } else { - // FIXME some process cannot read app_data_file because of MLS, e.g. bluetooth - needHook = ConfigManager.isAppNeedHook(appDataDir); - } - if (!needHook) { - // clean up the scene - onBlackListed(); - } - return needHook; - } - - private static void onBlackListed() { - XposedBridge.clearLoadedPackages(); - XposedBridge.clearInitPackageResources(); - } -} diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/proxy/NormalProxy.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/proxy/NormalProxy.java deleted file mode 100644 index 403e06ea..00000000 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/proxy/NormalProxy.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.elderdrivers.riru.edxp.sandhook.proxy; - -import com.elderdrivers.riru.edxp.Main; -import com.elderdrivers.riru.edxp.config.ConfigManager; -import com.elderdrivers.riru.edxp.deopt.PrebuiltMethodsDeopter; -import com.elderdrivers.riru.edxp.framework.Zygote; -import com.elderdrivers.riru.edxp.sandhook.entry.Router; - -import static com.elderdrivers.riru.edxp.util.FileUtils.getDataPathPrefix; - -public class NormalProxy { - - public static void forkAndSpecializePre(int uid, int gid, int[] gids, int debugFlags, - int[][] rlimits, int mountExternal, String seInfo, - String niceName, int[] fdsToClose, int[] fdsToIgnore, - boolean startChildZygote, String instructionSet, - String appDataDir) { - // mainly for secondary zygote - Router.onForkStart(); - Router.initResourcesHook(); - // call this to ensure the flag is set to false ASAP - Router.prepare(false); - PrebuiltMethodsDeopter.deoptBootMethods(); // do it once for secondary zygote - // install bootstrap hooks for secondary zygote - Router.installBootstrapHooks(false); - // only load modules for secondary zygote - Router.loadModulesSafely(true); - Zygote.closeFilesBeforeFork(); - } - - public static void forkAndSpecializePost(int pid, String appDataDir, String niceName) { - // TODO consider processes without forkAndSpecializePost called - Main.setAppDataDir(appDataDir); - Main.niceName = niceName; - Router.prepare(false); - Zygote.reopenFilesAfterFork(); - Router.onEnterChildProcess(); - // load modules for each app process on its forked if dynamic modules mode is on - Router.loadModulesSafely(false); - Router.onForkFinish(); - } - - public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, - long permittedCapabilities, long effectiveCapabilities) { - Router.onForkStart(); - Router.initResourcesHook(); - // set startsSystemServer flag used when loadModules - 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 - Router.installBootstrapHooks(true); - // loadModules have to be executed in zygote even isDynamicModules is false - // because if not global hooks installed in initZygote might not be - // propagated to processes not forked via forkAndSpecialize - Router.loadModulesSafely(true); - Zygote.closeFilesBeforeFork(); - } - - public static void forkSystemServerPost(int pid) { - // in system_server process - Main.setAppDataDir(getDataPathPrefix() + "android"); - Main.niceName = "system_server"; - Router.prepare(true); - Zygote.reopenFilesAfterFork(); - Router.onEnterChildProcess(); - // reload module list if dynamic mode is on - Router.loadModulesSafely(false); - Router.onForkFinish(); - } - -} diff --git a/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/XposedCompat.java b/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/XposedCompat.java index d3f8e893..a29d621f 100644 --- a/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/XposedCompat.java +++ b/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/XposedCompat.java @@ -4,6 +4,7 @@ import android.annotation.SuppressLint; import android.os.Process; import android.text.TextUtils; +import com.elderdrivers.riru.edxp.config.ConfigManager; import com.swift.sandhook.SandHook; import com.swift.sandhook.xposedcompat.classloaders.ComposeClassLoader; import com.swift.sandhook.xposedcompat.methodgen.SandHookXposedBridge; @@ -21,8 +22,6 @@ import static com.swift.sandhook.xposedcompat.utils.FileUtils.IS_USING_PROTECTED public class XposedCompat { - public static volatile String appDataDir; - // TODO initialize these variables public static volatile File cacheDir; public static volatile ClassLoader classLoader; @@ -37,16 +36,17 @@ public class XposedCompat { public static void addHookers(ClassLoader classLoader, Class[] hookers) { if (hookers == null) return; - for (Class hooker:hookers) { + for (Class hooker : hookers) { try { SandHook.addHookClass(classLoader, hooker); - } catch (Throwable throwable) {} + } catch (Throwable throwable) { + } } } public static File getCacheDir() { if (cacheDir == null) { - String fixedAppDataDir = getDataPathPrefix() + getPackageName(appDataDir) + "/"; + String fixedAppDataDir = getDataPathPrefix() + getPackageName(ConfigManager.appDataDir) + "/"; cacheDir = new File(fixedAppDataDir, "/cache/sandhook/" + ProcessUtils.getProcessName().replace(":", "_") + "/"); } diff --git a/edxp-sandhook/src/main/resources/META-INF/services/com.elderdrivers.riru.edxp.core.EdxpImpl b/edxp-sandhook/src/main/resources/META-INF/services/com.elderdrivers.riru.edxp.core.EdxpImpl new file mode 100644 index 00000000..7d797c04 --- /dev/null +++ b/edxp-sandhook/src/main/resources/META-INF/services/com.elderdrivers.riru.edxp.core.EdxpImpl @@ -0,0 +1 @@ +com.elderdrivers.riru.edxp.sandhook.core.SandHookEdxpImpl \ No newline at end of file diff --git a/edxp-whale/build.gradle b/edxp-whale/build.gradle index bb0fa267..686adfaa 100644 --- a/edxp-whale/build.gradle +++ b/edxp-whale/build.gradle @@ -12,6 +12,7 @@ android { targetSdkVersion 28 versionCode 1 versionName "1.0" + multiDexEnabled true } buildTypes { @@ -60,7 +61,8 @@ afterEvaluate { task("makeAndCopy${variantNameCapped}", type: Jar, dependsOn: "assemble${variantNameCapped}") { dependsOn tasks.getByPath(":edxp-common:copyCommonProperties") - from "${buildDir}/intermediates/transforms/dexMerger/${variantNameLowered}/0/" + from "${buildDir}/intermediates/transforms/dexMerger/${variantNameLowered}/0/", + "${projectDir}/src/main/resources/" destinationDir file(myTemplatePath + "system/framework/") baseName "edxp" doLast { diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/Main.java b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/Main.java deleted file mode 100644 index 5899d658..00000000 --- a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/Main.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.elderdrivers.riru.edxp; - -import android.annotation.SuppressLint; -import android.os.Build; -import android.os.Process; - -import com.elderdrivers.riru.common.KeepAll; -import com.elderdrivers.riru.edxp.config.ConfigManager; -import com.elderdrivers.riru.edxp.config.InstallerChooser; -import com.elderdrivers.riru.edxp.core.Yahfa; -import com.elderdrivers.riru.edxp.util.Utils; -import com.elderdrivers.riru.edxp.whale.core.HookMethodResolver; -import com.elderdrivers.riru.edxp.whale.entry.Router; -import com.elderdrivers.riru.edxp.whale.proxy.BlackWhiteListProxy; -import com.elderdrivers.riru.edxp.whale.proxy.NormalProxy; - -import java.util.Arrays; - -@SuppressLint("DefaultLocale") -public class Main implements KeepAll { - - public static String appDataDir = ""; - public static String niceName = ""; - public static String appProcessName = ""; - private static String forkAndSpecializePramsStr = ""; - private static String forkSystemServerPramsStr = ""; - - static { - Yahfa.init(Build.VERSION.SDK_INT); - HookMethodResolver.init(); - Router.injectConfig(); - InstallerChooser.setInstallerPackageName(ConfigManager.getInstallerPackageName()); - } - - /////////////////////////////////////////////////////////////////////////////////////////////// - // entry points - /////////////////////////////////////////////////////////////////////////////////////////////// - - public static void forkAndSpecializePre(int uid, int gid, int[] gids, int debugFlags, - int[][] rlimits, int mountExternal, String seInfo, - String niceName, int[] fdsToClose, int[] fdsToIgnore, - boolean startChildZygote, String instructionSet, - 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); - } - if (ConfigManager.isBlackWhiteListEnabled()) { - BlackWhiteListProxy.forkAndSpecializePre(uid, gid, gids, debugFlags, rlimits, - mountExternal, seInfo, niceName, fdsToClose, fdsToIgnore, startChildZygote, - instructionSet, appDataDir); - } else { - NormalProxy.forkAndSpecializePre(uid, gid, gids, debugFlags, rlimits, mountExternal, - seInfo, niceName, fdsToClose, fdsToIgnore, startChildZygote, instructionSet, - appDataDir); - } - } - - public static void forkAndSpecializePost(int pid, String appDataDir, String niceName) { - if (pid == 0) { - Utils.logD(forkAndSpecializePramsStr + " = " + Process.myPid()); - if (ConfigManager.isBlackWhiteListEnabled()) { - BlackWhiteListProxy.forkAndSpecializePost(pid, appDataDir, niceName); - } else { - NormalProxy.forkAndSpecializePost(pid, appDataDir, niceName); - } - } 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 - } - } - - public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, - 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 (ConfigManager.isBlackWhiteListEnabled()) { - BlackWhiteListProxy.forkSystemServerPre(uid, gid, gids, debugFlags, rlimits, - permittedCapabilities, effectiveCapabilities); - } else { - NormalProxy.forkSystemServerPre(uid, gid, gids, debugFlags, rlimits, - permittedCapabilities, effectiveCapabilities); - } - } - - public static void forkSystemServerPost(int pid) { - if (pid == 0) { - Utils.logD(forkSystemServerPramsStr + " = " + Process.myPid()); - if (ConfigManager.isBlackWhiteListEnabled()) { - BlackWhiteListProxy.forkSystemServerPost(pid); - } else { - NormalProxy.forkSystemServerPost(pid); - } - } 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 - } - } - -} diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/_hooker/LoadedApkConstructorHooker.java b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/_hooker/LoadedApkConstructorHooker.java deleted file mode 100644 index 2376ce82..00000000 --- a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/_hooker/LoadedApkConstructorHooker.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.elderdrivers.riru.edxp.whale._hooker; - -import android.app.ActivityThread; -import android.app.AndroidAppHelper; -import android.app.LoadedApk; -import android.content.pm.ApplicationInfo; -import android.content.res.CompatibilityInfo; -import android.util.Log; - -import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp.hooker.XposedBlackListHooker; -import com.elderdrivers.riru.edxp.whale.entry.Router; - -import de.robv.android.xposed.XposedBridge; -import de.robv.android.xposed.XposedHelpers; -import de.robv.android.xposed.XposedInit; -import de.robv.android.xposed.callbacks.XC_LoadPackage; - -import static com.elderdrivers.riru.edxp.util.ClassLoaderUtils.replaceParentClassLoader; - -// when a package is loaded for an existing process, trigger the callbacks as well -// ed: remove resources related hooking -public class LoadedApkConstructorHooker implements KeepMembers { - public static String className = "android.app.LoadedApk"; - public static String methodName = ""; - public static String methodSig = "(Landroid/app/ActivityThread;" + - "Landroid/content/pm/ApplicationInfo;" + - "Landroid/content/res/CompatibilityInfo;" + - "Ljava/lang/ClassLoader;ZZZ)V"; - - public static void hook(Object thiz, ActivityThread activityThread, - ApplicationInfo aInfo, CompatibilityInfo compatInfo, - ClassLoader baseLoader, boolean securityViolation, - boolean includeCode, boolean registerPackage) { - - if (XposedBlackListHooker.shouldDisableHooks("")) { - backup(thiz, activityThread, aInfo, compatInfo, baseLoader, securityViolation, - includeCode, registerPackage); - return; - } - - Router.logD("LoadedApk# starts"); - backup(thiz, activityThread, aInfo, compatInfo, baseLoader, securityViolation, - includeCode, registerPackage); - - try { - LoadedApk loadedApk = (LoadedApk) thiz; - String packageName = loadedApk.getPackageName(); - Object mAppDir = XposedHelpers.getObjectField(thiz, "mAppDir"); - Router.logD("LoadedApk# ends: " + mAppDir); - - if (XposedBlackListHooker.shouldDisableHooks(packageName)) { - return; - } - - if (packageName.equals("android")) { - Router.logD("LoadedApk# is android, skip: " + mAppDir); - return; - } - - // mIncludeCode checking should go ahead of loadedPackagesInProcess added checking - if (!XposedHelpers.getBooleanField(loadedApk, "mIncludeCode")) { - Router.logD("LoadedApk# mIncludeCode == false: " + mAppDir); - return; - } - - if (!XposedInit.loadedPackagesInProcess.add(packageName)) { - Router.logD("LoadedApk# has been loaded before, skip: " + mAppDir); - return; - } - - // OnePlus magic... - if (Log.getStackTraceString(new Throwable()). - contains("android.app.ActivityThread$ApplicationThread.schedulePreload")) { - Router.logD("LoadedApk# maybe oneplus's custom opt, skip"); - return; - } - - replaceParentClassLoader(loadedApk.getClassLoader()); - - XC_LoadPackage.LoadPackageParam lpparam = new XC_LoadPackage.LoadPackageParam(XposedBridge.sLoadedPackageCallbacks); - lpparam.packageName = packageName; - lpparam.processName = AndroidAppHelper.currentProcessName(); - lpparam.classLoader = loadedApk.getClassLoader(); - lpparam.appInfo = loadedApk.getApplicationInfo(); - lpparam.isFirstApplication = false; - XC_LoadPackage.callAll(lpparam); - } catch (Throwable t) { - Router.logE("error when hooking LoadedApk.", t); - } - } - - public static void backup(Object thiz, ActivityThread activityThread, - ApplicationInfo aInfo, CompatibilityInfo compatInfo, - ClassLoader baseLoader, boolean securityViolation, - boolean includeCode, boolean registerPackage) { - - } -} \ No newline at end of file diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/_hooker/OnePlusWorkAroundHooker.java b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/_hooker/OnePlusWorkAroundHooker.java deleted file mode 100644 index 85c53223..00000000 --- a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/_hooker/OnePlusWorkAroundHooker.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.elderdrivers.riru.edxp.whale._hooker; - -import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp.Main; -import com.elderdrivers.riru.edxp.whale.entry.Router; - -import de.robv.android.xposed.XposedBridge; - -/** - * On OnePlus stock roms (Android Pie), {@link dalvik.system.BaseDexClassLoader#findClass(String)} - * will open /dev/binder to communicate with PackageManagerService to check whether - * current package name inCompatConfigList, which is an OnePlus OEM feature enabled only when - * system prop "persist.sys.oem.region" set to "CN".(detail of related source code: - * https://gist.github.com/solohsu/ecc07141759958fc096ba0781fac0a5f) - * If we invoke intZygoteCallbacks in - * {@link Main#forkAndSpecializePre}, where in zygote process, - * we would get a chance to invoke findclass, leaving fd of /dev/binder open in zygote process, - * which is not allowed because /dev/binder is not in predefined whitelist here: - * http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/jni/fd_utils.cpp#35 - * So we just hook BaseDexClassLoader#inCompatConfigList to return false to prevent - * open of /dev/binder and we haven't found side effects yet. - * Other roms might share the same problems but not reported too. - */ -public class OnePlusWorkAroundHooker implements KeepMembers { - - public static String className = "dalvik.system.BaseDexClassLoader"; - public static String methodName = "inCompatConfigList"; - public static String methodSig = "(ILjava/lang/String;)Z"; - - public static boolean hook(int type, String packageName) { - if (XposedBridge.disableHooks || Router.forkCompleted) { - return backup(type, packageName); - } - Router.logD("BaseDexClassLoader#inCompatConfigList() starts"); - return false; - } - - public static boolean backup(int type, String packageName) { - return false; - } -} \ No newline at end of file diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/_hooker/StartBootstrapServicesHooker.java b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/_hooker/StartBootstrapServicesHooker.java deleted file mode 100644 index b49dacef..00000000 --- a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/_hooker/StartBootstrapServicesHooker.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.elderdrivers.riru.edxp.whale._hooker; - -import android.os.Build; - -import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp.whale.entry.Router; - -import de.robv.android.xposed.XC_MethodReplacement; -import de.robv.android.xposed.XposedBridge; -import de.robv.android.xposed.XposedHelpers; -import de.robv.android.xposed.XposedInit; -import de.robv.android.xposed.callbacks.XC_LoadPackage; - -import static com.elderdrivers.riru.edxp.util.ClassLoaderUtils.replaceParentClassLoader; -import static com.elderdrivers.riru.edxp.util.Utils.logD; -import static de.robv.android.xposed.XposedHelpers.findAndHookMethod; - -public class StartBootstrapServicesHooker implements KeepMembers { - public static String className = "com.android.server.SystemServer"; - public static String methodName = "startBootstrapServices"; - public static String methodSig = "()V"; - - public static void hook(Object systemServer) { - - if (XposedBridge.disableHooks) { - backup(systemServer); - return; - } - - logD("SystemServer#startBootstrapServices() starts"); - - try { - XposedInit.loadedPackagesInProcess.add("android"); - - replaceParentClassLoader(SystemMainHooker.systemServerCL); - - XC_LoadPackage.LoadPackageParam lpparam = new XC_LoadPackage.LoadPackageParam(XposedBridge.sLoadedPackageCallbacks); - lpparam.packageName = "android"; - lpparam.processName = "android"; // it's actually system_server, but other functions return this as well - lpparam.classLoader = SystemMainHooker.systemServerCL; - lpparam.appInfo = null; - lpparam.isFirstApplication = true; - XC_LoadPackage.callAll(lpparam); - - // Huawei - try { - findAndHookMethod("com.android.server.pm.HwPackageManagerService", SystemMainHooker.systemServerCL, "isOdexMode", XC_MethodReplacement.returnConstant(false)); - } catch (XposedHelpers.ClassNotFoundError | NoSuchMethodError ignored) { - } - - try { - String className = "com.android.server.pm." + (Build.VERSION.SDK_INT >= 23 ? "PackageDexOptimizer" : "PackageManagerService"); - findAndHookMethod(className, SystemMainHooker.systemServerCL, "dexEntryExists", String.class, XC_MethodReplacement.returnConstant(true)); - } catch (XposedHelpers.ClassNotFoundError | NoSuchMethodError ignored) { - } - } catch (Throwable t) { - Router.logE("error when hooking startBootstrapServices", t); - } finally { - backup(systemServer); - } - } - - public static void backup(Object systemServer) { - - } -} diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/_hooker/SystemMainHooker.java b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/_hooker/SystemMainHooker.java deleted file mode 100644 index 707e6dd7..00000000 --- a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/_hooker/SystemMainHooker.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.elderdrivers.riru.edxp.whale._hooker; - -import android.app.ActivityThread; - -import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp.deopt.PrebuiltMethodsDeopter; -import com.elderdrivers.riru.edxp.whale.entry.Router; - -import de.robv.android.xposed.XposedBridge; - - -// system_server initialization -// ed: only support sdk >= 21 for now -public class SystemMainHooker implements KeepMembers { - - public static String className = "android.app.ActivityThread"; - public static String methodName = "systemMain"; - public static String methodSig = "()Landroid/app/ActivityThread;"; - - public static ClassLoader systemServerCL; - - public static ActivityThread hook() { - if (XposedBridge.disableHooks) { - return backup(); - } - Router.logD("ActivityThread#systemMain() starts"); - ActivityThread activityThread = backup(); - try { - // get system_server classLoader - systemServerCL = Thread.currentThread().getContextClassLoader(); - // deopt methods in SYSTEMSERVERCLASSPATH - PrebuiltMethodsDeopter.deoptSystemServerMethods(systemServerCL); - Router.startSystemServerHook(); - } catch (Throwable t) { - Router.logE("error when hooking systemMain", t); - } - return activityThread; - } - - public static ActivityThread backup() { - return null; - } -} \ No newline at end of file diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/config/WhaleEdxpConfig.java b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/config/WhaleEdxpConfig.java index 6246b282..f3172399 100644 --- a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/config/WhaleEdxpConfig.java +++ b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/config/WhaleEdxpConfig.java @@ -1,6 +1,5 @@ package com.elderdrivers.riru.edxp.whale.config; -import com.elderdrivers.riru.edxp.Main; import com.elderdrivers.riru.edxp.config.ConfigManager; import com.elderdrivers.riru.edxp.config.EdXpConfig; import com.elderdrivers.riru.edxp.config.InstallerChooser; diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/config/WhaleHookProvider.java b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/config/WhaleHookProvider.java index f4a7997e..cbf5cbf5 100644 --- a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/config/WhaleHookProvider.java +++ b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/config/WhaleHookProvider.java @@ -1,6 +1,5 @@ package com.elderdrivers.riru.edxp.whale.config; -import com.elderdrivers.riru.edxp.Main; import com.elderdrivers.riru.edxp.art.ClassLinker; import com.elderdrivers.riru.edxp.config.BaseHookProvider; import com.elderdrivers.riru.edxp.core.ResourcesHook; diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/core/HookMain.java b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/core/HookMain.java deleted file mode 100644 index 5abe1d3e..00000000 --- a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/core/HookMain.java +++ /dev/null @@ -1,185 +0,0 @@ -package com.elderdrivers.riru.edxp.whale.core; - -import com.elderdrivers.riru.edxp.Main; -import com.elderdrivers.riru.edxp.art.Heap; -import com.elderdrivers.riru.edxp.core.Yahfa; -import com.elderdrivers.riru.edxp.whale._hooker.OnePlusWorkAroundHooker; -import com.elderdrivers.riru.edxp.util.Utils; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Set; - -import de.robv.android.xposed.XposedHelpers; - -public class HookMain { - - private static Set hookItemWhiteList = Collections.singleton(OnePlusWorkAroundHooker.class.getName()); - - public static void doHookDefault(ClassLoader patchClassLoader, ClassLoader originClassLoader, String hookInfoClassName) { - try { - Class hookInfoClass = Class.forName(hookInfoClassName, true, patchClassLoader); - String[] hookItemNames = (String[]) hookInfoClass.getField("hookItemNames").get(null); - for (String hookItemName : hookItemNames) { - doHookItemDefault(patchClassLoader, hookItemName, originClassLoader); - } - } catch (Throwable e) { - Utils.logE("error when hooking all in: " + hookInfoClassName, e); - } - } - - private static void doHookItemDefault(ClassLoader patchClassLoader, String hookItemName, ClassLoader originClassLoader) { - try { - Utils.logD("Start hooking with item " + hookItemName); - Class hookItem = Class.forName(hookItemName, true, patchClassLoader); - - String className = (String) hookItem.getField("className").get(null); - String methodName = (String) hookItem.getField("methodName").get(null); - String methodSig = (String) hookItem.getField("methodSig").get(null); - - if (className == null || className.equals("")) { - Utils.logW("No target class. Skipping..."); - return; - } - Class clazz = null; - try { - clazz = Class.forName(className, true, originClassLoader); - } catch (ClassNotFoundException cnfe) { - Utils.logE(className + " not found in " + originClassLoader); - return; - } - if (Modifier.isAbstract(clazz.getModifiers())) { - Utils.logW("Hook may fail for abstract class: " + className); - } - - Method hook = null; - Method backup = null; - for (Method method : hookItem.getDeclaredMethods()) { - if (method.getName().equals("hook") && Modifier.isStatic(method.getModifiers())) { - hook = method; - } else if (method.getName().equals("backup") && Modifier.isStatic(method.getModifiers())) { - backup = method; - } - } - if (hook == null) { - Utils.logE("Cannot find hook for " + methodName); - return; - } - findAndBackupAndHook(clazz, methodName, methodSig, hook, backup); - } catch (Throwable e) { - if (!hookItemWhiteList.contains(hookItemName)) { - Utils.logE("error when hooking " + hookItemName, e); - } - } - } - - public static void findAndHook(Class targetClass, String methodName, String methodSig, Method hook) { - hook(findMethod(targetClass, methodName, methodSig), hook); - } - - public static void findAndBackupAndHook(Class targetClass, String methodName, String methodSig, - Method hook, Method backup) { - backupAndHook(findMethod(targetClass, methodName, methodSig), hook, backup); - } - - public static void hook(Object target, Method hook) { - backupAndHook(target, hook, null); - } - - public static void backupAndHook(Object target, Method hook, Method backup) { - Utils.logD(String.format("target=%s, hook=%s, backup=%s", target, hook, backup)); - if (target == null) { - throw new IllegalArgumentException("null target method"); - } - if (hook == null) { - throw new IllegalArgumentException("null hook method"); - } - - if (!Modifier.isStatic(hook.getModifiers())) { - throw new IllegalArgumentException("Hook must be a static method: " + hook); - } - checkCompatibleMethods(target, hook, "Original", "Hook"); - if (backup != null) { - if (!Modifier.isStatic(backup.getModifiers())) { - throw new IllegalArgumentException("Backup must be a static method: " + backup); - } - // backup is just a placeholder and the constraint could be less strict - checkCompatibleMethods(target, backup, "Original", "Backup"); - } - if (backup != null) { - HookMethodResolver.resolveMethod(hook, backup); - } - // make sure GC completed before hook - Thread currentThread = Thread.currentThread(); - int lastGcType = Heap.waitForGcToComplete( - XposedHelpers.getLongField(currentThread, "nativePeer")); - if (lastGcType < 0) { - Utils.logW("waitForGcToComplete failed, using fallback"); - Runtime.getRuntime().gc(); - } - if (!Yahfa.backupAndHookNative(target, hook, backup)) { - throw new RuntimeException("Failed to hook " + target + " with " + hook); - } - } - - public static Object findMethod(Class cls, String methodName, String methodSig) { - if (cls == null) { - throw new IllegalArgumentException("null class"); - } - if (methodName == null) { - throw new IllegalArgumentException("null method name"); - } - if (methodSig == null) { - throw new IllegalArgumentException("null method signature"); - } - return Yahfa.findMethodNative(cls, methodName, methodSig); - } - - private static void checkCompatibleMethods(Object original, Method replacement, String originalName, String replacementName) { - ArrayList> originalParams; - if (original instanceof Method) { - originalParams = new ArrayList<>(Arrays.asList(((Method) original).getParameterTypes())); - } else if (original instanceof Constructor) { - originalParams = new ArrayList<>(Arrays.asList(((Constructor) original).getParameterTypes())); - } else { - throw new IllegalArgumentException("Type of target method is wrong"); - } - - ArrayList> replacementParams = new ArrayList<>(Arrays.asList(replacement.getParameterTypes())); - - if (original instanceof Method - && !Modifier.isStatic(((Method) original).getModifiers())) { - originalParams.add(0, ((Method) original).getDeclaringClass()); - } else if (original instanceof Constructor) { - originalParams.add(0, ((Constructor) original).getDeclaringClass()); - } - - - if (!Modifier.isStatic(replacement.getModifiers())) { - replacementParams.add(0, replacement.getDeclaringClass()); - } - - if (original instanceof Method - && !replacement.getReturnType().isAssignableFrom(((Method) original).getReturnType())) { - throw new IllegalArgumentException("Incompatible return types. " + originalName + ": " + ((Method) original).getReturnType() + ", " + replacementName + ": " + replacement.getReturnType()); - } else if (original instanceof Constructor) { - if (replacement.getReturnType().equals(Void.class)) { - throw new IllegalArgumentException("Incompatible return types. " + "" + ": " + "V" + ", " + replacementName + ": " + replacement.getReturnType()); - } - } - - if (originalParams.size() != replacementParams.size()) { - throw new IllegalArgumentException("Number of arguments don't match. " + originalName + ": " + originalParams.size() + ", " + replacementName + ": " + replacementParams.size()); - } - - for (int i = 0; i < originalParams.size(); i++) { - if (!replacementParams.get(i).isAssignableFrom(originalParams.get(i))) { - throw new IllegalArgumentException("Incompatible argument #" + i + ": " + originalName + ": " + originalParams.get(i) + ", " + replacementName + ": " + replacementParams.get(i)); - } - } - } -} diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/core/WhaleEdxpImpl.java b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/core/WhaleEdxpImpl.java new file mode 100644 index 00000000..e3ee44f9 --- /dev/null +++ b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/core/WhaleEdxpImpl.java @@ -0,0 +1,32 @@ +package com.elderdrivers.riru.edxp.whale.core; + +import android.os.Build; + +import com.elderdrivers.riru.edxp.config.ConfigManager; +import com.elderdrivers.riru.edxp.config.InstallerChooser; +import com.elderdrivers.riru.edxp.core.BaseEdxpImpl; +import com.elderdrivers.riru.edxp.core.Yahfa; +import com.elderdrivers.riru.edxp.core.yahfa.HookMethodResolver; + +public class WhaleEdxpImpl extends BaseEdxpImpl { + + @Override + protected com.elderdrivers.riru.edxp.proxy.Router createRouter() { + return new WhaleRouter(); + } + + @Override + public int getVariant() { + return WHALE; + } + + @Override + public void init() { + Yahfa.init(Build.VERSION.SDK_INT); + HookMethodResolver.init(); + getRouter().injectConfig(); + InstallerChooser.setInstallerPackageName(ConfigManager.getInstallerPackageName()); + + setInitialized(); + } +} diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/core/WhaleRouter.java b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/core/WhaleRouter.java new file mode 100644 index 00000000..baa142e9 --- /dev/null +++ b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/core/WhaleRouter.java @@ -0,0 +1,22 @@ +package com.elderdrivers.riru.edxp.whale.core; + +import com.elderdrivers.riru.edxp.config.EdXpConfigGlobal; +import com.elderdrivers.riru.edxp.proxy.BaseRouter; +import com.elderdrivers.riru.edxp.whale.config.WhaleEdxpConfig; +import com.elderdrivers.riru.edxp.whale.config.WhaleHookProvider; + +import de.robv.android.xposed.XposedBridge; + +public class WhaleRouter extends BaseRouter { + + public void onEnterChildProcess() { + + } + + public void injectConfig() { + EdXpConfigGlobal.sConfig = new WhaleEdxpConfig(); + EdXpConfigGlobal.sHookProvider = new WhaleHookProvider(); + XposedBridge.log("using HookProvider: " + EdXpConfigGlobal.sHookProvider.getClass().getName()); + } + +} diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/dexmaker/DexLog.java b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/dexmaker/DexLog.java deleted file mode 100644 index 234dfaad..00000000 --- a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/dexmaker/DexLog.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.elderdrivers.riru.edxp.whale.dexmaker; - -import android.util.Log; - -import com.elderdrivers.riru.edxp.BuildConfig; - -public class DexLog { - - public static final String TAG = "EdXposed-dexmaker"; - - public static int v(String s) { - return Log.v(TAG, s); - } - - public static int i(String s) { - return Log.i(TAG, s); - } - - public static int d(String s) { - if (BuildConfig.DEBUG) { - return Log.d(TAG, s); - } - return 0; - } - - public static int w(String s) { - return Log.w(TAG, s); - } - - public static int e(String s) { - return Log.e(TAG, s); - } - - public static int e(String s, Throwable t) { - return Log.e(TAG, s, t); - } -} diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/dexmaker/MethodInfo.java b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/dexmaker/MethodInfo.java deleted file mode 100644 index 1879a4a0..00000000 --- a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/dexmaker/MethodInfo.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.elderdrivers.riru.edxp.whale.dexmaker; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Member; -import java.lang.reflect.Method; - -public class MethodInfo { - - public String className; - public String classDesc; - public String methodName; - public String methodSig; - public Method method; - public Constructor constructor; - public boolean isConstructor; - public ClassLoader classLoader; - - public MethodInfo(Member member) { - if (member instanceof Method) { - method = (Method) member; - isConstructor = false; - classLoader = member.getDeclaringClass().getClassLoader(); - generateMethodInfo(); - } else if (member instanceof Constructor) { - constructor = (Constructor) member; - isConstructor = true; - classLoader = member.getDeclaringClass().getClassLoader(); - generateConstructorInfo(); - } else { - throw new IllegalArgumentException("member should be Method or Constructor"); - } - } - - private void generateConstructorInfo() { - methodName = ""; - className = constructor.getDeclaringClass().getName(); - generateCommonInfo(constructor.getParameterTypes(), void.class); - } - - private void generateMethodInfo() { - methodName = method.getName(); - className = method.getDeclaringClass().getName(); - generateCommonInfo(method.getParameterTypes(), method.getReturnType()); - } - - private void generateCommonInfo(Class[] parameterTypes, Class returnType) { - classDesc = "L" + className.replace(".", "/") + ";"; - StringBuilder builder = new StringBuilder(); - builder.append("("); - for (Class parameterType : parameterTypes) { - builder.append(getDescStr(parameterType)); - } - builder.append(")"); - builder.append(getDescStr(returnType)); - methodSig = builder.toString(); - } - - public Class getClassForSure() { - try { - // TODO does initialize make sense? - return Class.forName(className, true, classLoader); - } catch (Throwable throwable) { - DexLog.e("error when getClassForSure", throwable); - return null; - } - } - - public static String getDescStr(Class clazz) { - if (clazz.equals(boolean.class)) { - return "Z"; - } else if (clazz.equals(byte.class)) { - return "B"; - } else if (clazz.equals(char.class)) { - return "C"; - } else if (clazz.equals(double.class)) { - return "D"; - } else if (clazz.equals(float.class)) { - return "F"; - } else if (clazz.equals(int.class)) { - return "I"; - } else if (clazz.equals(long.class)) { - return "J"; - } else if (clazz.equals(short.class)) { - return "S"; - } else if (clazz.equals(void.class)) { - return "V"; - } else { - String prefix = clazz.isArray() ? "" : "L"; - String suffix = clazz.isArray() ? "" : ";"; - return prefix + clazz.getName().replace(".", "/") + suffix; - } - } - -} diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/entry/Router.java b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/entry/Router.java deleted file mode 100644 index d4b1d39f..00000000 --- a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/entry/Router.java +++ /dev/null @@ -1,134 +0,0 @@ -package com.elderdrivers.riru.edxp.whale.entry; - -import android.app.AndroidAppHelper; -import android.text.TextUtils; - -import com.elderdrivers.riru.edxp.config.EdXpConfigGlobal; -import com.elderdrivers.riru.edxp.util.Utils; -import com.elderdrivers.riru.edxp.whale.config.WhaleEdxpConfig; -import com.elderdrivers.riru.edxp.whale.config.WhaleHookProvider; -import com.elderdrivers.riru.edxp.whale.core.HookMain; -import com.elderdrivers.riru.edxp.whale.entry.bootstrap.AppBootstrapHookInfo; -import com.elderdrivers.riru.edxp.whale.entry.bootstrap.SysBootstrapHookInfo; -import com.elderdrivers.riru.edxp.whale.entry.bootstrap.SysInnerHookInfo; -import com.elderdrivers.riru.edxp.whale.entry.bootstrap.WorkAroundHookInfo; -import com.elderdrivers.riru.edxp.whale._hooker.SystemMainHooker; - -import java.util.concurrent.atomic.AtomicBoolean; - -import de.robv.android.xposed.XposedBridge; -import de.robv.android.xposed.XposedInit; - -public class Router { - - public volatile static boolean forkCompleted = false; - - private static volatile AtomicBoolean bootstrapHooked = new AtomicBoolean(false); - - public static void initResourcesHook() { - startWorkAroundHook(); // for OnePlus devices - XposedBridge.initXResources(); - } - - public static void prepare(boolean isSystem) { - // this flag is needed when loadModules - XposedInit.startsSystemServer = isSystem; - } - - public static void checkHookState(String appDataDir) { - // determine whether allow xposed or not -// XposedBridge.disableHooks = ConfigManager.shouldHook(parsePackageName(appDataDir)); - } - - private static String parsePackageName(String appDataDir) { - if (TextUtils.isEmpty(appDataDir)) { - return ""; - } - int lastIndex = appDataDir.lastIndexOf("/"); - if (lastIndex < 1) { - return ""; - } - return appDataDir.substring(lastIndex + 1); - } - - public static void installBootstrapHooks(boolean isSystem) { - // Initialize the Xposed framework - try { - if (!bootstrapHooked.compareAndSet(false, true)) { - return; - } - Router.startBootstrapHook(isSystem); - XposedInit.initForZygote(isSystem); - } catch (Throwable t) { - Utils.logE("error during Xposed initialization", t); - XposedBridge.disableHooks = true; - } - } - - public static void loadModulesSafely(boolean isInZygote) { - try { - // FIXME some coredomain app can't reading modules.list - XposedInit.loadModules(isInZygote); - } catch (Exception exception) { - Utils.logE("error loading module list", exception); - } - } - - public static void startBootstrapHook(boolean isSystem) { - Utils.logD("startBootstrapHook starts: isSystem = " + isSystem); - ClassLoader classLoader = XposedBridge.BOOTCLASSLOADER; - if (isSystem) { - HookMain.doHookDefault( - Router.class.getClassLoader(), - classLoader, - SysBootstrapHookInfo.class.getName()); - } else { - HookMain.doHookDefault( - Router.class.getClassLoader(), - classLoader, - AppBootstrapHookInfo.class.getName()); - } - } - - public static void startSystemServerHook() { - HookMain.doHookDefault( - Router.class.getClassLoader(), - SystemMainHooker.systemServerCL, - SysInnerHookInfo.class.getName()); - } - - public static void startWorkAroundHook() { - HookMain.doHookDefault( - Router.class.getClassLoader(), - XposedBridge.BOOTCLASSLOADER, - WorkAroundHookInfo.class.getName()); - } - - public static void onForkStart() { - forkCompleted = false; - } - - public static void onForkFinish() { - forkCompleted = true; - } - - public static void onEnterChildProcess() { - - } - - public static void logD(String prefix) { - Utils.logD(String.format("%s: pkg=%s, prc=%s", prefix, AndroidAppHelper.currentPackageName(), - AndroidAppHelper.currentProcessName())); - } - - public static void logE(String prefix, Throwable throwable) { - Utils.logE(String.format("%s: pkg=%s, prc=%s", prefix, AndroidAppHelper.currentPackageName(), - AndroidAppHelper.currentProcessName()), throwable); - } - - public static void injectConfig() { - EdXpConfigGlobal.sConfig = new WhaleEdxpConfig(); - EdXpConfigGlobal.sHookProvider = new WhaleHookProvider(); - XposedBridge.log("using HookProvider: " + EdXpConfigGlobal.sHookProvider.getClass().getName()); - } -} diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/entry/bootstrap/SysBootstrapHookInfo.java b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/entry/bootstrap/SysBootstrapHookInfo.java deleted file mode 100644 index 38ccae83..00000000 --- a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/entry/bootstrap/SysBootstrapHookInfo.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.elderdrivers.riru.edxp.whale.entry.bootstrap; - -import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp.whale._hooker.HandleBindAppHooker; -import com.elderdrivers.riru.edxp.whale._hooker.LoadedApkConstructorHooker; -import com.elderdrivers.riru.edxp.whale._hooker.OnePlusWorkAroundHooker; -import com.elderdrivers.riru.edxp.whale._hooker.SystemMainHooker; - -public class SysBootstrapHookInfo implements KeepMembers { - public static String[] hookItemNames = { - HandleBindAppHooker.class.getName(), - SystemMainHooker.class.getName(), - LoadedApkConstructorHooker.class.getName(), - OnePlusWorkAroundHooker.class.getName() - }; -} diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/entry/bootstrap/SysInnerHookInfo.java b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/entry/bootstrap/SysInnerHookInfo.java deleted file mode 100644 index a08a012c..00000000 --- a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/entry/bootstrap/SysInnerHookInfo.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.elderdrivers.riru.edxp.whale.entry.bootstrap; - -import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp.whale._hooker.StartBootstrapServicesHooker; - -public class SysInnerHookInfo implements KeepMembers { - public static String[] hookItemNames = { - StartBootstrapServicesHooker.class.getName() - }; -} diff --git a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/proxy/NormalProxy.java b/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/proxy/NormalProxy.java deleted file mode 100644 index 9f39c0dd..00000000 --- a/edxp-whale/src/main/java/com/elderdrivers/riru/edxp/whale/proxy/NormalProxy.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.elderdrivers.riru.edxp.whale.proxy; - -import com.elderdrivers.riru.edxp.Main; -import com.elderdrivers.riru.edxp.config.ConfigManager; -import com.elderdrivers.riru.edxp.deopt.PrebuiltMethodsDeopter; -import com.elderdrivers.riru.edxp.framework.Zygote; -import com.elderdrivers.riru.edxp.whale.entry.Router; - -import static com.elderdrivers.riru.edxp.util.FileUtils.getDataPathPrefix; - -public class NormalProxy { - - public static void forkAndSpecializePre(int uid, int gid, int[] gids, int debugFlags, - int[][] rlimits, int mountExternal, String seInfo, - String niceName, int[] fdsToClose, int[] fdsToIgnore, - boolean startChildZygote, String instructionSet, - String appDataDir) { - // mainly for secondary zygote - Router.onForkStart(); - Router.initResourcesHook(); - // call this to ensure the flag is set to false ASAP - Router.prepare(false); - PrebuiltMethodsDeopter.deoptBootMethods(); // do it once for secondary zygote - // install bootstrap hooks for secondary zygote - Router.installBootstrapHooks(false); - // only load modules for secondary zygote - Router.loadModulesSafely(true); - Zygote.closeFilesBeforeFork(); - } - - public static void forkAndSpecializePost(int pid, String appDataDir, String niceName) { - // TODO consider processes without forkAndSpecializePost called - Main.appDataDir = appDataDir; - Main.niceName = niceName; - Router.prepare(false); - Zygote.reopenFilesAfterFork(); - Router.onEnterChildProcess(); - // load modules for each app process on its forked if dynamic modules mode is on - Router.loadModulesSafely(false); - Router.onForkFinish(); - } - - public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, - long permittedCapabilities, long effectiveCapabilities) { - Router.onForkStart(); - Router.initResourcesHook(); - // set startsSystemServer flag used when loadModules - 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 - Router.installBootstrapHooks(true); - // loadModules have to be executed in zygote even isDynamicModules is false - // because if not global hooks installed in initZygote might not be - // propagated to processes not forked via forkAndSpecialize - Router.loadModulesSafely(true); - Zygote.closeFilesBeforeFork(); - } - - public static void forkSystemServerPost(int pid) { - // in system_server process - Main.appDataDir = getDataPathPrefix() + "android"; - Main.niceName = "system_server"; - Router.prepare(true); - Zygote.reopenFilesAfterFork(); - Router.onEnterChildProcess(); - // reload module list if dynamic mode is on - Router.loadModulesSafely(false); - Router.onForkFinish(); - } - -} diff --git a/edxp-whale/src/main/resources/META-INF/services/com.elderdrivers.riru.edxp.core.EdxpImpl b/edxp-whale/src/main/resources/META-INF/services/com.elderdrivers.riru.edxp.core.EdxpImpl new file mode 100644 index 00000000..aa3d9d26 --- /dev/null +++ b/edxp-whale/src/main/resources/META-INF/services/com.elderdrivers.riru.edxp.core.EdxpImpl @@ -0,0 +1 @@ +com.elderdrivers.riru.edxp.whale.core.WhaleEdxpImpl \ No newline at end of file diff --git a/edxp-yahfa/build.gradle b/edxp-yahfa/build.gradle index 7250442b..28233df2 100644 --- a/edxp-yahfa/build.gradle +++ b/edxp-yahfa/build.gradle @@ -12,6 +12,7 @@ android { targetSdkVersion 28 versionCode 1 versionName "1.0" + multiDexEnabled true } buildTypes { @@ -60,7 +61,8 @@ afterEvaluate { task("makeAndCopy${variantNameCapped}", type: Jar, dependsOn: "assemble${variantNameCapped}") { dependsOn tasks.getByPath(":edxp-common:copyCommonProperties") - from "${buildDir}/intermediates/transforms/dexMerger/${variantNameLowered}/0/" + from "${buildDir}/intermediates/transforms/dexMerger/${variantNameLowered}/0/", + "${projectDir}/src/main/resources/" destinationDir file(myTemplatePath + "system/framework/") baseName "edxp" doLast { diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/Main.java b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/Main.java deleted file mode 100644 index 7eed9a4a..00000000 --- a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/Main.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.elderdrivers.riru.edxp; - -import android.annotation.SuppressLint; -import android.os.Build; -import android.os.Process; - -import com.elderdrivers.riru.common.KeepAll; -import com.elderdrivers.riru.edxp.config.ConfigManager; -import com.elderdrivers.riru.edxp.config.InstallerChooser; -import com.elderdrivers.riru.edxp.core.Yahfa; -import com.elderdrivers.riru.edxp.util.Utils; -import com.elderdrivers.riru.edxp.yahfa.core.HookMethodResolver; -import com.elderdrivers.riru.edxp.yahfa.entry.Router; -import com.elderdrivers.riru.edxp.yahfa.proxy.BlackWhiteListProxy; -import com.elderdrivers.riru.edxp.yahfa.proxy.NormalProxy; - -import java.util.Arrays; - -@SuppressLint("DefaultLocale") -public class Main implements KeepAll { - - public static String appDataDir = ""; - public static String niceName = ""; - public static String appProcessName = ""; - private static String forkAndSpecializePramsStr = ""; - private static String forkSystemServerPramsStr = ""; - - static { - Yahfa.init(Build.VERSION.SDK_INT); - HookMethodResolver.init(); - Router.injectConfig(); - InstallerChooser.setInstallerPackageName(ConfigManager.getInstallerPackageName()); - } - - /////////////////////////////////////////////////////////////////////////////////////////////// - // entry points - /////////////////////////////////////////////////////////////////////////////////////////////// - - public static void forkAndSpecializePre(int uid, int gid, int[] gids, int debugFlags, - int[][] rlimits, int mountExternal, String seInfo, - String niceName, int[] fdsToClose, int[] fdsToIgnore, - boolean startChildZygote, String instructionSet, - 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); - } - if (ConfigManager.isBlackWhiteListEnabled()) { - BlackWhiteListProxy.forkAndSpecializePre(uid, gid, gids, debugFlags, rlimits, - mountExternal, seInfo, niceName, fdsToClose, fdsToIgnore, startChildZygote, - instructionSet, appDataDir); - } else { - NormalProxy.forkAndSpecializePre(uid, gid, gids, debugFlags, rlimits, mountExternal, - seInfo, niceName, fdsToClose, fdsToIgnore, startChildZygote, instructionSet, - appDataDir); - } - } - - public static void forkAndSpecializePost(int pid, String appDataDir, String niceName) { - if (pid == 0) { - Utils.logD(forkAndSpecializePramsStr + " = " + Process.myPid()); - if (ConfigManager.isBlackWhiteListEnabled()) { - BlackWhiteListProxy.forkAndSpecializePost(pid, appDataDir, niceName); - } else { - NormalProxy.forkAndSpecializePost(pid, appDataDir, niceName); - } - } 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 - } - } - - public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, - 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 (ConfigManager.isBlackWhiteListEnabled()) { - BlackWhiteListProxy.forkSystemServerPre(uid, gid, gids, debugFlags, rlimits, - permittedCapabilities, effectiveCapabilities); - } else { - NormalProxy.forkSystemServerPre(uid, gid, gids, debugFlags, rlimits, - permittedCapabilities, effectiveCapabilities); - } - } - - public static void forkSystemServerPost(int pid) { - if (pid == 0) { - Utils.logD(forkSystemServerPramsStr + " = " + Process.myPid()); - if (ConfigManager.isBlackWhiteListEnabled()) { - BlackWhiteListProxy.forkSystemServerPost(pid); - } else { - NormalProxy.forkSystemServerPost(pid); - } - } 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 - } - } - -} diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/_hooker/HandleBindAppHooker.java b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/_hooker/HandleBindAppHooker.java deleted file mode 100644 index 7d71512e..00000000 --- a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/_hooker/HandleBindAppHooker.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.elderdrivers.riru.edxp.yahfa._hooker; - -import android.app.ActivityThread; -import android.app.LoadedApk; -import android.content.ComponentName; -import android.content.pm.ApplicationInfo; -import android.content.res.CompatibilityInfo; - -import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp.Main; -import com.elderdrivers.riru.edxp.hooker.SliceProviderFix; -import com.elderdrivers.riru.edxp.hooker.XposedBlackListHooker; -import com.elderdrivers.riru.edxp.hooker.XposedInstallerHooker; -import com.elderdrivers.riru.edxp.util.Utils; -import com.elderdrivers.riru.edxp.yahfa.entry.Router; - -import de.robv.android.xposed.XposedBridge; -import de.robv.android.xposed.XposedHelpers; -import de.robv.android.xposed.XposedInit; -import de.robv.android.xposed.callbacks.XC_LoadPackage; - -import static com.elderdrivers.riru.edxp.config.InstallerChooser.INSTALLER_PACKAGE_NAME; -import static com.elderdrivers.riru.edxp.hooker.SliceProviderFix.SYSTEMUI_PACKAGE_NAME; -import static com.elderdrivers.riru.edxp.hooker.XposedBlackListHooker.BLACK_LIST_PACKAGE_NAME; -import static com.elderdrivers.riru.edxp.util.ClassLoaderUtils.replaceParentClassLoader; - -// normal process initialization (for new Activity, Service, BroadcastReceiver etc.) -public class HandleBindAppHooker implements KeepMembers { - - public static String className = "android.app.ActivityThread"; - public static String methodName = "handleBindApplication"; - public static String methodSig = "(Landroid/app/ActivityThread$AppBindData;)V"; - - public static void hook(Object thiz, Object bindData) { - if (XposedBlackListHooker.shouldDisableHooks("")) { - backup(thiz, bindData); - return; - } - try { - Router.logD("ActivityThread#handleBindApplication() starts"); - ActivityThread activityThread = (ActivityThread) thiz; - ApplicationInfo appInfo = (ApplicationInfo) XposedHelpers.getObjectField(bindData, "appInfo"); - // save app process name here for later use - Main.appProcessName = (String) XposedHelpers.getObjectField(bindData, "processName"); - String reportedPackageName = appInfo.packageName.equals("android") ? "system" : appInfo.packageName; - Utils.logD("processName=" + Main.appProcessName + - ", packageName=" + reportedPackageName + ", appDataDir=" + Main.appDataDir); - - if (XposedBlackListHooker.shouldDisableHooks(reportedPackageName)) { - return; - } - - ComponentName instrumentationName = (ComponentName) XposedHelpers.getObjectField(bindData, "instrumentationName"); - if (instrumentationName != null) { - Router.logD("Instrumentation detected, disabling framework for"); - XposedBridge.disableHooks = true; - return; - } - CompatibilityInfo compatInfo = (CompatibilityInfo) XposedHelpers.getObjectField(bindData, "compatInfo"); - if (appInfo.sourceDir == null) { - return; - } - - XposedHelpers.setObjectField(activityThread, "mBoundApplication", bindData); - XposedInit.loadedPackagesInProcess.add(reportedPackageName); - LoadedApk loadedApk = activityThread.getPackageInfoNoCheck(appInfo, compatInfo); - - replaceParentClassLoader(loadedApk.getClassLoader()); - - XC_LoadPackage.LoadPackageParam lpparam = new XC_LoadPackage.LoadPackageParam(XposedBridge.sLoadedPackageCallbacks); - lpparam.packageName = reportedPackageName; - lpparam.processName = (String) XposedHelpers.getObjectField(bindData, "processName"); - lpparam.classLoader = loadedApk.getClassLoader(); - lpparam.appInfo = appInfo; - lpparam.isFirstApplication = true; - XC_LoadPackage.callAll(lpparam); - - if (reportedPackageName.equals(INSTALLER_PACKAGE_NAME)) { - XposedInstallerHooker.hookXposedInstaller(lpparam.classLoader); - } - if (reportedPackageName.equals(BLACK_LIST_PACKAGE_NAME)) { - XposedBlackListHooker.hook(lpparam.classLoader); - } - if (reportedPackageName.equals(SYSTEMUI_PACKAGE_NAME)) { - SliceProviderFix.hook(); - } - } catch (Throwable t) { - Router.logE("error when hooking bindApp", t); - } finally { - backup(thiz, bindData); - } - } - - public static void backup(Object thiz, Object bindData) { - } -} \ No newline at end of file diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/_hooker/LoadedApkConstructorHooker.java b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/_hooker/LoadedApkConstructorHooker.java deleted file mode 100644 index e3a55710..00000000 --- a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/_hooker/LoadedApkConstructorHooker.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.elderdrivers.riru.edxp.yahfa._hooker; - -import android.app.ActivityThread; -import android.app.AndroidAppHelper; -import android.app.LoadedApk; -import android.content.pm.ApplicationInfo; -import android.content.res.CompatibilityInfo; -import android.util.Log; - -import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp.hooker.XposedBlackListHooker; -import com.elderdrivers.riru.edxp.yahfa.entry.Router; - -import de.robv.android.xposed.XposedBridge; -import de.robv.android.xposed.XposedHelpers; -import de.robv.android.xposed.XposedInit; -import de.robv.android.xposed.callbacks.XC_LoadPackage; - -import static com.elderdrivers.riru.edxp.util.ClassLoaderUtils.replaceParentClassLoader; - -// when a package is loaded for an existing process, trigger the callbacks as well -// ed: remove resources related hooking -public class LoadedApkConstructorHooker implements KeepMembers { - public static String className = "android.app.LoadedApk"; - public static String methodName = ""; - public static String methodSig = "(Landroid/app/ActivityThread;" + - "Landroid/content/pm/ApplicationInfo;" + - "Landroid/content/res/CompatibilityInfo;" + - "Ljava/lang/ClassLoader;ZZZ)V"; - - public static void hook(Object thiz, ActivityThread activityThread, - ApplicationInfo aInfo, CompatibilityInfo compatInfo, - ClassLoader baseLoader, boolean securityViolation, - boolean includeCode, boolean registerPackage) { - - if (XposedBlackListHooker.shouldDisableHooks("")) { - backup(thiz, activityThread, aInfo, compatInfo, baseLoader, securityViolation, - includeCode, registerPackage); - return; - } - - Router.logD("LoadedApk# starts"); - backup(thiz, activityThread, aInfo, compatInfo, baseLoader, securityViolation, - includeCode, registerPackage); - - try { - LoadedApk loadedApk = (LoadedApk) thiz; - String packageName = loadedApk.getPackageName(); - Object mAppDir = XposedHelpers.getObjectField(thiz, "mAppDir"); - Router.logD("LoadedApk# ends: " + mAppDir); - - if (XposedBlackListHooker.shouldDisableHooks(packageName)) { - return; - } - - if (packageName.equals("android")) { - Router.logD("LoadedApk# is android, skip: " + mAppDir); - return; - } - - // mIncludeCode checking should go ahead of loadedPackagesInProcess added checking - if (!XposedHelpers.getBooleanField(loadedApk, "mIncludeCode")) { - Router.logD("LoadedApk# mIncludeCode == false: " + mAppDir); - return; - } - - if (!XposedInit.loadedPackagesInProcess.add(packageName)) { - Router.logD("LoadedApk# has been loaded before, skip: " + mAppDir); - return; - } - - // OnePlus magic... - if (Log.getStackTraceString(new Throwable()). - contains("android.app.ActivityThread$ApplicationThread.schedulePreload")) { - Router.logD("LoadedApk# maybe oneplus's custom opt, skip"); - return; - } - - replaceParentClassLoader(loadedApk.getClassLoader()); - - XC_LoadPackage.LoadPackageParam lpparam = new XC_LoadPackage.LoadPackageParam(XposedBridge.sLoadedPackageCallbacks); - lpparam.packageName = packageName; - lpparam.processName = AndroidAppHelper.currentProcessName(); - lpparam.classLoader = loadedApk.getClassLoader(); - lpparam.appInfo = loadedApk.getApplicationInfo(); - lpparam.isFirstApplication = false; - XC_LoadPackage.callAll(lpparam); - } catch (Throwable t) { - Router.logE("error when hooking LoadedApk.", t); - } - } - - public static void backup(Object thiz, ActivityThread activityThread, - ApplicationInfo aInfo, CompatibilityInfo compatInfo, - ClassLoader baseLoader, boolean securityViolation, - boolean includeCode, boolean registerPackage) { - - } -} \ No newline at end of file diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/_hooker/SystemMainHooker.java b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/_hooker/SystemMainHooker.java deleted file mode 100644 index a41423be..00000000 --- a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/_hooker/SystemMainHooker.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.elderdrivers.riru.edxp.yahfa._hooker; - -import android.app.ActivityThread; - -import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp.deopt.PrebuiltMethodsDeopter; -import com.elderdrivers.riru.edxp.yahfa.entry.Router; - -import de.robv.android.xposed.XposedBridge; - - -// system_server initialization -// ed: only support sdk >= 21 for now -public class SystemMainHooker implements KeepMembers { - - public static String className = "android.app.ActivityThread"; - public static String methodName = "systemMain"; - public static String methodSig = "()Landroid/app/ActivityThread;"; - - public static ClassLoader systemServerCL; - - public static ActivityThread hook() { - if (XposedBridge.disableHooks) { - return backup(); - } - Router.logD("ActivityThread#systemMain() starts"); - ActivityThread activityThread = backup(); - try { - // get system_server classLoader - systemServerCL = Thread.currentThread().getContextClassLoader(); - // deopt methods in SYSTEMSERVERCLASSPATH - PrebuiltMethodsDeopter.deoptSystemServerMethods(systemServerCL); - Router.startSystemServerHook(); - } catch (Throwable t) { - Router.logE("error when hooking systemMain", t); - } - return activityThread; - } - - public static ActivityThread backup() { - return null; - } -} \ No newline at end of file diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/config/YahfaEdxpConfig.java b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/config/YahfaEdxpConfig.java index 308fccc4..8ea68550 100644 --- a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/config/YahfaEdxpConfig.java +++ b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/config/YahfaEdxpConfig.java @@ -1,6 +1,5 @@ package com.elderdrivers.riru.edxp.yahfa.config; -import com.elderdrivers.riru.edxp.Main; import com.elderdrivers.riru.edxp.config.ConfigManager; import com.elderdrivers.riru.edxp.config.EdXpConfig; import com.elderdrivers.riru.edxp.config.InstallerChooser; diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/core/HookMethodResolver.java b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/core/HookMethodResolver.java deleted file mode 100644 index 49b9edb3..00000000 --- a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/core/HookMethodResolver.java +++ /dev/null @@ -1,156 +0,0 @@ -package com.elderdrivers.riru.edxp.yahfa.core; - -import android.os.Build; - -import com.elderdrivers.riru.edxp.Main; -import com.elderdrivers.riru.edxp.core.Yahfa; -import com.elderdrivers.riru.edxp.util.Utils; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; - -/** - * create by Swift Gan on 14/01/2019 - * To ensure method in resolved cache - */ - -public class HookMethodResolver { - - public static Class artMethodClass; - - public static Field resolvedMethodsField; - public static Field dexCacheField; - public static Field dexMethodIndexField; - public static Field artMethodField; - - public static boolean canResolvedInJava = false; - public static boolean isArtMethod = false; - - public static long resolvedMethodsAddress = 0; - public static int dexMethodIndex = 0; - - public static Method testMethod; - public static Object testArtMethod; - - public static void init() { - checkSupport(); - } - - private static void checkSupport() { - try { - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - isArtMethod = false; - canResolvedInJava = false; - return; - } - - testMethod = HookMethodResolver.class.getDeclaredMethod("init"); - artMethodField = getField(Method.class, "artMethod"); - - testArtMethod = artMethodField.get(testMethod); - - if (hasJavaArtMethod() && testArtMethod.getClass() == artMethodClass) { - checkSupportForArtMethod(); - isArtMethod = true; - } else if (testArtMethod instanceof Long) { - checkSupportForArtMethodId(); - isArtMethod = false; - } else { - canResolvedInJava = false; - } - - } catch (Throwable throwable) { - Utils.logE("error when checkSupport", throwable); - } - } - - // may 5.0 - private static void checkSupportForArtMethod() throws Exception { - dexMethodIndexField = getField(artMethodClass, "dexMethodIndex"); - dexCacheField = getField(Class.class, "dexCache"); - Object dexCache = dexCacheField.get(testMethod.getDeclaringClass()); - resolvedMethodsField = getField(dexCache.getClass(), "resolvedMethods"); - if (resolvedMethodsField.get(dexCache) instanceof Object[]) { - canResolvedInJava = true; - } - } - - // may 6.0 - private static void checkSupportForArtMethodId() throws Exception { - dexMethodIndexField = getField(Method.class, "dexMethodIndex"); - dexMethodIndex = (int) dexMethodIndexField.get(testMethod); - dexCacheField = getField(Class.class, "dexCache"); - Object dexCache = dexCacheField.get(testMethod.getDeclaringClass()); - resolvedMethodsField = getField(dexCache.getClass(), "resolvedMethods"); - Object resolvedMethods = resolvedMethodsField.get(dexCache); - if (resolvedMethods instanceof Long) { - canResolvedInJava = false; - resolvedMethodsAddress = (long) resolvedMethods; - } else if (resolvedMethods instanceof long[]) { - canResolvedInJava = true; - } - } - - public static void resolveMethod(Method hook, Method backup) { - if (canResolvedInJava && artMethodField != null) { - // in java - try { - resolveInJava(hook, backup); - } catch (Exception e) { - // in native - resolveInNative(hook, backup); - } - } else { - // in native - resolveInNative(hook, backup); - } - } - - private static void resolveInJava(Method hook, Method backup) throws Exception { - Object dexCache = dexCacheField.get(hook.getDeclaringClass()); - if (isArtMethod) { - Object artMethod = artMethodField.get(backup); - int dexMethodIndex = (int) dexMethodIndexField.get(artMethod); - Object resolvedMethods = resolvedMethodsField.get(dexCache); - ((Object[])resolvedMethods)[dexMethodIndex] = artMethod; - } else { - int dexMethodIndex = (int) dexMethodIndexField.get(backup); - Object resolvedMethods = resolvedMethodsField.get(dexCache); - long artMethod = (long) artMethodField.get(backup); - ((long[])resolvedMethods)[dexMethodIndex] = artMethod; - } - } - - private static void resolveInNative(Method hook, Method backup) { - Yahfa.ensureMethodCached(hook, backup); - } - - public static Field getField(Class topClass, String fieldName) throws NoSuchFieldException { - while (topClass != null && topClass != Object.class) { - try { - Field field = topClass.getDeclaredField(fieldName); - field.setAccessible(true); - return field; - } catch (Exception e) { - } - topClass = topClass.getSuperclass(); - } - throw new NoSuchFieldException(fieldName); - } - - public static boolean hasJavaArtMethod() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - return false; - } - if (artMethodClass != null) - return true; - try { - artMethodClass = Class.forName("java.lang.reflect.ArtMethod"); - return true; - } catch (ClassNotFoundException e) { - return false; - } - } - -} \ No newline at end of file diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/core/YahfaEdxpImpl.java b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/core/YahfaEdxpImpl.java new file mode 100644 index 00000000..da225aa7 --- /dev/null +++ b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/core/YahfaEdxpImpl.java @@ -0,0 +1,56 @@ +package com.elderdrivers.riru.edxp.yahfa.core; + +import android.os.Build; + +import com.elderdrivers.riru.edxp.config.ConfigManager; +import com.elderdrivers.riru.edxp.config.InstallerChooser; +import com.elderdrivers.riru.edxp.core.BaseEdxpImpl; +import com.elderdrivers.riru.edxp.core.EdxpImpl; +import com.elderdrivers.riru.edxp.core.Main; +import com.elderdrivers.riru.edxp.core.Proxy; +import com.elderdrivers.riru.edxp.core.Yahfa; +import com.elderdrivers.riru.edxp.core.yahfa.HookMethodResolver; +import com.elderdrivers.riru.edxp.proxy.BlackWhiteListProxy; +import com.elderdrivers.riru.edxp.proxy.NormalProxy; +import com.elderdrivers.riru.edxp.proxy.Router; + +public class YahfaEdxpImpl extends BaseEdxpImpl { + + static { + final EdxpImpl edxpImpl = new YahfaEdxpImpl(); + if (Main.setEdxpImpl(edxpImpl)) { + edxpImpl.init(); + } + } + + @Variant + @Override + public int getVariant() { + return YAHFA; + } + + @Override + public void init() { + Yahfa.init(Build.VERSION.SDK_INT); + HookMethodResolver.init(); + getRouter().injectConfig(); + InstallerChooser.setInstallerPackageName(ConfigManager.getInstallerPackageName()); + + setInitialized(); + } + + @Override + protected Proxy createBlackWhiteListProxy() { + return new BlackWhiteListProxy(getRouter()); + } + + @Override + protected Proxy createNormalProxy() { + return new NormalProxy(getRouter()); + } + + @Override + protected Router createRouter() { + return new YahfaRouter(); + } +} diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/core/YahfaRouter.java b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/core/YahfaRouter.java new file mode 100644 index 00000000..08c88fe4 --- /dev/null +++ b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/core/YahfaRouter.java @@ -0,0 +1,23 @@ +package com.elderdrivers.riru.edxp.yahfa.core; + +import com.elderdrivers.riru.edxp.config.EdXpConfigGlobal; +import com.elderdrivers.riru.edxp.proxy.BaseRouter; +import com.elderdrivers.riru.edxp.yahfa.config.YahfaEdxpConfig; +import com.elderdrivers.riru.edxp.yahfa.config.YahfaHookProvider; +import com.elderdrivers.riru.edxp.yahfa.dexmaker.DynamicBridge; + +import de.robv.android.xposed.XposedBridge; + +public class YahfaRouter extends BaseRouter { + + public void onEnterChildProcess() { + DynamicBridge.onForkPost(); + } + + public void injectConfig() { + EdXpConfigGlobal.sConfig = new YahfaEdxpConfig(); + EdXpConfigGlobal.sHookProvider = new YahfaHookProvider(); + XposedBridge.log("using HookProvider: " + EdXpConfigGlobal.sHookProvider.getClass().getName()); + } + +} diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/dexmaker/DexMakerUtils.java b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/dexmaker/DexMakerUtils.java index 7ca85d47..8d18a1e9 100644 --- a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/dexmaker/DexMakerUtils.java +++ b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/dexmaker/DexMakerUtils.java @@ -4,9 +4,8 @@ import android.app.AndroidAppHelper; import android.os.Build; import android.text.TextUtils; -import com.elderdrivers.riru.edxp.Main; import com.elderdrivers.riru.edxp.config.ConfigManager; -import com.elderdrivers.riru.edxp.yahfa.core.HookMain; +import com.elderdrivers.riru.edxp.core.yahfa.HookMain; import java.lang.reflect.Member; import java.security.MessageDigest; @@ -27,8 +26,8 @@ public class DexMakerUtils { } String packageName = AndroidAppHelper.currentPackageName(); if (TextUtils.isEmpty(packageName)) { //default to true - DexLog.w("packageName is empty, processName=" + Main.appProcessName - + ", appDataDir=" + Main.appDataDir); + DexLog.w("packageName is empty, processName=" + ConfigManager.appProcessName + + ", appDataDir=" + ConfigManager.appDataDir); return true; } return !ConfigManager.shouldUseCompatMode(packageName); diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/dexmaker/DynamicBridge.java b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/dexmaker/DynamicBridge.java index b998a29e..3287ab4f 100644 --- a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/dexmaker/DynamicBridge.java +++ b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/dexmaker/DynamicBridge.java @@ -1,6 +1,7 @@ package com.elderdrivers.riru.edxp.yahfa.dexmaker; -import com.elderdrivers.riru.edxp.Main; + +import com.elderdrivers.riru.edxp.config.ConfigManager; import java.io.File; import java.lang.reflect.Constructor; @@ -13,10 +14,10 @@ import java.util.concurrent.atomic.AtomicBoolean; import de.robv.android.xposed.XposedBridge; -import static com.elderdrivers.riru.edxp.yahfa.dexmaker.DexMakerUtils.shouldUseInMemoryHook; import static com.elderdrivers.riru.edxp.util.FileUtils.getDataPathPrefix; import static com.elderdrivers.riru.edxp.util.FileUtils.getPackageName; import static com.elderdrivers.riru.edxp.util.ProcessUtils.getCurrentProcessName; +import static com.elderdrivers.riru.edxp.yahfa.dexmaker.DexMakerUtils.shouldUseInMemoryHook; public final class DynamicBridge { @@ -74,12 +75,12 @@ public final class DynamicBridge { try { // we always choose to use device encrypted storage data on android N and later // in case some app is installing hooks before phone is unlocked - String fixedAppDataDir = getDataPathPrefix() + getPackageName(Main.appDataDir) + "/"; + String fixedAppDataDir = getDataPathPrefix() + getPackageName(ConfigManager.appDataDir) + "/"; dexDir = new File(fixedAppDataDir, "/cache/edhookers/" - + getCurrentProcessName(Main.appProcessName).replace(":", "_") + "/"); + + getCurrentProcessName(ConfigManager.appProcessName).replace(":", "_") + "/"); dexOptDir = new File(dexDir, "oat"); dexDir.mkdirs(); - DexLog.d(Main.appProcessName + " deleting dir: " + dexOptDir.getAbsolutePath()); + DexLog.d(ConfigManager.appProcessName + " deleting dir: " + dexOptDir.getAbsolutePath()); } catch (Throwable throwable) { DexLog.e("error when init dex path", throwable); } diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/dexmaker/HookerDexMaker.java b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/dexmaker/HookerDexMaker.java index ee731009..e0f1a42b 100644 --- a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/dexmaker/HookerDexMaker.java +++ b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/dexmaker/HookerDexMaker.java @@ -4,9 +4,8 @@ import android.annotation.TargetApi; import android.os.Build; import android.text.TextUtils; -import com.elderdrivers.riru.edxp.Main; import com.elderdrivers.riru.edxp.core.Yahfa; -import com.elderdrivers.riru.edxp.yahfa.core.HookMain; +import com.elderdrivers.riru.edxp.core.yahfa.HookMain; import java.io.File; import java.lang.reflect.Constructor; diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/entry/Router.java b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/entry/Router.java deleted file mode 100644 index c1b6aa03..00000000 --- a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/entry/Router.java +++ /dev/null @@ -1,135 +0,0 @@ -package com.elderdrivers.riru.edxp.yahfa.entry; - -import android.app.AndroidAppHelper; -import android.text.TextUtils; - -import com.elderdrivers.riru.edxp.config.EdXpConfigGlobal; -import com.elderdrivers.riru.edxp.util.Utils; -import com.elderdrivers.riru.edxp.yahfa.config.YahfaEdxpConfig; -import com.elderdrivers.riru.edxp.yahfa.config.YahfaHookProvider; -import com.elderdrivers.riru.edxp.yahfa.core.HookMain; -import com.elderdrivers.riru.edxp.yahfa.dexmaker.DynamicBridge; -import com.elderdrivers.riru.edxp.yahfa.entry.bootstrap.AppBootstrapHookInfo; -import com.elderdrivers.riru.edxp.yahfa.entry.bootstrap.SysBootstrapHookInfo; -import com.elderdrivers.riru.edxp.yahfa.entry.bootstrap.SysInnerHookInfo; -import com.elderdrivers.riru.edxp.yahfa.entry.bootstrap.WorkAroundHookInfo; -import com.elderdrivers.riru.edxp.yahfa._hooker.SystemMainHooker; - -import java.util.concurrent.atomic.AtomicBoolean; - -import de.robv.android.xposed.XposedBridge; -import de.robv.android.xposed.XposedInit; - -public class Router { - - public volatile static boolean forkCompleted = false; - - private static volatile AtomicBoolean bootstrapHooked = new AtomicBoolean(false); - - public static void initResourcesHook() { - startWorkAroundHook(); // for OnePlus devices - XposedBridge.initXResources(); - } - - public static void prepare(boolean isSystem) { - // this flag is needed when loadModules - XposedInit.startsSystemServer = isSystem; - } - - public static void checkHookState(String appDataDir) { - // determine whether allow xposed or not -// XposedBridge.disableHooks = ConfigManager.shouldHook(parsePackageName(appDataDir)); - } - - private static String parsePackageName(String appDataDir) { - if (TextUtils.isEmpty(appDataDir)) { - return ""; - } - int lastIndex = appDataDir.lastIndexOf("/"); - if (lastIndex < 1) { - return ""; - } - return appDataDir.substring(lastIndex + 1); - } - - public static void installBootstrapHooks(boolean isSystem) { - // Initialize the Xposed framework - try { - if (!bootstrapHooked.compareAndSet(false, true)) { - return; - } - Router.startBootstrapHook(isSystem); - XposedInit.initForZygote(isSystem); - } catch (Throwable t) { - Utils.logE("error during Xposed initialization", t); - XposedBridge.disableHooks = true; - } - } - - public static void loadModulesSafely(boolean isInZygote) { - try { - // FIXME some coredomain app can't reading modules.list - XposedInit.loadModules(isInZygote); - } catch (Exception exception) { - Utils.logE("error loading module list", exception); - } - } - - public static void startBootstrapHook(boolean isSystem) { - Utils.logD("startBootstrapHook starts: isSystem = " + isSystem); - ClassLoader classLoader = XposedBridge.BOOTCLASSLOADER; - if (isSystem) { - HookMain.doHookDefault( - Router.class.getClassLoader(), - classLoader, - SysBootstrapHookInfo.class.getName()); - } else { - HookMain.doHookDefault( - Router.class.getClassLoader(), - classLoader, - AppBootstrapHookInfo.class.getName()); - } - } - - public static void startSystemServerHook() { - HookMain.doHookDefault( - Router.class.getClassLoader(), - SystemMainHooker.systemServerCL, - SysInnerHookInfo.class.getName()); - } - - public static void startWorkAroundHook() { - HookMain.doHookDefault( - Router.class.getClassLoader(), - XposedBridge.BOOTCLASSLOADER, - WorkAroundHookInfo.class.getName()); - } - - public static void onForkStart() { - forkCompleted = false; - } - - public static void onForkFinish() { - forkCompleted = true; - } - - public static void onEnterChildProcess() { - DynamicBridge.onForkPost(); - } - - public static void logD(String prefix) { - Utils.logD(String.format("%s: pkg=%s, prc=%s", prefix, AndroidAppHelper.currentPackageName(), - AndroidAppHelper.currentProcessName())); - } - - public static void logE(String prefix, Throwable throwable) { - Utils.logE(String.format("%s: pkg=%s, prc=%s", prefix, AndroidAppHelper.currentPackageName(), - AndroidAppHelper.currentProcessName()), throwable); - } - - public static void injectConfig() { - EdXpConfigGlobal.sConfig = new YahfaEdxpConfig(); - EdXpConfigGlobal.sHookProvider = new YahfaHookProvider(); - XposedBridge.log("using HookProvider: " + EdXpConfigGlobal.sHookProvider.getClass().getName()); - } -} diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/entry/bootstrap/AppBootstrapHookInfo.java b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/entry/bootstrap/AppBootstrapHookInfo.java deleted file mode 100644 index f15f542f..00000000 --- a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/entry/bootstrap/AppBootstrapHookInfo.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.elderdrivers.riru.edxp.yahfa.entry.bootstrap; - -import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp.yahfa._hooker.HandleBindAppHooker; -import com.elderdrivers.riru.edxp.yahfa._hooker.LoadedApkConstructorHooker; -import com.elderdrivers.riru.edxp.yahfa._hooker.OnePlusWorkAroundHooker; - -public class AppBootstrapHookInfo implements KeepMembers { - public static String[] hookItemNames = { - HandleBindAppHooker.class.getName(), - LoadedApkConstructorHooker.class.getName(), - OnePlusWorkAroundHooker.class.getName() - }; -} diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/entry/bootstrap/WorkAroundHookInfo.java b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/entry/bootstrap/WorkAroundHookInfo.java deleted file mode 100644 index 650dda8e..00000000 --- a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/entry/bootstrap/WorkAroundHookInfo.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.elderdrivers.riru.edxp.yahfa.entry.bootstrap; - -import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp.yahfa._hooker.OnePlusWorkAroundHooker; - -public class WorkAroundHookInfo implements KeepMembers { - public static String[] hookItemNames = { - OnePlusWorkAroundHooker.class.getName() - }; -} diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/proxy/BlackWhiteListProxy.java b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/proxy/BlackWhiteListProxy.java deleted file mode 100644 index 680fed3f..00000000 --- a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/proxy/BlackWhiteListProxy.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.elderdrivers.riru.edxp.yahfa.proxy; - -import android.text.TextUtils; - -import com.elderdrivers.riru.edxp.Main; -import com.elderdrivers.riru.edxp.config.ConfigManager; -import com.elderdrivers.riru.edxp.deopt.PrebuiltMethodsDeopter; -import com.elderdrivers.riru.edxp.framework.Zygote; -import com.elderdrivers.riru.edxp.util.ProcessUtils; -import com.elderdrivers.riru.edxp.util.Utils; -import com.elderdrivers.riru.edxp.yahfa.entry.Router; - -import de.robv.android.xposed.XposedBridge; - -import static com.elderdrivers.riru.edxp.util.FileUtils.getDataPathPrefix; - -/** - * 1. Non dynamic mode - * - system_server is whitelisted - * * for all child processes of main zygote - * What've been done in main zygote pre-forking system_server - * 1) non dynamic flag set (no need to reset) - * 2) boot image methods deopted (no need to redo) - * 3) startSystemServer flag set to true (need to reset) - * 4) workaround hooks installed (need to redo) - * 5) module list loaded and initZygote called (no need to redo) - * 6) close all fds (no need to redo because of 5)) - * * for all child processes of secondary zygote - * 1) do the same things pre-forking first child process - * - system_server is blacklisted: - * * for all child processes of both main zygote and secondary zygote - * 1) do the same things pre-forking first child process - * 2. Dynamic mode: - * to be continued - */ -public class BlackWhiteListProxy { - - public static void forkAndSpecializePre(int uid, int gid, int[] gids, int debugFlags, - int[][] rlimits, int mountExternal, String seInfo, - String niceName, int[] fdsToClose, int[] fdsToIgnore, - boolean startChildZygote, String instructionSet, - String appDataDir) { - final boolean isDynamicModulesMode = ConfigManager.isDynamicModulesEnabled(); - if (isDynamicModulesMode) { - // should never happen - return; - } - // only enter here when isDynamicModulesMode is off - onForkPreForNonDynamicMode(false); - } - - public static void forkAndSpecializePost(int pid, String appDataDir, String niceName) { - onForkPostCommon(false, appDataDir, niceName); - } - - public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, - int[][] rlimits, long permittedCapabilities, - long effectiveCapabilities) { - final boolean isDynamicModulesMode = ConfigManager.isDynamicModulesEnabled(); - if (isDynamicModulesMode) { - // should never happen - return; - } - // only enter here when isDynamicModulesMode is off - onForkPreForNonDynamicMode(true); - } - - public static void forkSystemServerPost(int pid) { - onForkPostCommon(true, getDataPathPrefix() + "android", "system_server"); - } - - /** - * Some details are different between main zygote and secondary zygote. - */ - private static void onForkPreForNonDynamicMode(boolean isSystemServer) { - Router.onForkStart(); - Router.initResourcesHook(); - // set startsSystemServer flag used when loadModules - Router.prepare(isSystemServer); - // deoptBootMethods once for all child processes of zygote - PrebuiltMethodsDeopter.deoptBootMethods(); - // we never install bootstrap hooks here in black/white list mode except workaround hooks - // because installed hooks would be propagated to all child processes of zygote - Router.startWorkAroundHook(); - // loadModules once for all child processes of zygote - // TODO maybe just save initZygote callbacks and call them when whitelisted process forked? - Router.loadModulesSafely(true); - Zygote.closeFilesBeforeFork(); - } - - private static void onForkPostCommon(boolean isSystemServer, String appDataDir, String niceName) { - Main.appDataDir = appDataDir; - Main.niceName = niceName; - final boolean isDynamicModulesMode = ConfigManager.isDynamicModulesEnabled(); - if (!isDynamicModulesMode) { - Zygote.reopenFilesAfterFork(); - } - Router.onEnterChildProcess(); - if (!checkNeedHook(appDataDir, niceName)) { - // if is blacklisted, just stop here - Router.onForkFinish(); - return; - } - if (isDynamicModulesMode) { - Router.initResourcesHook(); - } - Router.prepare(isSystemServer); - PrebuiltMethodsDeopter.deoptBootMethods(); - Router.installBootstrapHooks(isSystemServer); - if (isDynamicModulesMode) { - Router.loadModulesSafely(false); - } - Router.onForkFinish(); - } - - private static boolean checkNeedHook(String appDataDir, String niceName) { - boolean needHook; - if (TextUtils.isEmpty(appDataDir)) { - Utils.logE("niceName:" + niceName + ", procName:" - + ProcessUtils.getCurrentProcessName(Main.appProcessName) + ", appDataDir is null, blacklisted!"); - needHook = false; - } else { - // FIXME some process cannot read app_data_file because of MLS, e.g. bluetooth - needHook = ConfigManager.isAppNeedHook(appDataDir); - } - if (!needHook) { - // clean up the scene - onBlackListed(); - } - return needHook; - } - - private static void onBlackListed() { - XposedBridge.clearLoadedPackages(); - XposedBridge.clearInitPackageResources(); - } -} diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/proxy/NormalProxy.java b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/proxy/NormalProxy.java deleted file mode 100644 index 9b108e42..00000000 --- a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/proxy/NormalProxy.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.elderdrivers.riru.edxp.yahfa.proxy; - -import com.elderdrivers.riru.edxp.Main; -import com.elderdrivers.riru.edxp.deopt.PrebuiltMethodsDeopter; -import com.elderdrivers.riru.edxp.framework.Zygote; -import com.elderdrivers.riru.edxp.yahfa.entry.Router; - -import static com.elderdrivers.riru.edxp.util.FileUtils.getDataPathPrefix; - -public class NormalProxy { - - public static void forkAndSpecializePre(int uid, int gid, int[] gids, int debugFlags, - int[][] rlimits, int mountExternal, String seInfo, - String niceName, int[] fdsToClose, int[] fdsToIgnore, - boolean startChildZygote, String instructionSet, - String appDataDir) { - // mainly for secondary zygote - Router.onForkStart(); - Router.initResourcesHook(); - // call this to ensure the flag is set to false ASAP - Router.prepare(false); - PrebuiltMethodsDeopter.deoptBootMethods(); // do it once for secondary zygote - // install bootstrap hooks for secondary zygote - Router.installBootstrapHooks(false); - // only load modules for secondary zygote - Router.loadModulesSafely(true); - Zygote.closeFilesBeforeFork(); - } - - public static void forkAndSpecializePost(int pid, String appDataDir, String niceName) { - // TODO consider processes without forkAndSpecializePost called - Main.appDataDir = appDataDir; - Main.niceName = niceName; - Router.prepare(false); - Zygote.reopenFilesAfterFork(); - Router.onEnterChildProcess(); - // load modules for each app process on its forked if dynamic modules mode is on - Router.loadModulesSafely(false); - Router.onForkFinish(); - } - - public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, - long permittedCapabilities, long effectiveCapabilities) { - Router.onForkStart(); - Router.initResourcesHook(); - // set startsSystemServer flag used when loadModules - 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 - Router.installBootstrapHooks(true); - // loadModules have to be executed in zygote even isDynamicModules is false - // because if not global hooks installed in initZygote might not be - // propagated to processes not forked via forkAndSpecialize - Router.loadModulesSafely(true); - Zygote.closeFilesBeforeFork(); - } - - public static void forkSystemServerPost(int pid) { - // in system_server process - Main.appDataDir = getDataPathPrefix() + "android"; - Main.niceName = "system_server"; - Router.prepare(true); - Zygote.reopenFilesAfterFork(); - Router.onEnterChildProcess(); - // reload module list if dynamic mode is on - Router.loadModulesSafely(false); - Router.onForkFinish(); - } - -} diff --git a/edxp-yahfa/src/main/resources/META-INF/services/com.elderdrivers.riru.edxp.core.EdxpImpl b/edxp-yahfa/src/main/resources/META-INF/services/com.elderdrivers.riru.edxp.core.EdxpImpl new file mode 100644 index 00000000..3d3af179 --- /dev/null +++ b/edxp-yahfa/src/main/resources/META-INF/services/com.elderdrivers.riru.edxp.core.EdxpImpl @@ -0,0 +1 @@ +com.elderdrivers.riru.edxp.yahfa.core.YahfaEdxpImpl \ No newline at end of file