From 49c1da99db56d4087f81713d2bb54d7d84714049 Mon Sep 17 00:00:00 2001 From: Justin <40630518+Juxstin@users.noreply.github.com> Date: Tue, 4 Jun 2019 13:31:55 -0500 Subject: [PATCH 1/5] Fix Snapchat Detection Fix Snapchat Detection --- edxp-core/src/main/cpp/main/include/art/runtime/hidden_api.h | 3 ++- edxp-core/src/main/cpp/main/src/native_hook.cpp | 2 +- edxp-whale/src/main/java/com/lody/whale/WhaleRuntime.java | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/edxp-core/src/main/cpp/main/include/art/runtime/hidden_api.h b/edxp-core/src/main/cpp/main/include/art/runtime/hidden_api.h index ae6eddbf9..4b34e1cf4 100644 --- a/edxp-core/src/main/cpp/main/include/art/runtime/hidden_api.h +++ b/edxp-core/src/main/cpp/main/include/art/runtime/hidden_api.h @@ -22,6 +22,7 @@ namespace art { return Action::kAllow; } +/* static void DisableHiddenApi(void *handle, HookFunType hook_func) { if (GetAndroidApiLevel() < ANDROID_P) { return; @@ -33,7 +34,7 @@ namespace art { "_ZN3art9hiddenapi6detail19GetMemberActionImplINS_8ArtFieldEEENS0_" "6ActionEPT_NS_20HiddenApiAccessFlags7ApiListES4_NS0_12AccessMethodE"); }; - +*/ } } diff --git a/edxp-core/src/main/cpp/main/src/native_hook.cpp b/edxp-core/src/main/cpp/main/src/native_hook.cpp index a3d6d7900..a941ad39e 100644 --- a/edxp-core/src/main/cpp/main/src/native_hook.cpp +++ b/edxp-core/src/main/cpp/main/src/native_hook.cpp @@ -51,7 +51,7 @@ namespace edxp { if (!art_handle.IsValid()) { return; } - art::hidden_api::DisableHiddenApi(art_handle.Get(), hook_func); + /*art::hidden_api::DisableHiddenApi(art_handle.Get(), hook_func);*/ art::Runtime::Setup(art_handle.Get(), hook_func); art::gc::Heap::Setup(art_handle.Get(), hook_func); art::ClassLinker::Setup(art_handle.Get(), hook_func); diff --git a/edxp-whale/src/main/java/com/lody/whale/WhaleRuntime.java b/edxp-whale/src/main/java/com/lody/whale/WhaleRuntime.java index 2c0904e49..40160595d 100644 --- a/edxp-whale/src/main/java/com/lody/whale/WhaleRuntime.java +++ b/edxp-whale/src/main/java/com/lody/whale/WhaleRuntime.java @@ -66,7 +66,7 @@ public static native Object invokeOriginalMethodNative(long slot, Object thisObj public static native void removeFinalFlagNative(Class cl); - public static native void enforceDisableHiddenAPIPolicy(); + /* public static native void enforceDisableHiddenAPIPolicy(); */ private static native void reserved0(); From 5bad853fb35f738e177a6da04829e537c8e5e5a8 Mon Sep 17 00:00:00 2001 From: Justin <40630518+Juxstin@users.noreply.github.com> Date: Tue, 4 Jun 2019 14:14:55 -0500 Subject: [PATCH 2/5] Cleaned Up Shite For PR Cleaned Up Shite For PR --- .../src/main/cpp/main/include/art/runtime/hidden_api.h | 6 +++--- edxp-core/src/main/cpp/main/src/native_hook.cpp | 2 -- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/edxp-core/src/main/cpp/main/include/art/runtime/hidden_api.h b/edxp-core/src/main/cpp/main/include/art/runtime/hidden_api.h index 4b34e1cf4..f16065189 100644 --- a/edxp-core/src/main/cpp/main/include/art/runtime/hidden_api.h +++ b/edxp-core/src/main/cpp/main/include/art/runtime/hidden_api.h @@ -6,7 +6,7 @@ namespace art { namespace hidden_api { - + /* enum Action { kAllow, kAllowButWarn, @@ -22,7 +22,7 @@ namespace art { return Action::kAllow; } -/* + static void DisableHiddenApi(void *handle, HookFunType hook_func) { if (GetAndroidApiLevel() < ANDROID_P) { return; @@ -34,7 +34,7 @@ namespace art { "_ZN3art9hiddenapi6detail19GetMemberActionImplINS_8ArtFieldEEENS0_" "6ActionEPT_NS_20HiddenApiAccessFlags7ApiListES4_NS0_12AccessMethodE"); }; -*/ + */ } } diff --git a/edxp-core/src/main/cpp/main/src/native_hook.cpp b/edxp-core/src/main/cpp/main/src/native_hook.cpp index a941ad39e..83e991456 100644 --- a/edxp-core/src/main/cpp/main/src/native_hook.cpp +++ b/edxp-core/src/main/cpp/main/src/native_hook.cpp @@ -15,7 +15,6 @@ #include "art/runtime/mirror/class.h" #include "art/runtime/class_linker.h" #include "art/runtime/gc/heap.h" -#include "art/runtime/hidden_api.h" namespace edxp { @@ -51,7 +50,6 @@ namespace edxp { if (!art_handle.IsValid()) { return; } - /*art::hidden_api::DisableHiddenApi(art_handle.Get(), hook_func);*/ art::Runtime::Setup(art_handle.Get(), hook_func); art::gc::Heap::Setup(art_handle.Get(), hook_func); art::ClassLinker::Setup(art_handle.Get(), hook_func); From 8717489ffeaecef8f56eaa612dc30a2b31e77109 Mon Sep 17 00:00:00 2001 From: Justin <40630518+Juxstin@users.noreply.github.com> Date: Tue, 4 Jun 2019 14:16:47 -0500 Subject: [PATCH 3/5] Delete hidden_api.h --- .../cpp/main/include/art/runtime/hidden_api.h | 40 ------------------- 1 file changed, 40 deletions(-) delete mode 100644 edxp-core/src/main/cpp/main/include/art/runtime/hidden_api.h diff --git a/edxp-core/src/main/cpp/main/include/art/runtime/hidden_api.h b/edxp-core/src/main/cpp/main/include/art/runtime/hidden_api.h deleted file mode 100644 index f16065189..000000000 --- a/edxp-core/src/main/cpp/main/include/art/runtime/hidden_api.h +++ /dev/null @@ -1,40 +0,0 @@ - -#pragma once - -#include "base/object.h" - -namespace art { - - namespace hidden_api { - /* - enum Action { - kAllow, - kAllowButWarn, - kAllowButWarnAndToast, - kDeny - }; - - CREATE_HOOK_STUB_ENTRIES(Action, GetMethodActionImpl) { - return Action::kAllow; - } - - CREATE_HOOK_STUB_ENTRIES(Action, GetFieldActionImpl) { - return Action::kAllow; - } - - - static void DisableHiddenApi(void *handle, HookFunType hook_func) { - if (GetAndroidApiLevel() < ANDROID_P) { - return; - } - HOOK_FUNC(GetMethodActionImpl, - "_ZN3art9hiddenapi6detail19GetMemberActionImplINS_9ArtMethodEEENS0_" - "6ActionEPT_NS_20HiddenApiAccessFlags7ApiListES4_NS0_12AccessMethodE"); - HOOK_FUNC(GetFieldActionImpl, - "_ZN3art9hiddenapi6detail19GetMemberActionImplINS_8ArtFieldEEENS0_" - "6ActionEPT_NS_20HiddenApiAccessFlags7ApiListES4_NS0_12AccessMethodE"); - }; - */ - } - -} From b5efd6128d867a9ad2eae5e06d0d6f8a18c0ae16 Mon Sep 17 00:00:00 2001 From: Justin <40630518+Juxstin@users.noreply.github.com> Date: Sun, 16 Jun 2019 02:49:03 -0500 Subject: [PATCH 4/5] Update To Latest Source Update To Latest Source --- README.md | 2 + appveyor.yml | 39 ++++++++ .../riru/edxp/_hooker/impl/HandleBindApp.java | 3 - .../riru/edxp/_hooker/impl/LoadedApkCstr.java | 4 - .../_hooker/impl/StartBootstrapServices.java | 3 - .../riru/edxp/art/ClassLinker.java | 4 +- .../com/elderdrivers/riru/edxp/core/Main.java | 34 +++++-- .../riru/edxp/framework/ProcessHelper.java | 52 +++++++++++ .../riru/edxp/framework/Zygote.java | 12 +++ .../riru/edxp/proxy/BaseRouter.java | 25 +++--- .../riru/edxp/proxy/BlackWhiteListProxy.java | 5 -- .../riru/edxp/proxy/NormalProxy.java | 5 -- .../riru/edxp/util/ClassLoaderUtils.java | 47 +++++++++- .../riru/edxp/util/ClassUtils.java | 77 +++++----------- .../riru/edxp/util/ComposeClassLoader.java | 35 ++++++++ .../elderdrivers/riru/edxp/util/Utils.java | 15 +++- edxp-core/build.gradle | 4 +- .../main/cpp/external/yahfa/src/HookMain.c | 1 + .../src/main/cpp/external/yahfa/src/common.h | 2 +- .../src/main/cpp/external/yahfa/src/env.h | 1 + .../src/main/cpp/main/include/JNIHelper.h | 6 +- .../main/include/art/runtime/class_linker.h | 6 +- .../main/include/art/runtime/jni_env_ext.h | 9 ++ .../main/include/art/runtime/mirror/class.h | 26 +++--- edxp-core/src/main/cpp/main/include/config.h | 37 +++++--- .../cpp/main/include/framework/fd_utils.h | 37 ++++++++ .../src/main/cpp/main/src/edxp_context.cpp | 88 +++++++++++++------ .../src/main/cpp/main/src/edxp_context.h | 8 ++ .../cpp/main/src/jni/edxp_resources_hook.cpp | 4 +- edxp-core/src/main/cpp/main/src/main.cpp | 71 +++++++-------- .../src/main/cpp/main/src/native_hook.cpp | 57 ++++++++++-- .../common/util_functions.sh | 4 +- .../riru/edxp/sandhook/dexmaker/DexLog.java | 4 +- .../sandhook/hooker/SystemMainHooker.java | 4 +- .../sandhook/xposedcompat/XposedCompat.java | 2 +- .../methodgen/SandHookXposedBridge.java | 7 +- .../java/com/lody/whale/WhaleRuntime.java | 2 - .../riru/edxp/yahfa/dexmaker/DexLog.java | 4 +- .../edxp/yahfa/dexmaker/HookerDexMaker.java | 4 +- xposed-bridge/src/main/AndroidManifest.xml | 3 +- .../de/robv/android/xposed/PendingHooks.java | 24 +++++ .../de/robv/android/xposed/XposedBridge.java | 21 +---- 42 files changed, 557 insertions(+), 241 deletions(-) create mode 100644 appveyor.yml create mode 100644 edxp-common/src/main/java/com/elderdrivers/riru/edxp/framework/ProcessHelper.java create mode 100644 edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ComposeClassLoader.java create mode 100644 edxp-core/src/main/cpp/main/include/framework/fd_utils.h create mode 100644 xposed-bridge/src/main/java/de/robv/android/xposed/PendingHooks.java diff --git a/README.md b/README.md index 03e451924..4abd4daf5 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[![Build status](https://ci.appveyor.com/api/projects/status/qu3vj1d64nqia1b8/branch/master?svg=true)](https://ci.appveyor.com/project/ElderDrivers/edxposed/branch/master) + # EdXposed A Riru module trying to provide a ART hooking framework (initially for Android Pie) which delivers consistent APIs with the OG Xposed, leveraging YAHFA (or SandHook) hooking framework. diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 000000000..12f8182b6 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,39 @@ +environment: + ANDROID_HOME: C:\android-sdk-windows + +install: + - appveyor DownloadFile https://dl.google.com/android/repository/sdk-tools-windows-4333796.zip + - 7z x sdk-tools-windows-4333796.zip -oC:\android-sdk-windows > nul + - yes | C:\android-sdk-windows\tools\bin\sdkmanager.bat --licenses > nul + - C:\android-sdk-windows\tools\bin\sdkmanager.bat "platforms;android-28" > nul + - C:\android-sdk-windows\tools\bin\sdkmanager.bat "platform-tools" > nul + - C:\android-sdk-windows\tools\bin\sdkmanager.bat "build-tools;28.0.3" > nul + - C:\android-sdk-windows\tools\bin\sdkmanager.bat "cmake;3.6.4111459" > nul + - C:\android-sdk-windows\tools\bin\sdkmanager.bat "patcher;v4" > nul + - C:\android-sdk-windows\tools\bin\sdkmanager.bat "ndk-bundle" > nul + - set PATH=%PATH%;C:\android-sdk-windows\ndk-bundle;C:\android-sdk-windows\build-tools\28.0.3 + +build_script: + - gradlew.bat :edxp-core:zipYahfaRelease + - gradlew.bat :edxp-core:zipSandhookRelease + +artifacts: + - path: 'edxp-core\release\**\*.zip' + +only_commits: + files: + - dalvikdx/ + - dexmaker/ + - edxp-common/ + - edxp-core/ + - edxp-sandhook/ + - edxp-whale/ + - edxp-yahfa/ + - hiddenapi-stubs/ + - xposed-bridge/ + - build.gradle + - settings.gradle + - gradle.properties + - appveyor.yml + +version: '0.4.4.5_alpha (4450) {build}' diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/HandleBindApp.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/HandleBindApp.java index 9e0d200c6..177a3063c 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/HandleBindApp.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/HandleBindApp.java @@ -22,7 +22,6 @@ 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 HandleBindApp extends XC_MethodHook { @@ -62,8 +61,6 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { 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"); 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 index 394b0e027..889457cc3 100644 --- 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 @@ -13,8 +13,6 @@ 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 { @@ -60,8 +58,6 @@ protected void afterHookedMethod(MethodHookParam param) throws Throwable { return; } - replaceParentClassLoader(loadedApk.getClassLoader()); - XC_LoadPackage.LoadPackageParam lpparam = new XC_LoadPackage.LoadPackageParam(XposedBridge.sLoadedPackageCallbacks); lpparam.packageName = packageName; lpparam.processName = AndroidAppHelper.currentProcessName(); diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/StartBootstrapServices.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/StartBootstrapServices.java index 41cbfb0a7..0b1b11b12 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/StartBootstrapServices.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/_hooker/impl/StartBootstrapServices.java @@ -11,7 +11,6 @@ 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; @@ -28,8 +27,6 @@ protected void beforeHookedMethod(MethodHookParam param) throws Throwable { try { XposedInit.loadedPackagesInProcess.add("android"); - 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 diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/art/ClassLinker.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/art/ClassLinker.java index 5d2eeeb93..a99cf092a 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/art/ClassLinker.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/art/ClassLinker.java @@ -4,13 +4,13 @@ import java.lang.reflect.Member; -import de.robv.android.xposed.XposedBridge; +import de.robv.android.xposed.PendingHooks; public class ClassLinker implements KeepAll { public static native void setEntryPointsToInterpreter(Member method); public static void onPostFixupStaticTrampolines(Class clazz) { - XposedBridge.hookPendingMethod(clazz); + PendingHooks.hookPendingMethod(clazz); } } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/Main.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/Main.java index 31bdc6417..36ced2063 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/Main.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/core/Main.java @@ -4,8 +4,9 @@ import android.os.Process; import com.elderdrivers.riru.common.KeepAll; -import com.elderdrivers.riru.edxp.BuildConfig; +import com.elderdrivers.riru.edxp.common.BuildConfig; import com.elderdrivers.riru.edxp.config.ConfigManager; +import com.elderdrivers.riru.edxp.framework.ProcessHelper; import com.elderdrivers.riru.edxp.util.Utils; import java.security.AccessController; @@ -18,6 +19,7 @@ @SuppressLint("DefaultLocale") public class Main implements KeepAll { + private static final boolean logEnabled = BuildConfig.DEBUG; private static String forkAndSpecializePramsStr = ""; private static String forkSystemServerPramsStr = ""; @@ -36,11 +38,14 @@ public static void forkAndSpecializePre(int uid, int gid, int[] gids, int debugF String niceName, int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir) { + if (isBlackListedProcess(uid)) { + return; + } final EdxpImpl edxp = getEdxpImpl(); if (edxp == null || !edxp.isInitialized()) { return; } - if (BuildConfig.DEBUG) { + if (logEnabled) { 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), @@ -60,12 +65,17 @@ public static void forkAndSpecializePre(int uid, int gid, int[] gids, int debugF } public static void forkAndSpecializePost(int pid, String appDataDir, String niceName) { + if (isBlackListedProcess(Process.myUid())) { + return; + } final EdxpImpl edxp = getEdxpImpl(); if (edxp == null || !edxp.isInitialized()) { return; } if (pid == 0) { - Utils.logD(forkAndSpecializePramsStr + " = " + Process.myPid()); + if (logEnabled) { + Utils.logI(forkAndSpecializePramsStr + " = " + Process.myPid()); + } if (ConfigManager.isBlackWhiteListEnabled()) { edxp.getBlackWhiteListProxy().forkAndSpecializePost(pid, appDataDir, niceName); } else { @@ -83,7 +93,7 @@ public static void forkSystemServerPre(int uid, int gid, int[] gids, int debugFl if (edxp == null || !edxp.isInitialized()) { return; } - if (BuildConfig.DEBUG) { + if (logEnabled) { forkSystemServerPramsStr = String.format("Zygote#forkSystemServer(%d, %d, %s, %d, %s, %d, %d)", uid, gid, Arrays.toString(gids), debugFlags, Arrays.toString(rlimits), permittedCapabilities, effectiveCapabilities); @@ -103,7 +113,9 @@ public static void forkSystemServerPost(int pid) { return; } if (pid == 0) { - Utils.logD(forkSystemServerPramsStr + " = " + Process.myPid()); + if (logEnabled) { + Utils.logI(forkSystemServerPramsStr + " = " + Process.myPid()); + } if (ConfigManager.isBlackWhiteListEnabled()) { edxp.getBlackWhiteListProxy().forkSystemServerPost(pid); } else { @@ -123,6 +135,11 @@ public static synchronized EdxpImpl getEdxpImpl() { return edxpImplRef.get(); } + @EdxpImpl.Variant + public static synchronized int getEdxpVariant() { + return getEdxpImpl().getVariant(); + } + private static void loadEdxpImpls() { AccessController.doPrivileged(new PrivilegedAction() { public Void run() { @@ -133,11 +150,16 @@ public Void run() { iterator.next(); } } catch (Throwable t) { - // Do nothing + Utils.logE("error when loadEdxpImpls", t); } return null; } }); } + private static boolean isBlackListedProcess(int uid) { + return ProcessHelper.isIsolated(uid) + || ProcessHelper.isRELROUpdater(uid) + || ProcessHelper.isWebViewZygote(uid); + } } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/framework/ProcessHelper.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/framework/ProcessHelper.java new file mode 100644 index 000000000..6018a1ea1 --- /dev/null +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/framework/ProcessHelper.java @@ -0,0 +1,52 @@ +package com.elderdrivers.riru.edxp.framework; + +import de.robv.android.xposed.XposedHelpers; + +public class ProcessHelper { + + static { + // WEBVIEW_ZYGOTE_UID differ among versions + WEBVIEW_ZYGOTE_UID = XposedHelpers.getStaticIntField(android.os.Process.class, "WEBVIEW_ZYGOTE_UID"); + } + + /** + * Defines the UID/GID for the shared RELRO file updater process. + */ + public static final int SHARED_RELRO_UID = 1037; + + /** + * Defines the UID/GID for the WebView zygote process. + */ + public static final int WEBVIEW_ZYGOTE_UID; + + /** + * First uid used for fully isolated sandboxed processes (with no permissions of their own) + */ + public static final int FIRST_ISOLATED_UID = 99000; + /** + * Last uid used for fully isolated sandboxed processes (with no permissions of their own) + */ + public static final int LAST_ISOLATED_UID = 99999; + + /** + * Range of uids allocated for a user. + */ + public static final int PER_USER_RANGE = 100000; + + public static int getAppId(int uid) { + return uid % PER_USER_RANGE; + } + + public static boolean isRELROUpdater(int uid) { + return getAppId(uid) == SHARED_RELRO_UID; + } + + public static boolean isWebViewZygote(int uid) { + return getAppId(uid) == WEBVIEW_ZYGOTE_UID; + } + + public static boolean isIsolated(int uid) { + uid = getAppId(uid); + return uid >= FIRST_ISOLATED_UID && uid <= LAST_ISOLATED_UID; + } +} diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/framework/Zygote.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/framework/Zygote.java index 8aa08002e..9ca7606cd 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/framework/Zygote.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/framework/Zygote.java @@ -1,5 +1,9 @@ package com.elderdrivers.riru.edxp.framework; +import com.elderdrivers.riru.edxp.util.Utils; + +import de.robv.android.xposed.XposedHelpers; + public class Zygote { // prevent from fatal error caused by holding not whitelisted file descriptors when forking zygote @@ -8,4 +12,12 @@ public class Zygote { public static native void reopenFilesAfterFork(); + public static void allowFileAcrossFork(String path) { + try { + Class zygote = XposedHelpers.findClass("com.android.internal.os.Zygote", null); + XposedHelpers.callStaticMethod(zygote, "nativeAllowFileAcrossFork", path); + } catch (Throwable throwable) { + Utils.logE("error when allowFileAcrossFork", throwable); + } + } } 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 index 51ab60c24..a40bb8fe4 100644 --- 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 @@ -7,10 +7,12 @@ import com.elderdrivers.riru.edxp._hooker.impl.HandleBindApp; import com.elderdrivers.riru.edxp._hooker.impl.LoadedApkCstr; +import com.elderdrivers.riru.edxp._hooker.impl.OneplusWorkaround; import com.elderdrivers.riru.edxp._hooker.impl.StartBootstrapServices; import com.elderdrivers.riru.edxp._hooker.impl.SystemMain; 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.StartBootstrapServicesHooker; import com.elderdrivers.riru.edxp._hooker.yahfa.SystemMainHooker; import com.elderdrivers.riru.edxp.core.yahfa.HookMain; @@ -138,15 +140,18 @@ public void startSystemServerHook() { public void startWorkAroundHook() { ClassLoader classLoader = BaseRouter.class.getClassLoader(); -// if (useXposedApi) { -// XposedHelpers.findAndHookMethod(OnePlusWorkAroundHooker.className, -// classLoader, OnePlusWorkAroundHooker.methodName, -// int.class, String.class, new OneplusWorkaround()); -// } else { - HookMain.doHookDefault( - BaseRouter.class.getClassLoader(), - classLoader, - WorkAroundHookInfo.class.getName()); -// } + if (useXposedApi) { + try { + XposedHelpers.findAndHookMethod(OnePlusWorkAroundHooker.className, + classLoader, OnePlusWorkAroundHooker.methodName, + int.class, String.class, new OneplusWorkaround()); + } catch (Throwable throwable) { + } + } else { + HookMain.doHookDefault( + BaseRouter.class.getClassLoader(), + classLoader, + WorkAroundHookInfo.class.getName()); + } } } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BlackWhiteListProxy.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BlackWhiteListProxy.java index 7abfa1ffa..88bd5a117 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BlackWhiteListProxy.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BlackWhiteListProxy.java @@ -4,7 +4,6 @@ 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; @@ -87,16 +86,12 @@ private void onForkPreForNonDynamicMode(boolean isSystemServer) { // loadModules once for all child processes of zygote // TODO maybe just save initZygote callbacks and call them when whitelisted process forked? mRouter.loadModulesSafely(true); - Zygote.closeFilesBeforeFork(); } private void onForkPostCommon(boolean isSystemServer, String appDataDir, String niceName) { ConfigManager.appDataDir = appDataDir; ConfigManager.niceName = niceName; final boolean isDynamicModulesMode = ConfigManager.isDynamicModulesEnabled(); - if (!isDynamicModulesMode) { - Zygote.reopenFilesAfterFork(); - } mRouter.onEnterChildProcess(); if (!checkNeedHook(appDataDir, niceName)) { // if is blacklisted, just stop here 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 index 68c462338..c28ff4534 100644 --- 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 @@ -2,7 +2,6 @@ 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; @@ -27,7 +26,6 @@ public void forkAndSpecializePre(int uid, int gid, int[] gids, int debugFlags, mRouter.installBootstrapHooks(false); // only load modules for secondary zygote mRouter.loadModulesSafely(true); - Zygote.closeFilesBeforeFork(); } public void forkAndSpecializePost(int pid, String appDataDir, String niceName) { @@ -35,7 +33,6 @@ public void forkAndSpecializePost(int pid, String appDataDir, String niceName) { 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); @@ -57,7 +54,6 @@ public void forkSystemServerPre(int uid, int gid, int[] gids, int debugFlags, in // 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) { @@ -65,7 +61,6 @@ public void forkSystemServerPost(int pid) { 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); diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ClassLoaderUtils.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ClassLoaderUtils.java index 9a722e283..09e429b3d 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ClassLoaderUtils.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ClassLoaderUtils.java @@ -3,14 +3,16 @@ import android.os.Build; import android.util.ArrayMap; -import com.elderdrivers.riru.edxp.BuildConfig; +import com.elderdrivers.riru.edxp.common.BuildConfig; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import dalvik.system.BaseDexClassLoader; import dalvik.system.PathClassLoader; +import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; @@ -62,6 +64,11 @@ private static void dumpClassLoaders(ClassLoader classLoader) { } } + public static ClassLoader createComposeClassLoader(ClassLoader appClassLoader) { + ClassLoader current = ClassLoaderUtils.class.getClassLoader(); + return appClassLoader == null ? current : new ComposeClassLoader(appClassLoader, current); + } + public static List getAppClassLoader() { List cacheLoaders = new ArrayList<>(0); try { @@ -107,4 +114,42 @@ public static boolean addPathToClassLoader(ClassLoader classLoader) { return false; } + public static void hookClassLoading() { + final ClassLoader currentCl = ClassLoaderUtils.class.getClassLoader(); + XposedHelpers.findAndHookMethod(Class.class, + "forName", String.class, boolean.class, ClassLoader.class, + new XC_MethodHook(Integer.MAX_VALUE) { + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + if (param.args[2] == currentCl) { + return; + } + try { + param.setResult(Class.forName( + (String) param.args[0], (boolean) param.args[1], currentCl)); + } catch (Throwable throwable) { + // silently continue to call original + } + } + }); + XC_MethodHook findClassHook = new XC_MethodHook(Integer.MAX_VALUE) { + @Override + protected void beforeHookedMethod(MethodHookParam param) throws Throwable { + if (param.thisObject == currentCl) { + return; + } + try { + param.setResult(XposedHelpers.callMethod(currentCl, + "findClass", param.args[0])); + param.setThrowable(null); + } catch (Throwable throwable) { + // silently continue to return + } + } + }; + XposedHelpers.findAndHookMethod(BaseDexClassLoader.class, + "findClass", String.class, findClassHook); + XposedHelpers.findAndHookMethod("java.lang.BootClassLoader", null, + "findClass", String.class, findClassHook); + } } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ClassUtils.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ClassUtils.java index 3421d1ce2..bd46ded36 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ClassUtils.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ClassUtils.java @@ -1,73 +1,36 @@ package com.elderdrivers.riru.edxp.util; +import android.os.Build; + import de.robv.android.xposed.XposedHelpers; public class ClassUtils { - public enum ClassStatus { - kNotReady(0), // Zero-initialized Class object starts in this state. - kRetired(1), // Retired, should not be used. Use the newly cloned one instead. - kErrorResolved(2), - kErrorUnresolved(3), - kIdx(4), // Loaded, DEX idx in super_class_type_idx_ and interfaces_type_idx_. - kLoaded(5), // DEX idx values resolved. - kResolving(6), // Just cloned from temporary class object. - kResolved(7), // Part of linking. - kVerifying(8), // In the process of being verified. - kRetryVerificationAtRuntime(9), // Compile time verification failed, retry at runtime. - kVerifyingAtRuntime(10), // Retrying verification at runtime. - kVerified(11), // Logically part of linking; done pre-init. - kSuperclassValidated(12), // Superclass validation part of init done. - kInitializing(13), // Class init in progress. - kInitialized(14); // Ready to go. - - private final int status; - - ClassStatus(int status) { - this.status = status; - } - - static ClassStatus withValue(int value) { - for (ClassStatus status : ClassStatus.values()) { - if (status.status == value) { - return status; - } - } - return kNotReady; - } - } - - /** - * enum class ClassStatus : uint8_t { - * kNotReady = 0, // Zero-initialized Class object starts in this state. - * kRetired = 1, // Retired, should not be used. Use the newly cloned one instead. - * kErrorResolved = 2, - * kErrorUnresolved = 3, - * kIdx = 4, // Loaded, DEX idx in super_class_type_idx_ and interfaces_type_idx_. - * kLoaded = 5, // DEX idx values resolved. - * kResolving = 6, // Just cloned from temporary class object. - * kResolved = 7, // Part of linking. - * kVerifying = 8, // In the process of being verified. - * kRetryVerificationAtRuntime = 9, // Compile time verification failed, retry at runtime. - * kVerifyingAtRuntime = 10, // Retrying verification at runtime. - * kVerified = 11, // Logically part of linking; done pre-init. - * kSuperclassValidated = 12, // Superclass validation part of init done. - * kInitializing = 13, // Class init in progress. - * kInitialized = 14, // Ready to go. - * kLast = kInitialized - * }; - */ - public static ClassStatus getClassStatus(Class clazz) { + public static int getClassStatus(Class clazz, boolean isUnsigned) { if (clazz == null) { - return ClassStatus.kNotReady; + return 0; } int status = XposedHelpers.getIntField(clazz, "status"); - return ClassStatus.withValue((int) (Integer.toUnsignedLong(status) >> (32 - 4))); + if (isUnsigned) { + status = (int) (Integer.toUnsignedLong(status) >> (32 - 4)); + } + return status; } + /** + * 5.0-8.0: kInitialized = 10 int + * 8.1: kInitialized = 11 int + * 9.0: kInitialized = 14 uint8_t + */ public static boolean isInitialized(Class clazz) { - return getClassStatus(clazz) == ClassStatus.kInitialized; + if (Build.VERSION.SDK_INT >= 28) { + return getClassStatus(clazz, true) == 14; + } else if (Build.VERSION.SDK_INT == 27) { + return getClassStatus(clazz, false) == 11; + } else { + return getClassStatus(clazz, false) == 10; + } } } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ComposeClassLoader.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ComposeClassLoader.java new file mode 100644 index 000000000..1409b40ba --- /dev/null +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ComposeClassLoader.java @@ -0,0 +1,35 @@ +package com.elderdrivers.riru.edxp.util; + +/** + * Created by weishu on 17/11/30. + */ + +public class ComposeClassLoader extends ClassLoader { + + private final ClassLoader mAppClassLoader; + + public ComposeClassLoader(ClassLoader parent, ClassLoader appClassLoader) { + super(parent); + mAppClassLoader = appClassLoader; + } + + @Override + protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + Class clazz = null; + + try { + clazz = mAppClassLoader.loadClass(name); + } catch (ClassNotFoundException e) { + // IGNORE. + } + if (clazz == null) { + clazz = super.loadClass(name, resolve); + } + + if (clazz == null) { + throw new ClassNotFoundException(); + } + + return clazz; + } +} diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/Utils.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/Utils.java index 7cfe79656..e6bcb8453 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/Utils.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/Utils.java @@ -2,14 +2,14 @@ import android.util.Log; -import com.elderdrivers.riru.edxp.BuildConfig; +import com.elderdrivers.riru.edxp.common.BuildConfig; import de.robv.android.xposed.XposedHelpers; public class Utils { - public static final String LOG_TAG = "EdXposed-Fwk"; + public static final String LOG_TAG = "EdXposed"; public static void logD(Object msg) { if (BuildConfig.DEBUG) @@ -46,7 +46,14 @@ public static void logE(String msg, Throwable throwable) { } public static String getSysProp(String key) { - Class sysProps = XposedHelpers.findClassIfExists("android.os.SystemProperties", null); - return (String) XposedHelpers.callStaticMethod(sysProps, "get", key); + try { + Class sysProps = XposedHelpers.findClassIfExists("android.os.SystemProperties", null); + if (sysProps != null) { + return (String) XposedHelpers.callStaticMethod(sysProps, "get", key); + } + } catch (Throwable throwable) { + Utils.logE("error when get sys prop", throwable); + } + return ""; } } diff --git a/edxp-core/build.gradle b/edxp-core/build.gradle index 41a4741b9..6e9f38d03 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.4_alpha" +version "v0.4.4.5_alpha" ext { - versionCode = "4340" + versionCode = "4450" 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/src/HookMain.c b/edxp-core/src/main/cpp/external/yahfa/src/HookMain.c index c15a56878..8cad76f1e 100644 --- a/edxp-core/src/main/cpp/external/yahfa/src/HookMain.c +++ b/edxp-core/src/main/cpp/external/yahfa/src/HookMain.c @@ -37,6 +37,7 @@ void Java_lab_galaxy_yahfa_HookMain_init(JNIEnv *env, jclass clazz, jint sdkVers SDKVersion = sdkVersion; LOGI("init to SDK %d", sdkVersion); switch (sdkVersion) { + case ANDROID_Q: case ANDROID_P: kAccCompileDontBother = 0x02000000; OFFSET_ArtMehod_in_Object = 0; diff --git a/edxp-core/src/main/cpp/external/yahfa/src/common.h b/edxp-core/src/main/cpp/external/yahfa/src/common.h index 11d0818e5..6d99272db 100644 --- a/edxp-core/src/main/cpp/external/yahfa/src/common.h +++ b/edxp-core/src/main/cpp/external/yahfa/src/common.h @@ -14,7 +14,7 @@ #define LOGW(...) #define LOGE(...) #else -#define LOG_TAG "EdXposed-YAHFA" +#define LOG_TAG "EdXposed" #ifdef DEBUG #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__) diff --git a/edxp-core/src/main/cpp/external/yahfa/src/env.h b/edxp-core/src/main/cpp/external/yahfa/src/env.h index 105c45863..026f20edc 100644 --- a/edxp-core/src/main/cpp/external/yahfa/src/env.h +++ b/edxp-core/src/main/cpp/external/yahfa/src/env.h @@ -13,6 +13,7 @@ #define ANDROID_O 26 #define ANDROID_O2 27 #define ANDROID_P 28 +#define ANDROID_Q 29 #define roundUpTo4(v) ((v+4-1) - ((v+4-1)&3)) #define roundUpTo8(v) ((v+8-1) - ((v+8-1)&7)) diff --git a/edxp-core/src/main/cpp/main/include/JNIHelper.h b/edxp-core/src/main/cpp/main/include/JNIHelper.h index a28708a04..d3dab8a23 100644 --- a/edxp-core/src/main/cpp/main/include/JNIHelper.h +++ b/edxp-core/src/main/cpp/main/include/JNIHelper.h @@ -85,7 +85,11 @@ ALWAYS_INLINE static int ClearException(JNIEnv *env) { #define JNI_CallStaticObjectMethod(env, obj, ...) \ env->CallStaticObjectMethod(obj, __VA_ARGS__); \ - if (ClearException(env)) LOGE("CallStaticVoidMethod " #obj " " #__VA_ARGS__); + if (ClearException(env)) LOGE("CallStaticObjectMethod " #obj " " #__VA_ARGS__); + +#define JNI_CallStaticIntMethod(env, obj, ...) \ + env->CallStaticIntMethod(obj, __VA_ARGS__); \ + if (ClearException(env)) LOGE("CallStaticIntMethod " #obj " " #__VA_ARGS__); #define JNI_GetArrayLength(env, array) \ env->GetArrayLength(array); \ diff --git a/edxp-core/src/main/cpp/main/include/art/runtime/class_linker.h b/edxp-core/src/main/cpp/main/include/art/runtime/class_linker.h index 816d85183..6f1749a60 100644 --- a/edxp-core/src/main/cpp/main/include/art/runtime/class_linker.h +++ b/edxp-core/src/main/cpp/main/include/art/runtime/class_linker.h @@ -40,11 +40,13 @@ namespace art { } static void Setup(void *handle, HookFunType hook_func) { - HOOK_FUNC(Constructor, "_ZN3art11ClassLinkerC2EPNS_11InternTableE"); + HOOK_FUNC(Constructor, "_ZN3art11ClassLinkerC2EPNS_11InternTableE", + "_ZN3art11ClassLinkerC2EPNS_11InternTableEb"); // 10.0 RETRIEVE_FUNC_SYMBOL(SetEntryPointsToInterpreter, "_ZNK3art11ClassLinker27SetEntryPointsToInterpreterEPNS_9ArtMethodE"); - HOOK_FUNC(FixupStaticTrampolines, "_ZN3art11ClassLinker22FixupStaticTrampolinesENS_6ObjPtrINS_6mirror5ClassEEE"); + HOOK_FUNC(FixupStaticTrampolines, + "_ZN3art11ClassLinker22FixupStaticTrampolinesENS_6ObjPtrINS_6mirror5ClassEEE"); } ALWAYS_INLINE void SetEntryPointsToInterpreter(void *art_method) const { diff --git a/edxp-core/src/main/cpp/main/include/art/runtime/jni_env_ext.h b/edxp-core/src/main/cpp/main/include/art/runtime/jni_env_ext.h index 1f34f6cf6..015122dd4 100644 --- a/edxp-core/src/main/cpp/main/include/art/runtime/jni_env_ext.h +++ b/edxp-core/src/main/cpp/main/include/art/runtime/jni_env_ext.h @@ -13,16 +13,25 @@ namespace art { return NewLocalRefSym(env, mirror_ptr); } + CREATE_FUNC_SYMBOL_ENTRY(void, DeleteLocalRef, void *env, jobject obj) { + DeleteLocalRefSym(env, obj); + } + public: JNIEnvExt(void *thiz) : HookedObject(thiz) {} static void Setup(void *handle, HookFunType hook_func) { RETRIEVE_FUNC_SYMBOL(NewLocalRef, "_ZN3art9JNIEnvExt11NewLocalRefEPNS_6mirror6ObjectE"); + RETRIEVE_FUNC_SYMBOL(DeleteLocalRef, "_ZN3art9JNIEnvExt14DeleteLocalRefEP8_jobject"); } jobject NewLocalRefer(void *mirror_ptr) { return NewLocalRef(thiz_, mirror_ptr); } + + void DeleteLocalRef(jobject obj) { + DeleteLocalRef(thiz_, obj); + } }; diff --git a/edxp-core/src/main/cpp/main/include/art/runtime/mirror/class.h b/edxp-core/src/main/cpp/main/include/art/runtime/mirror/class.h index cca55aca0..72eb8f2c5 100644 --- a/edxp-core/src/main/cpp/main/include/art/runtime/mirror/class.h +++ b/edxp-core/src/main/cpp/main/include/art/runtime/mirror/class.h @@ -1,6 +1,7 @@ #pragma once +#include #include "base/object.h" namespace art { @@ -15,15 +16,10 @@ namespace art { CREATE_FUNC_SYMBOL_ENTRY(const char *, GetDescriptor, void *thiz, std::string *storage) { - return GetDescriptorSym(thiz, storage); - } - - - CREATE_ORIGINAL_ENTRY(bool, IsInSamePackage, void *thiz, void *that) { - if (IsInSamePackageBackup) { - return IsInSamePackageBackup(thiz, that); - } - return false; + if (GetDescriptorSym) + return GetDescriptorSym(thiz, storage); + else + return ""; } CREATE_HOOK_STUB_ENTRIES(bool, IsInSamePackage, void *thiz, void *that) { @@ -44,7 +40,7 @@ namespace art { || strstr(thatDesc, "android/content/res/XResources$XTypedArray") != nullptr) { return true; } - return IsInSamePackage(thiz, that); + return IsInSamePackageBackup(thiz, that); } public: @@ -60,6 +56,16 @@ namespace art { HOOK_FUNC(IsInSamePackage, "_ZN3art6mirror5Class15IsInSamePackageENS_6ObjPtrIS1_EE", //8.0- "_ZN3art6mirror5Class15IsInSamePackageEPS1_"); //5.0-7.1 + +// HOOK_FUNC(ClassForName, +// "_ZN3artL18Class_classForNameEP7_JNIEnvP7_jclassP8_jstringhP8_jobject"); + } + + const char *GetDescriptor(std::string *storage) { + if (thiz_ && GetDescriptorSym) { + return GetDescriptor(thiz_, storage); + } + return ""; } }; diff --git a/edxp-core/src/main/cpp/main/include/config.h b/edxp-core/src/main/cpp/main/include/config.h index f0e8cb2e8..4c53f3e93 100644 --- a/edxp-core/src/main/cpp/main/include/config.h +++ b/edxp-core/src/main/cpp/main/include/config.h @@ -5,6 +5,7 @@ #include #include #include "art/base/macros.h" +#include "android_build.h" namespace edxp { @@ -17,19 +18,29 @@ namespace edxp { # define LP_SELECT(lp32, lp64) (lp32) #endif - 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.core.Main"; - static constexpr const char *kClassLinkerClassName = "com.elderdrivers.riru.edxp.art.ClassLinker"; - static constexpr const char *kSandHookClassName = "com.swift.sandhook.SandHook"; - static constexpr const char *kSandHookNeverCallClassName = "com.swift.sandhook.ClassNeverCall"; - - static const std::string kLibBasePath = LP_SELECT("/system/lib/", "/system/lib64/"); - static const std::string kLibArtPath = kLibBasePath + "libart.so"; - static const std::string kLibWhalePath = kLibBasePath + "libwhale.edxp.so"; - static const std::string kLibSandHookPath = kLibBasePath + "libsandhook.edxp.so"; - static const std::string kLibFwPath = kLibBasePath + "libandroidfw.so"; + static constexpr auto kInjectDexPath = "/system/framework/edxp.jar:" + "/system/framework/eddalvikdx.jar:" + "/system/framework/eddexmaker.jar"; + + static constexpr auto kEntryClassName = "com.elderdrivers.riru.edxp.core.Main"; + static constexpr auto kClassLinkerClassName = "com.elderdrivers.riru.edxp.art.ClassLinker"; + static constexpr auto kSandHookClassName = "com.swift.sandhook.SandHook"; + static constexpr auto kSandHookNeverCallClassName = "com.swift.sandhook.ClassNeverCall"; + + static constexpr auto kLibArtName = "libart.so"; + static constexpr auto kLibFwkName = "libandroid_runtime.so"; + + static const auto kLibBasePath = std::string(LP_SELECT("/system/lib/", "/system/lib64/")); + static const auto kLibRuntimeBasePath = std::string( + LP_SELECT("/apex/com.android.runtime/lib/", "/apex/com.android.runtime/lib64/")); + + static const auto kLibArtPath = + (GetAndroidApiLevel() >= ANDROID_Q ? kLibRuntimeBasePath : kLibBasePath) + kLibArtName; + static const auto kLibWhalePath = kLibBasePath + "libwhale.edxp.so"; + static const auto kLibSandHookPath = kLibBasePath + "libsandhook.edxp.so"; + static const auto kLibFwPath = kLibBasePath + "libandroidfw.so"; + static const auto kLibDlPath = kLibBasePath + "libdl.so"; + static const auto kLibFwkPath = kLibBasePath + kLibFwkName; inline const char *const BoolToString(bool b) { return b ? "true" : "false"; diff --git a/edxp-core/src/main/cpp/main/include/framework/fd_utils.h b/edxp-core/src/main/cpp/main/include/framework/fd_utils.h new file mode 100644 index 000000000..a576337da --- /dev/null +++ b/edxp-core/src/main/cpp/main/include/framework/fd_utils.h @@ -0,0 +1,37 @@ + +#pragma once + +#include +#include "base/object.h" + +namespace android { + + // Static whitelist of open paths that the zygote is allowed to keep open. + static const char *kPathWhitelist[] = { + "/data/app/", + "/data/app-private/" + }; + + class FileDescriptorWhitelist : public edxp::HookedObject { + + public: + FileDescriptorWhitelist(void *thiz) : HookedObject(thiz) {} + + static void Setup(void *handle, HookFunType hook_func) { + HOOK_FUNC(IsAllowed, + "_ZNK23FileDescriptorWhitelist9IsAllowedERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE"); + } + + private: + + CREATE_HOOK_STUB_ENTRIES(bool, IsAllowed, void *thiz, const std::string &path) { + for (const auto &whitelist_path : kPathWhitelist) { + if (android::base::StartsWith(path, whitelist_path)) + return true; + } + return IsAllowedBackup(thiz, path); + } + + }; + +} \ No newline at end of file diff --git a/edxp-core/src/main/cpp/main/src/edxp_context.cpp b/edxp-core/src/main/cpp/main/src/edxp_context.cpp index 37d6a0bc7..dd2a66402 100644 --- a/edxp-core/src/main/cpp/main/src/edxp_context.cpp +++ b/edxp-core/src/main/cpp/main/src/edxp_context.cpp @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include "edxp_context.h" #include "config_manager.h" @@ -33,12 +35,18 @@ namespace edxp { } void Context::CallOnPostFixupStaticTrampolines(void *class_ptr) { - if (post_fixup_static_mid_ != nullptr) { - JNIEnv *env; - vm_->GetEnv((void **) (&env), JNI_VERSION_1_4); - art::JNIEnvExt env_ext(env); - jobject clazz = env_ext.NewLocalRefer(class_ptr); - JNI_CallStaticVoidMethod(env, class_linker_class_, post_fixup_static_mid_, clazz); + if (UNLIKELY(!post_fixup_static_mid_ || !class_linker_class_)) { + return; + } + if (!class_ptr) { + return; + } + JNIEnv *env; + vm_->GetEnv((void **) (&env), JNI_VERSION_1_4); + art::JNIEnvExt env_ext(env); + ScopedLocalRef clazz(env, env_ext.NewLocalRefer(class_ptr)); + if (clazz != nullptr) { + JNI_CallStaticVoidMethod(env, class_linker_class_, post_fixup_static_mid_, clazz.get()); } } @@ -60,12 +68,22 @@ namespace edxp { "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/ClassLoader;)V"); jobject my_cl = JNI_NewObject(env, path_classloader, initMid, env->NewStringUTF(dex_path), nullptr, sys_classloader); - if (UNLIKELY(!my_cl)) { + + env->DeleteLocalRef(classloader); + env->DeleteLocalRef(sys_classloader); + env->DeleteLocalRef(path_classloader); + + if (UNLIKELY(my_cl == nullptr)) { LOG(ERROR) << "PathClassLoader creation failed!!!"; return; } + + // TODO clear up all these global refs if blacklisted? + inject_class_loader_ = env->NewGlobalRef(my_cl); + env->DeleteLocalRef(my_cl); + // initialize pending methods related env->GetJavaVM(&vm_); class_linker_class_ = (jclass) env->NewGlobalRef( @@ -84,22 +102,36 @@ namespace edxp { RegisterArtHeap(env); RegisterEdxpYahfa(env); + // must call entry class's methods after all native methods registered + if (LIKELY(entry_class_)) { + jmethodID get_variant_mid = JNI_GetStaticMethodID(env, entry_class_, + "getEdxpVariant", "()I"); + if (LIKELY(get_variant_mid)) { + int variant = JNI_CallStaticIntMethod(env, entry_class_, get_variant_mid); + variant_ = static_cast(variant); + } + } + initialized_ = true; - //for SandHook variant - ScopedDlHandle sandhook_handle(kLibSandHookPath.c_str()); - if (!sandhook_handle.IsValid()) { - return; - } - typedef bool *(*TYPE_JNI_LOAD)(JNIEnv *, jclass, jclass); - auto jni_load = sandhook_handle.DlSym("JNI_Load_Ex"); - jclass sandhook_class = FindClassFromLoader(env, kSandHookClassName); - jclass nevercall_class = FindClassFromLoader(env, kSandHookNeverCallClassName); - if (!sandhook_class || !nevercall_class) { // fail-fast - return; - } - if (!jni_load(env, sandhook_class, nevercall_class)) { - LOGE("SandHook: HookEntry class error. %d", getpid()); + if (variant_ == SANDHOOK) { + //for SandHook variant + ScopedDlHandle sandhook_handle(kLibSandHookPath.c_str()); + if (!sandhook_handle.IsValid()) { + return; + } + typedef bool *(*TYPE_JNI_LOAD)(JNIEnv *, jclass, jclass); + auto jni_load = sandhook_handle.DlSym("JNI_Load_Ex"); + ScopedLocalRef sandhook_class(env, FindClassFromLoader(env, kSandHookClassName)); + ScopedLocalRef nevercall_class(env, + FindClassFromLoader(env, kSandHookNeverCallClassName)); + if (sandhook_class == nullptr || nevercall_class == nullptr) { // fail-fast + return; + } + if (!jni_load(env, sandhook_class.get(), nevercall_class.get())) { + LOGE("SandHook: HookEntry class error. %d", getpid()); + } + } } @@ -133,9 +165,10 @@ namespace edxp { LoadDexAndInit(env, kInjectDexPath); } + inline void Context::FindAndCall(JNIEnv *env, const char *method_name, const char *method_sig, ...) const { - if (!entry_class_) { + if (UNLIKELY(!entry_class_)) { LOGE("cannot call method %s, entry class is null", method_name); return; } @@ -143,7 +176,7 @@ namespace edxp { if (LIKELY(mid)) { va_list args; va_start(args, method_sig); - env->functions->CallStaticVoidMethodV(env, entry_class_, mid, args); + env->CallStaticVoidMethodV(entry_class_, mid, args); va_end(args); } else { LOGE("method %s id is null", method_name); @@ -209,14 +242,14 @@ namespace edxp { jobjectArray rlimits, jint mount_external, jstring se_info, - jstring se_name, + jstring nice_name, jintArray fds_to_close, jintArray fds_to_ignore, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir) { app_data_dir_ = app_data_dir; - nice_name_ = se_name; + nice_name_ = nice_name; if (ConfigManager::GetInstance()->IsBlackWhiteListEnabled() && ConfigManager::GetInstance()->IsDynamicModulesEnabled()) { // when black/white list is on, never inject into zygote if dynamic modules mode is on @@ -226,7 +259,7 @@ namespace edxp { FindAndCall(env, "forkAndSpecializePre", "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;)V", uid, gid, gids, runtime_flags, rlimits, - mount_external, se_info, se_name, fds_to_close, fds_to_ignore, + mount_external, se_info, nice_name, fds_to_close, fds_to_ignore, is_child_zygote, instruction_set, app_data_dir); } @@ -234,8 +267,7 @@ namespace edxp { if (res == 0) { PrepareJavaEnv(env); FindAndCall(env, "forkAndSpecializePost", "(ILjava/lang/String;Ljava/lang/String;)V", - res, - app_data_dir_, nice_name_); + res, app_data_dir_, nice_name_); } 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-core/src/main/cpp/main/src/edxp_context.h b/edxp-core/src/main/cpp/main/src/edxp_context.h index 45369f21c..135a6b93e 100644 --- a/edxp-core/src/main/cpp/main/src/edxp_context.h +++ b/edxp-core/src/main/cpp/main/src/edxp_context.h @@ -8,6 +8,13 @@ namespace edxp { #define SYSTEM_SERVER_DATA_DIR "/data/user/0/android" + enum Variant { + NONE = 0, + YAHFA = 1, + SANDHOOK = 2, + WHALE = 3 + }; + class Context { public: @@ -52,6 +59,7 @@ namespace edxp { private: static Context *instance_; bool initialized_ = false; + Variant variant_ = NONE; jobject inject_class_loader_ = nullptr; jclass entry_class_ = nullptr; jstring app_data_dir_ = nullptr; diff --git a/edxp-core/src/main/cpp/main/src/jni/edxp_resources_hook.cpp b/edxp-core/src/main/cpp/main/src/jni/edxp_resources_hook.cpp index ab834d87a..17c20939b 100644 --- a/edxp-core/src/main/cpp/main/src/jni/edxp_resources_hook.cpp +++ b/edxp-core/src/main/cpp/main/src/jni/edxp_resources_hook.cpp @@ -16,8 +16,8 @@ namespace edxp { jclass class_clazz = JNI_FindClass(env, "java/lang/Class"); jfieldID java_lang_Class_accessFlags = JNI_GetFieldID( env, class_clazz, "accessFlags", "I"); - jint access_flags = env->GetIntField(clazz, java_lang_Class_accessFlags); - env->SetIntField(clazz, java_lang_Class_accessFlags, access_flags & ~kAccFinal); + jint access_flags = env->GetIntField(target_class, java_lang_Class_accessFlags); + env->SetIntField(target_class, java_lang_Class_accessFlags, access_flags & ~kAccFinal); return JNI_TRUE; } return JNI_FALSE; diff --git a/edxp-core/src/main/cpp/main/src/main.cpp b/edxp-core/src/main/cpp/main/src/main.cpp index 66026e436..94b24eb8d 100644 --- a/edxp-core/src/main/cpp/main/src/main.cpp +++ b/edxp-core/src/main/cpp/main/src/main.cpp @@ -19,67 +19,65 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-value" -namespace edxp { +#define EXPORT extern "C" __attribute__((visibility("default"))) - extern "C" { +namespace edxp { - __attribute__((visibility("default"))) void onModuleLoaded() { + EXPORT void onModuleLoaded() { LOG(INFO) << "onModuleLoaded: welcome to EdXposed!"; InstallInlineHooks(); } - __attribute__((visibility("default"))) int shouldSkipUid(int uid) { + EXPORT int shouldSkipUid(int uid) { return 0; } - __attribute__((visibility("default"))) void - nativeForkAndSpecializePre(JNIEnv *env, jclass clazz, jint *_uid, jint *gid, jintArray *gids, - jint *runtime_flags, - jobjectArray *rlimits, jint *mount_external, jstring *se_info, - jstring *se_name, - jintArray *fds_to_close, jintArray *fds_to_ignore, - jboolean *is_child_zygote, - jstring *instruction_set, jstring *app_data_dir, - jstring *package_name, - jobjectArray *packages_for_uid, jstring *sandbox_id) { + EXPORT void nativeForkAndSpecializePre(JNIEnv *env, jclass clazz, jint *_uid, jint *gid, + jintArray *gids, jint *runtime_flags, + jobjectArray *rlimits, jint *mount_external, + jstring *se_info, jstring *nice_name, + jintArray *fds_to_close, jintArray *fds_to_ignore, + jboolean *start_child_zygote, jstring *instruction_set, + jstring *app_data_dir, + /* parameters added in Android Q */ + jstring *package_name, jobjectArray *packages_for_uid, + jstring *sandbox_id) { Context::GetInstance()->OnNativeForkAndSpecializePre(env, clazz, *_uid, *gid, *gids, *runtime_flags, *rlimits, - *mount_external, *se_info, *se_name, + *mount_external, *se_info, *nice_name, *fds_to_close, *fds_to_ignore, - *is_child_zygote, *instruction_set, + *start_child_zygote, *instruction_set, *app_data_dir); } - __attribute__((visibility("default"))) int - nativeForkAndSpecializePost(JNIEnv *env, jclass clazz, - jint res) { + EXPORT int nativeForkAndSpecializePost(JNIEnv *env, jclass clazz, jint res) { return Context::GetInstance()->OnNativeForkAndSpecializePost(env, clazz, res); } - __attribute__((visibility("default"))) - void - nativeForkSystemServerPre(JNIEnv *env, jclass clazz, uid_t *uid, gid_t *gid, jintArray *gids, - jint *runtime_flags, - jobjectArray *rlimits, jlong *permitted_capabilities, - jlong *effective_capabilities) { + EXPORT void nativeForkSystemServerPre(JNIEnv *env, jclass clazz, uid_t *uid, gid_t *gid, + jintArray *gids, jint *runtime_flags, + jobjectArray *rlimits, jlong *permitted_capabilities, + jlong *effective_capabilities) { Context::GetInstance()->OnNativeForkSystemServerPre(env, clazz, *uid, *gid, *gids, *runtime_flags, *rlimits, *permitted_capabilities, - *effective_capabilities); + *effective_capabilities + ); } - __attribute__((visibility("default"))) - int nativeForkSystemServerPost(JNIEnv *env, jclass clazz, jint res) { + EXPORT int nativeForkSystemServerPost(JNIEnv *env, jclass clazz, jint res) { return Context::GetInstance()->OnNativeForkSystemServerPost(env, clazz, res); } - __attribute__((visibility("default"))) void specializeAppProcessPre( - JNIEnv *env, jclass clazz, jint *_uid, jint *gid, jintArray *gids, jint *runtime_flags, - jobjectArray *rlimits, jint *mount_external, jstring *se_info, jstring *nice_name, - jboolean *start_child_zygote, jstring *instruction_set, jstring *app_data_dir, - jstring *package_name, jobjectArray *packages_for_uid, jstring *sandbox_id) { - Context::GetInstance()->OnNativeForkAndSpecializePre(env, clazz, *_uid, *gid, *gids, + /* method added in Android Q */ + EXPORT void specializeAppProcessPre(JNIEnv *env, jclass clazz, jint *uid, jint *gid, + jintArray *gids, jint *runtime_flags, jobjectArray *rlimits, + jint *mount_external, jstring *se_info, jstring *nice_name, + jboolean *start_child_zygote, jstring *instruction_set, + jstring *app_data_dir, jstring *package_name, + jobjectArray *packages_for_uid, jstring *sandbox_id) { + Context::GetInstance()->OnNativeForkAndSpecializePre(env, clazz, *uid, *gid, *gids, *runtime_flags, *rlimits, *mount_external, *se_info, *nice_name, nullptr, nullptr, @@ -87,13 +85,10 @@ namespace edxp { *app_data_dir); } - __attribute__((visibility("default"))) int specializeAppProcessPost( - JNIEnv *env, jclass clazz) { + EXPORT int specializeAppProcessPost(JNIEnv *env, jclass clazz) { return Context::GetInstance()->OnNativeForkAndSpecializePost(env, clazz, 0); } - } - } #pragma clang diagnostic pop \ No newline at end of file diff --git a/edxp-core/src/main/cpp/main/src/native_hook.cpp b/edxp-core/src/main/cpp/main/src/native_hook.cpp index 83e991456..8b436b356 100644 --- a/edxp-core/src/main/cpp/main/src/native_hook.cpp +++ b/edxp-core/src/main/cpp/main/src/native_hook.cpp @@ -15,10 +15,27 @@ #include "art/runtime/mirror/class.h" #include "art/runtime/class_linker.h" #include "art/runtime/gc/heap.h" +#include "framework/fd_utils.h" namespace edxp { static bool installed = false; + static bool art_hooks_installed = false; + static bool fwk_hooks_installed = false; + static HookFunType hook_func = nullptr; + + void InstallArtHooks(void *art_handle); + + void InstallFwkHooks(void *fwk_handle); + + CREATE_HOOK_STUB_ENTRIES(void *, mydlopen, const char *file_name, int flags, + const void *caller) { + void *handle = mydlopenBackup(file_name, flags, caller); + if (file_name != nullptr && std::string(file_name).find(kLibArtName) != std::string::npos) { + InstallArtHooks(handle); + } + return handle; + } void InstallInlineHooks() { if (installed) { @@ -45,17 +62,39 @@ namespace edxp { if (!hook_func_symbol) { return; } - auto hook_func = reinterpret_cast(hook_func_symbol); - ScopedDlHandle art_handle(kLibArtPath.c_str()); - if (!art_handle.IsValid()) { + hook_func = reinterpret_cast(hook_func_symbol); + + if (api_level >= ANDROID_P) { + ScopedDlHandle dl_handle(kLibDlPath.c_str()); + void *handle = dl_handle.Get(); + HOOK_FUNC(mydlopen, "__loader_dlopen"); + } else { + ScopedDlHandle art_handle(kLibArtPath.c_str()); + InstallArtHooks(art_handle.Get()); + } + + ScopedDlHandle fwk_handle(kLibFwkPath.c_str()); + InstallFwkHooks(fwk_handle.Get()); + } + + void InstallArtHooks(void *art_handle) { + if (art_hooks_installed) { + return; + } + art::Runtime::Setup(art_handle, hook_func); + art::gc::Heap::Setup(art_handle, hook_func); + art::ClassLinker::Setup(art_handle, hook_func); + art::mirror::Class::Setup(art_handle, hook_func); + art::JNIEnvExt::Setup(art_handle, hook_func); + art_hooks_installed = true; + LOGI("ART hooks installed"); + } + + void InstallFwkHooks(void *fwk_handle) { + if (fwk_hooks_installed) { return; } - art::Runtime::Setup(art_handle.Get(), hook_func); - art::gc::Heap::Setup(art_handle.Get(), hook_func); - art::ClassLinker::Setup(art_handle.Get(), hook_func); - art::mirror::Class::Setup(art_handle.Get(), hook_func); - art::JNIEnvExt::Setup(art_handle.Get(), hook_func); - LOGI("Inline hooks installed"); + android::FileDescriptorWhitelist::Setup(fwk_handle, hook_func); } } diff --git a/edxp-core/template_override/common/util_functions.sh b/edxp-core/template_override/common/util_functions.sh index 3c34c3579..00ca706c8 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.4_alpha (4340)" +EDXP_VERSION="0.4.4.5_alpha (4450)" ANDROID_SDK=`getprop ro.build.version.sdk` BUILD_DESC=`getprop ro.build.description` PRODUCT=`getprop ro.build.product` @@ -79,7 +79,7 @@ start_log_cather () { } start_verbose_log_catcher () { - start_log_cather all.log "EdXposed:V EdXposed-Fwk:V EdXposed-dexmaker:V XSharedPreferences:V EdXposed-Bridge:V EdXposed-YAHFA:V EdXposed-Manager:V XposedInstaller:V" true ${LOG_VERBOSE} + start_log_cather all.log "EdXposed:V XSharedPreferences:V EdXposed-Bridge:V EdXposed-Manager:V XposedInstaller:V" true ${LOG_VERBOSE} } start_bridge_log_catcher () { diff --git a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/dexmaker/DexLog.java b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/dexmaker/DexLog.java index b2dd0f119..d24b28f29 100644 --- a/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/dexmaker/DexLog.java +++ b/edxp-sandhook/src/main/java/com/elderdrivers/riru/edxp/sandhook/dexmaker/DexLog.java @@ -2,11 +2,11 @@ import android.util.Log; -import com.elderdrivers.riru.edxp.BuildConfig; +import com.elderdrivers.riru.edxp.sandhook.BuildConfig; public class DexLog { - public static final String TAG = "EdXposed-dexmaker"; + public static final String TAG = "EdXposed"; public static int v(String s) { return Log.v(TAG, s); 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 index e0272c2b5..2280ca53d 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 @@ -3,7 +3,7 @@ import android.app.ActivityThread; import com.elderdrivers.riru.common.KeepMembers; -import com.elderdrivers.riru.edxp._hooker.impl.OneplusWorkaround; +import com.elderdrivers.riru.edxp._hooker.impl.SystemMain; import com.swift.sandhook.SandHook; import com.swift.sandhook.annotation.HookClass; import com.swift.sandhook.annotation.HookMethod; @@ -30,7 +30,7 @@ public class SystemMainHooker implements KeepMembers { @HookMethod("systemMain") public static ActivityThread hook() throws Throwable { - final XC_MethodHook methodHook = new OneplusWorkaround(); + final XC_MethodHook methodHook = new SystemMain(); final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam(); param.thisObject = null; param.args = new Object[]{}; 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 a29d621fe..ed21c1bb0 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 @@ -6,7 +6,7 @@ import com.elderdrivers.riru.edxp.config.ConfigManager; import com.swift.sandhook.SandHook; -import com.swift.sandhook.xposedcompat.classloaders.ComposeClassLoader; +import com.elderdrivers.riru.edxp.util.ComposeClassLoader; import com.swift.sandhook.xposedcompat.methodgen.SandHookXposedBridge; import com.swift.sandhook.xposedcompat.utils.ApplicationUtils; import com.swift.sandhook.xposedcompat.utils.FileUtils; diff --git a/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/SandHookXposedBridge.java b/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/SandHookXposedBridge.java index 6d8cd1ec6..aa30436d6 100644 --- a/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/SandHookXposedBridge.java +++ b/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/SandHookXposedBridge.java @@ -3,6 +3,7 @@ import android.os.Process; import android.os.Trace; +import com.elderdrivers.riru.edxp.util.ClassLoaderUtils; import com.swift.sandhook.SandHook; import com.swift.sandhook.SandHookConfig; import com.swift.sandhook.blacklist.HookBlackList; @@ -31,7 +32,7 @@ public final class SandHookXposedBridge { private static final AtomicBoolean dexPathInited = new AtomicBoolean(false); private static File dexDir; - public static Map entityMap = new ConcurrentHashMap<>(); + public static Map entityMap = new ConcurrentHashMap<>(); public static boolean hooked(Member member) { return hookedInfo.containsKey(member) || entityMap.containsKey(member); @@ -76,7 +77,9 @@ public static synchronized void hookMethod(Member hookMethod, XposedBridge.Addit hookMaker = defaultHookMaker; } hookMaker.start(hookMethod, additionalHookInfo, - hookMethod.getDeclaringClass().getClassLoader(), dexDir == null ? null : dexDir.getAbsolutePath()); + ClassLoaderUtils.createComposeClassLoader( + hookMethod.getDeclaringClass().getClassLoader()), + dexDir == null ? null : dexDir.getAbsolutePath()); hookedInfo.put(hookMethod, hookMaker.getCallBackupMethod()); } DexLog.d("hook method <" + hookMethod.toString() + "> cost " + (System.currentTimeMillis() - timeStart) + " ms, by " + (stub != null ? "internal stub" : "dex maker")); diff --git a/edxp-whale/src/main/java/com/lody/whale/WhaleRuntime.java b/edxp-whale/src/main/java/com/lody/whale/WhaleRuntime.java index 40160595d..a7f13d732 100644 --- a/edxp-whale/src/main/java/com/lody/whale/WhaleRuntime.java +++ b/edxp-whale/src/main/java/com/lody/whale/WhaleRuntime.java @@ -66,8 +66,6 @@ public static native Object invokeOriginalMethodNative(long slot, Object thisObj public static native void removeFinalFlagNative(Class cl); - /* public static native void enforceDisableHiddenAPIPolicy(); */ - private static native void reserved0(); private static native void reserved1(); diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/dexmaker/DexLog.java b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/dexmaker/DexLog.java index f77297372..0471190f1 100644 --- a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/dexmaker/DexLog.java +++ b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/dexmaker/DexLog.java @@ -2,11 +2,11 @@ import android.util.Log; -import com.elderdrivers.riru.edxp.BuildConfig; +import com.elderdrivers.riru.edxp.yahfa.BuildConfig; public class DexLog { - public static final String TAG = "EdXposed-dexmaker"; + public static final String TAG = "EdXposed"; public static int v(String s) { return Log.v(TAG, s); 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 e0f1a42b3..421b40512 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 @@ -6,6 +6,7 @@ import com.elderdrivers.riru.edxp.core.Yahfa; import com.elderdrivers.riru.edxp.core.yahfa.HookMain; +import com.elderdrivers.riru.edxp.util.ComposeClassLoader; import java.io.File; import java.lang.reflect.Constructor; @@ -177,9 +178,10 @@ public void start(Member member, XposedBridge.AdditionalHookInfo hookInfo, mDexDirPath = dexDirPath; if (appClassLoader == null || appClassLoader.getClass().getName().equals("java.lang.BootClassLoader")) { - mAppClassLoader = this.getClass().getClassLoader(); + mAppClassLoader = getClass().getClassLoader(); } else { mAppClassLoader = appClassLoader; + mAppClassLoader = new ComposeClassLoader(mAppClassLoader, getClass().getClassLoader()); } doMake(); } diff --git a/xposed-bridge/src/main/AndroidManifest.xml b/xposed-bridge/src/main/AndroidManifest.xml index cd2f6ed74..7a62fb963 100644 --- a/xposed-bridge/src/main/AndroidManifest.xml +++ b/xposed-bridge/src/main/AndroidManifest.xml @@ -1,2 +1 @@ - + diff --git a/xposed-bridge/src/main/java/de/robv/android/xposed/PendingHooks.java b/xposed-bridge/src/main/java/de/robv/android/xposed/PendingHooks.java new file mode 100644 index 000000000..ea8438293 --- /dev/null +++ b/xposed-bridge/src/main/java/de/robv/android/xposed/PendingHooks.java @@ -0,0 +1,24 @@ +package de.robv.android.xposed; + +import java.lang.reflect.Member; +import java.util.concurrent.ConcurrentHashMap; + +import static de.robv.android.xposed.XposedBridge.hookMethodNative; + +public final class PendingHooks { + + private static final ConcurrentHashMap + sPendingHookMethods = new ConcurrentHashMap<>(); + + public synchronized static void hookPendingMethod(Class clazz) { + for (Member member : sPendingHookMethods.keySet()) { + if (member.getDeclaringClass().equals(clazz)) { + hookMethodNative(member, clazz, 0, sPendingHookMethods.get(member)); + } + } + } + + public synchronized static void recordPendingMethod(Member hookMethod, XposedBridge.AdditionalHookInfo additionalInfo) { + sPendingHookMethods.put(hookMethod, additionalInfo); + } +} diff --git a/xposed-bridge/src/main/java/de/robv/android/xposed/XposedBridge.java b/xposed-bridge/src/main/java/de/robv/android/xposed/XposedBridge.java index fdaea140a..9be482d24 100644 --- a/xposed-bridge/src/main/java/de/robv/android/xposed/XposedBridge.java +++ b/xposed-bridge/src/main/java/de/robv/android/xposed/XposedBridge.java @@ -18,7 +18,6 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; import dalvik.system.InMemoryDexClassLoader; import de.robv.android.xposed.XC_MethodHook.MethodHookParam; @@ -235,29 +234,13 @@ public static XC_MethodHook.Unhook hookMethod(Member hookMethod, XC_MethodHook c if (reflectMethod != null) { hookMethodNative(reflectMethod, declaringClass, slot, additionalInfo); } else { - synchronized (pendingLock) { - sPendingHookMethods.put(hookMethod, additionalInfo); - } + PendingHooks.recordPendingMethod(hookMethod, additionalInfo); } } return callback.new Unhook(hookMethod); } - private static final ConcurrentHashMap - sPendingHookMethods = new ConcurrentHashMap<>(); - private static final Object pendingLock = new Object(); - - public static void hookPendingMethod(Class clazz) { - synchronized (pendingLock) { - for (Member member : sPendingHookMethods.keySet()) { - if (member.getDeclaringClass().equals(clazz)) { - hookMethodNative(member, clazz, 0, sPendingHookMethods.get(member)); - } - } - } - } - /** * Removes the callback for a hooked method/constructor. * @@ -448,7 +431,7 @@ public static void clearInitPackageResources() { * Intercept every call to the specified method and call a handler function instead. * @param method The method to intercept */ - private synchronized static void hookMethodNative(final Member method, Class declaringClass, + /*package*/ synchronized static void hookMethodNative(final Member method, Class declaringClass, int slot, final Object additionalInfoObj) { EdXpConfigGlobal.getHookProvider().hookMethod(method, (AdditionalHookInfo) additionalInfoObj); } From 5f9d44a2b8d46a0a5d3cf9e65c34ea7be3d2c9cf Mon Sep 17 00:00:00 2001 From: Justin <40630518+Juxstin@users.noreply.github.com> Date: Mon, 17 Jun 2019 13:17:35 -0500 Subject: [PATCH 5/5] Update To Latest Update To Latest --- appveyor.yml | 9 ++- .../riru/edxp/config/BaseEdxpConfig.java | 31 ++++++++++ .../riru/edxp/proxy/BlackWhiteListProxy.java | 4 ++ .../riru/edxp/util/ClassUtils.java | 12 ++++ edxp-core/build.gradle | 28 ++++++++- .../cpp/main/include/art/runtime/hidden_api.h | 57 +++++++++++++++++++ .../src/main/cpp/main/src/edxp_context.cpp | 11 +++- .../src/main/cpp/main/src/edxp_context.h | 5 +- .../common/util_functions.sh | 2 +- .../sandhook/config/SandHookEdxpConfig.java | 25 +------- .../classloaders/ComposeClassLoader.java | 34 ----------- .../edxp/whale/config/WhaleEdxpConfig.java | 25 +------- .../edxp/whale/config/WhaleHookProvider.java | 9 ++- .../riru/edxp/whale/core/WhaleEdxpImpl.java | 2 + .../riru/edxp/whale/core/WhaleRouter.java | 15 +++++ .../edxp/yahfa/config/YahfaEdxpConfig.java | 25 +------- .../edxp/yahfa/config/YahfaHookProvider.java | 5 +- .../edxp/yahfa/dexmaker/DexMakerUtils.java | 21 ------- .../riru/edxp/config/EdXpConfig.java | 3 +- .../riru/edxp/config/EdXpConfigGlobal.java | 4 +- .../android/xposed/IXposedHookZygoteInit.java | 33 ++++++++++- .../de/robv/android/xposed/XposedBridge.java | 19 +++++++ .../de/robv/android/xposed/XposedInit.java | 12 +++- .../xposed/callbacks/XC_InitZygote.java | 39 +++++++++++++ 24 files changed, 288 insertions(+), 142 deletions(-) create mode 100644 edxp-common/src/main/java/com/elderdrivers/riru/edxp/config/BaseEdxpConfig.java create mode 100644 edxp-core/src/main/cpp/main/include/art/runtime/hidden_api.h delete mode 100644 edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/classloaders/ComposeClassLoader.java create mode 100644 xposed-bridge/src/main/java/de/robv/android/xposed/callbacks/XC_InitZygote.java diff --git a/appveyor.yml b/appveyor.yml index 12f8182b6..c149e1ef2 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,3 +1,5 @@ +version: '0.4.4.6_alpha({build})' + environment: ANDROID_HOME: C:\android-sdk-windows @@ -20,6 +22,9 @@ build_script: artifacts: - path: 'edxp-core\release\**\*.zip' +pull_requests: + do_not_increment_build_number: true + only_commits: files: - dalvikdx/ @@ -34,6 +39,4 @@ only_commits: - build.gradle - settings.gradle - gradle.properties - - appveyor.yml - -version: '0.4.4.5_alpha (4450) {build}' + - appveyor.yml \ No newline at end of file diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/config/BaseEdxpConfig.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/config/BaseEdxpConfig.java new file mode 100644 index 000000000..a05c399fa --- /dev/null +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/config/BaseEdxpConfig.java @@ -0,0 +1,31 @@ +package com.elderdrivers.riru.edxp.config; + +import com.elderdrivers.riru.edxp.hooker.XposedBlackListHooker; + +public class BaseEdxpConfig implements EdxpConfig { + + @Override + public String getInstallerBaseDir() { + return InstallerChooser.INSTALLER_DATA_BASE_DIR; + } + + @Override + public String getBlackListModulePackageName() { + return XposedBlackListHooker.BLACK_LIST_PACKAGE_NAME; + } + + @Override + public boolean isDynamicModulesMode() { + return ConfigManager.isDynamicModulesEnabled(); + } + + @Override + public boolean isResourcesHookEnabled() { + return ConfigManager.isResourcesHookEnabled(); + } + + @Override + public boolean isBlackWhiteListMode() { + return ConfigManager.isBlackWhiteListEnabled(); + } +} diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BlackWhiteListProxy.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BlackWhiteListProxy.java index 88bd5a117..217a48d18 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BlackWhiteListProxy.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/proxy/BlackWhiteListProxy.java @@ -106,6 +106,9 @@ private void onForkPostCommon(boolean isSystemServer, String appDataDir, String mRouter.installBootstrapHooks(isSystemServer); if (isDynamicModulesMode) { mRouter.loadModulesSafely(false); + } else { + XposedBridge.callInitZygotes(); + XposedBridge.clearInitZygotes(); // one-time use } mRouter.onForkFinish(); } @@ -130,5 +133,6 @@ private boolean checkNeedHook(String appDataDir, String niceName) { private static void onBlackListed() { XposedBridge.clearLoadedPackages(); XposedBridge.clearInitPackageResources(); + XposedBridge.clearInitZygotes(); } } diff --git a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ClassUtils.java b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ClassUtils.java index bd46ded36..872d7b219 100644 --- a/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ClassUtils.java +++ b/edxp-common/src/main/java/com/elderdrivers/riru/edxp/util/ClassUtils.java @@ -2,6 +2,9 @@ import android.os.Build; +import java.lang.reflect.Member; +import java.lang.reflect.Modifier; + import de.robv.android.xposed.XposedHelpers; public class ClassUtils { @@ -33,4 +36,13 @@ public static boolean isInitialized(Class clazz) { } } + public static boolean shouldDelayHook(Member hookMethod) { + if (hookMethod == null) { + return false; + } + Class declaringClass = hookMethod.getDeclaringClass(); + return Modifier.isStatic(hookMethod.getModifiers()) + && !ClassUtils.isInitialized(declaringClass); + } + } diff --git a/edxp-core/build.gradle b/edxp-core/build.gradle index 6e9f38d03..72a04dcc3 100644 --- a/edxp-core/build.gradle +++ b/edxp-core/build.gradle @@ -3,10 +3,24 @@ import org.gradle.internal.os.OperatingSystem apply plugin: 'com.android.library' -version "v0.4.4.5_alpha" +// Values set here will be overriden by AppVeyor, feel free to modify during development. +def buildVersionName = 'v0.4.4.6_alpha' +def buildVersionCode = 10000 + +if (System.env.APPVEYOR_BUILD_VERSION != null) { + buildVersionName = "v${System.getenv('appveyor_build_version')}" +} + +if (System.env.APPVEYOR_BUILD_NUMBER != null) { + // Split is necessary because PRs set the build number to "1234-something". + def parts = System.env.APPVEYOR_BUILD_NUMBER.split('-') + buildVersionCode = Integer.valueOf(parts[0]) +} + +version buildVersionName ext { - versionCode = "4450" + versionCode = buildVersionCode module_name = "EdXposed" jar_dest_dir = "${projectDir}/template_override/system/framework/" is_windows = OperatingSystem.current().isWindows() @@ -130,7 +144,7 @@ afterEvaluate { into templateRootPath rename "module.prop.tpl", "module.prop" expand(moduleId: "$magiskModuleId", backend: "$backendCapped", - versionName: "$version" + "($backend)", + versionName: "$version" + " ($backend)", versionCode: "$versionCode", authorList: "$authorList") filter(FixCrLfFilter.class, eol: FixCrLfFilter.CrLf.newInstance("lf")) } @@ -146,6 +160,14 @@ afterEvaluate { from "${projectDir}/template_override" into zipPathMagiskRelease } + copy { + from "${projectDir}/template_override/common/util_functions.sh" + into "${zipPathMagiskRelease}/common" + filter { line -> line + .replaceAll('%VERSION%', "$version") + .replaceAll('%VERSION_CODE%', "$versionCode") + .replaceAll('%BACKEND%', "$backendCapped") } + } copy { from 'template_override/riru_module.prop' into "$zipPathMagiskRelease/data/misc/riru/modules/${riruModuleId}" diff --git a/edxp-core/src/main/cpp/main/include/art/runtime/hidden_api.h b/edxp-core/src/main/cpp/main/include/art/runtime/hidden_api.h new file mode 100644 index 000000000..abb3d394d --- /dev/null +++ b/edxp-core/src/main/cpp/main/include/art/runtime/hidden_api.h @@ -0,0 +1,57 @@ + +#pragma once + +#include "base/object.h" + +namespace art { + + namespace hidden_api { + + enum Action { + kAllow, + kAllowButWarn, + kAllowButWarnAndToast, + kDeny + }; + + CREATE_HOOK_STUB_ENTRIES(Action, GetMethodActionImpl) { + return Action::kAllow; + } + + CREATE_HOOK_STUB_ENTRIES(Action, GetFieldActionImpl) { + return Action::kAllow; + } + + CREATE_HOOK_STUB_ENTRIES(bool, ShouldDenyAccessToMethodImpl) { + return false; + } + + CREATE_HOOK_STUB_ENTRIES(bool, ShouldDenyAccessToFieldImpl) { + return false; + } + + static void DisableHiddenApi(void *handle, HookFunType hook_func) { + const int api_level = GetAndroidApiLevel(); + if (api_level < ANDROID_P) { + return; + } + if (api_level == ANDROID_P) { + HOOK_FUNC(GetMethodActionImpl, + "_ZN3art9hiddenapi6detail19GetMemberActionImplINS_9ArtMethodEEENS0_" + "6ActionEPT_NS_20HiddenApiAccessFlags7ApiListES4_NS0_12AccessMethodE"); + HOOK_FUNC(GetFieldActionImpl, + "_ZN3art9hiddenapi6detail19GetMemberActionImplINS_8ArtFieldEEENS0_" + "6ActionEPT_NS_20HiddenApiAccessFlags7ApiListES4_NS0_12AccessMethodE"); + } else { + HOOK_FUNC(ShouldDenyAccessToMethodImpl, + "_ZN3art9hiddenapi6detail28ShouldDenyAccessToMemberImplINS_" + "9ArtMethodEEEbPT_NS0_7ApiListENS0_12AccessMethodE"); + HOOK_FUNC(ShouldDenyAccessToFieldImpl, + "_ZN3art9hiddenapi6detail28ShouldDenyAccessToMemberImplINS_" + "8ArtFieldEEEbPT_NS0_7ApiListENS0_12AccessMethodE"); + } + }; + + } + +} diff --git a/edxp-core/src/main/cpp/main/src/edxp_context.cpp b/edxp-core/src/main/cpp/main/src/edxp_context.cpp index dd2a66402..9b4b18230 100644 --- a/edxp-core/src/main/cpp/main/src/edxp_context.cpp +++ b/edxp-core/src/main/cpp/main/src/edxp_context.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include "edxp_context.h" #include "config_manager.h" @@ -30,7 +31,15 @@ namespace edxp { return instance_; } - ALWAYS_INLINE inline jobject Context::GetCurrentClassLoader() const { + ALWAYS_INLINE bool Context::IsInitialized() const { + return initialized_; + } + + ALWAYS_INLINE Variant Context::GetVariant() const { + return variant_; + } + + ALWAYS_INLINE jobject Context::GetCurrentClassLoader() const { return inject_class_loader_; } diff --git a/edxp-core/src/main/cpp/main/src/edxp_context.h b/edxp-core/src/main/cpp/main/src/edxp_context.h index 135a6b93e..e8480ac8e 100644 --- a/edxp-core/src/main/cpp/main/src/edxp_context.h +++ b/edxp-core/src/main/cpp/main/src/edxp_context.h @@ -56,6 +56,10 @@ namespace edxp { jlong permitted_capabilities, jlong effective_capabilities); + bool IsInitialized() const; + + Variant GetVariant() const; + private: static Context *instance_; bool initialized_ = false; @@ -75,7 +79,6 @@ namespace edxp { void LoadDexAndInit(JNIEnv *env, const char *dex_path); jclass FindClassFromLoader(JNIEnv *env, jobject class_loader, const char *class_name) const; - }; } diff --git a/edxp-core/template_override/common/util_functions.sh b/edxp-core/template_override/common/util_functions.sh index 00ca706c8..770ffd5df 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.4.5_alpha (4450)" +EDXP_VERSION="%VERSION% (%BACKEND%)" ANDROID_SDK=`getprop ro.build.version.sdk` BUILD_DESC=`getprop ro.build.description` PRODUCT=`getprop ro.build.product` 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 8d52e4116..e79224b25 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,28 +1,7 @@ package com.elderdrivers.riru.edxp.sandhook.config; -import com.elderdrivers.riru.edxp.config.ConfigManager; -import com.elderdrivers.riru.edxp.config.EdXpConfig; -import com.elderdrivers.riru.edxp.config.InstallerChooser; -import com.elderdrivers.riru.edxp.hooker.XposedBlackListHooker; +import com.elderdrivers.riru.edxp.config.BaseEdxpConfig; -public class SandHookEdxpConfig implements EdXpConfig { - @Override - public String getInstallerBaseDir() { - return InstallerChooser.INSTALLER_DATA_BASE_DIR; - } +public class SandHookEdxpConfig extends BaseEdxpConfig { - @Override - public String getBlackListModulePackageName() { - return XposedBlackListHooker.BLACK_LIST_PACKAGE_NAME; - } - - @Override - public boolean isDynamicModulesMode() { - return ConfigManager.isDynamicModulesEnabled(); - } - - @Override - public boolean isResourcesHookEnabled() { - return ConfigManager.isResourcesHookEnabled(); - } } diff --git a/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/classloaders/ComposeClassLoader.java b/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/classloaders/ComposeClassLoader.java deleted file mode 100644 index 6d968f6f1..000000000 --- a/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/classloaders/ComposeClassLoader.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.swift.sandhook.xposedcompat.classloaders; - -/** - * Created by weishu on 17/11/30. - */ - -public class ComposeClassLoader extends ClassLoader { - - private final ClassLoader mAppClassLoader; - public ComposeClassLoader(ClassLoader parent, ClassLoader appClassLoader) { - super(parent); - mAppClassLoader = appClassLoader; - } - - @Override - protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - Class clazz = null; - - try { - clazz = mAppClassLoader.loadClass(name); - } catch (ClassNotFoundException e) { - // IGNORE. - } - if (clazz == null) { - clazz = super.loadClass(name, resolve); - } - - if (clazz == null) { - throw new ClassNotFoundException(); - } - - return clazz; - } -} 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 f3172399f..c02808d79 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,28 +1,7 @@ package com.elderdrivers.riru.edxp.whale.config; -import com.elderdrivers.riru.edxp.config.ConfigManager; -import com.elderdrivers.riru.edxp.config.EdXpConfig; -import com.elderdrivers.riru.edxp.config.InstallerChooser; -import com.elderdrivers.riru.edxp.hooker.XposedBlackListHooker; +import com.elderdrivers.riru.edxp.config.BaseEdxpConfig; -public class WhaleEdxpConfig implements EdXpConfig { - @Override - public String getInstallerBaseDir() { - return InstallerChooser.INSTALLER_DATA_BASE_DIR; - } +public class WhaleEdxpConfig extends BaseEdxpConfig { - @Override - public String getBlackListModulePackageName() { - return XposedBlackListHooker.BLACK_LIST_PACKAGE_NAME; - } - - @Override - public boolean isDynamicModulesMode() { - return ConfigManager.isDynamicModulesEnabled(); - } - - @Override - public boolean isResourcesHookEnabled() { - return ConfigManager.isResourcesHookEnabled(); - } } 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 cbf5cbf5a..534f4d370 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,9 +1,11 @@ package com.elderdrivers.riru.edxp.whale.config; import com.elderdrivers.riru.edxp.art.ClassLinker; +import com.elderdrivers.riru.edxp.art.Heap; import com.elderdrivers.riru.edxp.config.BaseHookProvider; import com.elderdrivers.riru.edxp.core.ResourcesHook; import com.elderdrivers.riru.edxp.core.Yahfa; +import com.elderdrivers.riru.edxp.util.Utils; import com.lody.whale.WhaleRuntime; import java.lang.reflect.Member; @@ -13,6 +15,9 @@ import java.util.Map; import de.robv.android.xposed.XposedBridge; +import de.robv.android.xposed.XposedHelpers; + +import static com.elderdrivers.riru.edxp.util.ClassUtils.shouldDelayHook; public class WhaleHookProvider extends BaseHookProvider { @@ -27,7 +32,7 @@ public void unhookMethod(Member method) { @Override public void hookMethod(Member method, XposedBridge.AdditionalHookInfo additionalInfo) { - resolveStaticMethod(method); +// resolveStaticMethod(method); long slot = WhaleRuntime.hookMethodNative(method.getDeclaringClass(), method, additionalInfo); synchronized (sHookedMethodSlotMap) { sHookedMethodSlotMap.put(method, slot); @@ -42,7 +47,7 @@ public Object invokeOriginalMethod(Member method, long methodId, Object thisObje @Override public Member findMethodNative(Member hookMethod) { - return hookMethod; + return shouldDelayHook(hookMethod) ? null : hookMethod; } @Override 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 index ccb13ef45..5f645b77b 100644 --- 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 @@ -7,6 +7,7 @@ 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.Router; @@ -39,4 +40,5 @@ public void init() { 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 index baa142e93..3d7cc11d8 100644 --- 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 @@ -1,11 +1,21 @@ package com.elderdrivers.riru.edxp.whale.core; +import android.app.ActivityThread; +import android.content.pm.ApplicationInfo; +import android.content.res.CompatibilityInfo; + +import com.elderdrivers.riru.edxp._hooker.impl.HandleBindApp; +import com.elderdrivers.riru.edxp._hooker.impl.LoadedApkCstr; +import com.elderdrivers.riru.edxp._hooker.yahfa.HandleBindAppHooker; +import com.elderdrivers.riru.edxp._hooker.yahfa.LoadedApkConstructorHooker; import com.elderdrivers.riru.edxp.config.EdXpConfigGlobal; +import com.elderdrivers.riru.edxp.framework.Zygote; 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; +import de.robv.android.xposed.XposedHelpers; public class WhaleRouter extends BaseRouter { @@ -14,9 +24,14 @@ public void onEnterChildProcess() { } public void injectConfig() { + BaseRouter.useXposedApi = true; EdXpConfigGlobal.sConfig = new WhaleEdxpConfig(); EdXpConfigGlobal.sHookProvider = new WhaleHookProvider(); XposedBridge.log("using HookProvider: " + EdXpConfigGlobal.sHookProvider.getClass().getName()); + Zygote.allowFileAcrossFork("/system/lib/libwhale.edxp.so"); + Zygote.allowFileAcrossFork("/system/lib64/libwhale.edxp.so"); + Zygote.allowFileAcrossFork("/system/lib/libart.so"); + Zygote.allowFileAcrossFork("/system/lib64/libart.so"); } } 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 8ea685508..e051a47ec 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,28 +1,7 @@ package com.elderdrivers.riru.edxp.yahfa.config; -import com.elderdrivers.riru.edxp.config.ConfigManager; -import com.elderdrivers.riru.edxp.config.EdXpConfig; -import com.elderdrivers.riru.edxp.config.InstallerChooser; -import com.elderdrivers.riru.edxp.hooker.XposedBlackListHooker; +import com.elderdrivers.riru.edxp.config.BaseEdxpConfig; -public class YahfaEdxpConfig implements EdXpConfig { - @Override - public String getInstallerBaseDir() { - return InstallerChooser.INSTALLER_DATA_BASE_DIR; - } +public class YahfaEdxpConfig extends BaseEdxpConfig { - @Override - public String getBlackListModulePackageName() { - return XposedBlackListHooker.BLACK_LIST_PACKAGE_NAME; - } - - @Override - public boolean isDynamicModulesMode() { - return ConfigManager.isDynamicModulesEnabled(); - } - - @Override - public boolean isResourcesHookEnabled() { - return ConfigManager.isResourcesHookEnabled(); - } } diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/config/YahfaHookProvider.java b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/config/YahfaHookProvider.java index 8eabd2e49..dbac995a3 100644 --- a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/config/YahfaHookProvider.java +++ b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/config/YahfaHookProvider.java @@ -4,13 +4,14 @@ import com.elderdrivers.riru.edxp.config.BaseHookProvider; import com.elderdrivers.riru.edxp.core.ResourcesHook; import com.elderdrivers.riru.edxp.core.Yahfa; -import com.elderdrivers.riru.edxp.yahfa.dexmaker.DexMakerUtils; import com.elderdrivers.riru.edxp.yahfa.dexmaker.DynamicBridge; import java.lang.reflect.Member; import de.robv.android.xposed.XposedBridge; +import static com.elderdrivers.riru.edxp.util.ClassUtils.shouldDelayHook; + public class YahfaHookProvider extends BaseHookProvider { @Override @@ -25,7 +26,7 @@ public Object invokeOriginalMethod(Member method, long methodId, Object thisObje @Override public Member findMethodNative(Member hookMethod) { - return DexMakerUtils.findMethodNative(hookMethod); + return shouldDelayHook(hookMethod) ? null : hookMethod; } @Override 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 9d9f3e8a6..8fbf22dca 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 @@ -5,11 +5,7 @@ import android.text.TextUtils; import com.elderdrivers.riru.edxp.config.ConfigManager; -import com.elderdrivers.riru.edxp.util.ClassUtils; -import com.elderdrivers.riru.edxp.util.Utils; -import java.lang.reflect.Member; -import java.lang.reflect.Modifier; import java.security.MessageDigest; import java.util.HashMap; import java.util.Map; @@ -246,21 +242,4 @@ public static String getSha1Hex(String text) { } return ""; } - - public static Member findMethodNative(Member hookMethod) { - if (shouldDelayHook(hookMethod)) { - Utils.logD("solo: " + hookMethod + " hooking delayed."); - return null; - } - return hookMethod; - } - - private static boolean shouldDelayHook(Member hookMethod) { - if (hookMethod == null) { - return false; - } - Class declaringClass = hookMethod.getDeclaringClass(); - return Modifier.isStatic(hookMethod.getModifiers()) - && !ClassUtils.isInitialized(declaringClass); - } } diff --git a/xposed-bridge/src/main/java/com/elderdrivers/riru/edxp/config/EdXpConfig.java b/xposed-bridge/src/main/java/com/elderdrivers/riru/edxp/config/EdXpConfig.java index 39882a25d..4a12da208 100644 --- a/xposed-bridge/src/main/java/com/elderdrivers/riru/edxp/config/EdXpConfig.java +++ b/xposed-bridge/src/main/java/com/elderdrivers/riru/edxp/config/EdXpConfig.java @@ -1,6 +1,6 @@ package com.elderdrivers.riru.edxp.config; -public interface EdXpConfig { +public interface EdxpConfig { String getInstallerBaseDir(); @@ -10,4 +10,5 @@ public interface EdXpConfig { boolean isResourcesHookEnabled(); + boolean isBlackWhiteListMode(); } diff --git a/xposed-bridge/src/main/java/com/elderdrivers/riru/edxp/config/EdXpConfigGlobal.java b/xposed-bridge/src/main/java/com/elderdrivers/riru/edxp/config/EdXpConfigGlobal.java index 0d94ae2d2..6cb93ac58 100644 --- a/xposed-bridge/src/main/java/com/elderdrivers/riru/edxp/config/EdXpConfigGlobal.java +++ b/xposed-bridge/src/main/java/com/elderdrivers/riru/edxp/config/EdXpConfigGlobal.java @@ -4,10 +4,10 @@ public class EdXpConfigGlobal { - public static volatile EdXpConfig sConfig; + public static volatile EdxpConfig sConfig; public static volatile HookProvider sHookProvider; - public static EdXpConfig getConfig() { + public static EdxpConfig getConfig() { if (sConfig == null) { throw new IllegalArgumentException("sConfig should not be null."); } diff --git a/xposed-bridge/src/main/java/de/robv/android/xposed/IXposedHookZygoteInit.java b/xposed-bridge/src/main/java/de/robv/android/xposed/IXposedHookZygoteInit.java index dc130a766..4f1597746 100644 --- a/xposed-bridge/src/main/java/de/robv/android/xposed/IXposedHookZygoteInit.java +++ b/xposed-bridge/src/main/java/de/robv/android/xposed/IXposedHookZygoteInit.java @@ -1,5 +1,8 @@ package de.robv.android.xposed; +import de.robv.android.xposed.callbacks.XC_InitZygote; +import de.robv.android.xposed.callbacks.XCallback; + /** * Hook the initialization of Zygote process(es), from which all the apps are forked. * @@ -20,9 +23,17 @@ public interface IXposedHookZygoteInit extends IXposedMod { void initZygote(StartupParam startupParam) throws Throwable; /** Data holder for {@link #initZygote}. */ - final class StartupParam { + final class StartupParam extends XCallback.Param { /*package*/ StartupParam() {} + /** + * @param callbacks + * @hide + */ + public StartupParam(XposedBridge.CopyOnWriteSortedSet callbacks) { + super(callbacks); + } + /** The path to the module's APK. */ public String modulePath; @@ -32,4 +43,24 @@ final class StartupParam { */ public boolean startsSystemServer; } + + /** + * @hide + */ + final class Wrapper extends XC_InitZygote { + private final IXposedHookZygoteInit instance; + private final StartupParam startupParam; + + public Wrapper(IXposedHookZygoteInit instance, StartupParam startupParam) { + this.instance = instance; + this.startupParam = startupParam; + } + + @Override + public void initZygote(StartupParam startupParam) throws Throwable { + // NOTE: parameter startupParam not used + // cause startupParam info is generated and saved along with instance here + instance.initZygote(this.startupParam); + } + } } diff --git a/xposed-bridge/src/main/java/de/robv/android/xposed/XposedBridge.java b/xposed-bridge/src/main/java/de/robv/android/xposed/XposedBridge.java index 9be482d24..76e9a8265 100644 --- a/xposed-bridge/src/main/java/de/robv/android/xposed/XposedBridge.java +++ b/xposed-bridge/src/main/java/de/robv/android/xposed/XposedBridge.java @@ -22,7 +22,9 @@ import dalvik.system.InMemoryDexClassLoader; import de.robv.android.xposed.XC_MethodHook.MethodHookParam; import de.robv.android.xposed.callbacks.XC_InitPackageResources; +import de.robv.android.xposed.callbacks.XC_InitZygote; import de.robv.android.xposed.callbacks.XC_LoadPackage; +import de.robv.android.xposed.callbacks.XCallback; import external.com.android.dx.DexMaker; import external.com.android.dx.TypeId; @@ -67,6 +69,7 @@ public final class XposedBridge { public static final Map> sHookedMethodCallbacks = new HashMap<>(); public static final CopyOnWriteSortedSet sLoadedPackageCallbacks = new CopyOnWriteSortedSet<>(); /*package*/ static final CopyOnWriteSortedSet sInitPackageResourcesCallbacks = new CopyOnWriteSortedSet<>(); + /*package*/ static final CopyOnWriteSortedSet sInitZygoteCallbacks = new CopyOnWriteSortedSet<>(); private XposedBridge() {} @@ -427,6 +430,22 @@ public static void clearInitPackageResources() { } } + public static void hookInitZygote(XC_InitZygote callback) { + synchronized (sInitZygoteCallbacks) { + sInitZygoteCallbacks.add(callback); + } + } + + public static void clearInitZygotes() { + synchronized (sInitZygoteCallbacks) { + sInitZygoteCallbacks.clear(); + } + } + + public static void callInitZygotes() { + XCallback.callAll(new IXposedHookZygoteInit.StartupParam(sInitZygoteCallbacks)); + } + /** * Intercept every call to the specified method and call a handler function instead. * @param method The method to intercept diff --git a/xposed-bridge/src/main/java/de/robv/android/xposed/XposedInit.java b/xposed-bridge/src/main/java/de/robv/android/xposed/XposedInit.java index 19936fa8d..14dd7b878 100644 --- a/xposed-bridge/src/main/java/de/robv/android/xposed/XposedInit.java +++ b/xposed-bridge/src/main/java/de/robv/android/xposed/XposedInit.java @@ -414,7 +414,17 @@ private static void loadModule(String apk, ClassLoader topClassLoader) { IXposedHookZygoteInit.StartupParam param = new IXposedHookZygoteInit.StartupParam(); param.modulePath = apk; param.startsSystemServer = startsSystemServer; - ((IXposedHookZygoteInit) moduleInstance).initZygote(param); + if (EdXpConfigGlobal.getConfig().isBlackWhiteListMode() + && !EdXpConfigGlobal.getConfig().isDynamicModulesMode()) { + // postpone initZygote callbacks under black/white list mode + // if dynamic modules mode is on, callback directly cause we + // are already in app process here + XposedBridge.hookInitZygote(new IXposedHookZygoteInit.Wrapper( + (IXposedHookZygoteInit) moduleInstance, param)); + } else { + // FIXME under dynamic modules mode, initZygote is called twice + ((IXposedHookZygoteInit) moduleInstance).initZygote(param); + } } if (moduleInstance instanceof IXposedHookLoadPackage) diff --git a/xposed-bridge/src/main/java/de/robv/android/xposed/callbacks/XC_InitZygote.java b/xposed-bridge/src/main/java/de/robv/android/xposed/callbacks/XC_InitZygote.java new file mode 100644 index 000000000..60c05252c --- /dev/null +++ b/xposed-bridge/src/main/java/de/robv/android/xposed/callbacks/XC_InitZygote.java @@ -0,0 +1,39 @@ +package de.robv.android.xposed.callbacks; + +import de.robv.android.xposed.IXposedHookZygoteInit; + +/** + * This class is only used for internal purposes, except for the {@link StartupParam} + * subclass. + */ +public abstract class XC_InitZygote extends XCallback implements IXposedHookZygoteInit { + + /** + * Creates a new callback with default priority. + * + * @hide + */ + @SuppressWarnings("deprecation") + public XC_InitZygote() { + super(); + } + + /** + * Creates a new callback with a specific priority. + * + * @param priority See {@link XCallback#priority}. + * @hide + */ + public XC_InitZygote(int priority) { + super(priority); + } + + /** + * @hide + */ + @Override + protected void call(Param param) throws Throwable { + if (param instanceof StartupParam) + initZygote((StartupParam) param); + } +}