From ce5c2bbe471a8244e25cf5dfbf13d6b9882c46a2 Mon Sep 17 00:00:00 2001 From: solohsu Date: Sun, 27 Jan 2019 19:35:33 +0800 Subject: [PATCH] Add support for EdXp Manager --- .../com/elderdrivers/riru/xposed/Main.java | 13 ++-- .../de/robv/android/xposed/XposedInit.java | 11 +++- Core/jni/main/Android.mk | 3 +- Core/jni/main/inject/config_manager.cpp | 65 +++++++++++++++++++ Core/jni/main/inject/config_manager.h | 12 ++++ Core/jni/main/inject/framework_hook.cpp | 21 +++++- 6 files changed, 113 insertions(+), 12 deletions(-) create mode 100644 Core/jni/main/inject/config_manager.cpp create mode 100644 Core/jni/main/inject/config_manager.h diff --git a/Bridge/src/main/java/com/elderdrivers/riru/xposed/Main.java b/Bridge/src/main/java/com/elderdrivers/riru/xposed/Main.java index 348dbf4e..e71ddf07 100644 --- a/Bridge/src/main/java/com/elderdrivers/riru/xposed/Main.java +++ b/Bridge/src/main/java/com/elderdrivers/riru/xposed/Main.java @@ -25,6 +25,7 @@ public class Main implements KeepAll { // private static String sForkSystemServerPramsStr = ""; public static String sAppDataDir = ""; public static String sAppProcessName = ""; + private static boolean sIsGlobalMode = false; static { init(Build.VERSION.SDK_INT); @@ -39,13 +40,16 @@ public class Main implements KeepAll { public static void forkAndSpecializePre(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, int[] fdsToIgnore, - boolean startChildZygote, String instructionSet, String appDataDir) { + boolean startChildZygote, String instructionSet, + String appDataDir, boolean isGlobalMode) { // sForkAndSpecializePramsStr = String.format( // "Zygote#forkAndSpecialize(%d, %d, %s, %d, %s, %d, %s, %s, %s, %s, %s, %s, %s)", // uid, gid, Arrays.toString(gids), debugFlags, Arrays.toString(rlimits), // mountExternal, seInfo, niceName, Arrays.toString(fdsToClose), // Arrays.toString(fdsToIgnore), startChildZygote, instructionSet, appDataDir); - if (!DYNAMIC_LOAD_MODULES) { + sAppDataDir = appDataDir; + sIsGlobalMode = isGlobalMode; + if (!DYNAMIC_LOAD_MODULES && isGlobalMode) { Router.onProcessForked(false); } } @@ -54,8 +58,7 @@ public class Main implements KeepAll { // Utils.logD(sForkAndSpecializePramsStr + " = " + pid); if (pid == 0) { // in app process - sAppDataDir = appDataDir; - if (DYNAMIC_LOAD_MODULES) { + if (DYNAMIC_LOAD_MODULES || !sIsGlobalMode) { Router.onProcessForked(false); } } else { @@ -69,13 +72,13 @@ public class Main implements KeepAll { // sForkSystemServerPramsStr = String.format("Zygote#forkSystemServer(%d, %d, %s, %d, %s, %d, %d)", // uid, gid, Arrays.toString(gids), debugFlags, Arrays.toString(rlimits), // permittedCapabilities, effectiveCapabilities); + sAppDataDir = getDataPathPrefix() + "android/"; } public static void forkSystemServerPost(int pid) { // Utils.logD(sForkSystemServerPramsStr + " = " + pid); if (pid == 0) { // in system_server process - sAppDataDir = getDataPathPrefix() + "android/"; Router.onProcessForked(true); } else { // in zygote process, res is child zygote pid diff --git a/Bridge/src/main/java/de/robv/android/xposed/XposedInit.java b/Bridge/src/main/java/de/robv/android/xposed/XposedInit.java index 6fae2d82..04c0036a 100644 --- a/Bridge/src/main/java/de/robv/android/xposed/XposedInit.java +++ b/Bridge/src/main/java/de/robv/android/xposed/XposedInit.java @@ -7,6 +7,7 @@ import android.text.TextUtils; import android.util.Log; import com.android.internal.os.ZygoteInit; +import com.elderdrivers.riru.xposed.BuildConfig; import com.elderdrivers.riru.xposed.entry.Router; import com.elderdrivers.riru.xposed.util.Utils; @@ -50,6 +51,7 @@ public final class XposedInit { } private static volatile AtomicBoolean bootstrapHooked = new AtomicBoolean(false); + /** * Hook some methods which we want to create an easier interface for developers. */ @@ -122,10 +124,12 @@ public final class XposedInit { * in assets/xposed_init. */ private static void loadModule(String apk, ClassLoader topClassLoader) { - Log.i(TAG, "Loading modules from " + apk); + if (BuildConfig.DEBUG) + Log.i(TAG, "Loading modules from " + apk); if (!TextUtils.isEmpty(apk) && apk.contains(BLACK_LIST_PACKAGE_NAME)) { - Log.i(TAG, "We are going to take over black list's job..."); + if (BuildConfig.DEBUG) + Log.i(TAG, "We are going to take over black list's job..."); return; } @@ -186,7 +190,8 @@ public final class XposedInit { continue; try { - Log.i(TAG, " Loading class " + moduleClassName); + if (BuildConfig.DEBUG) + Log.i(TAG, " Loading class " + moduleClassName); Class moduleClass = mcl.loadClass(moduleClassName); if (!IXposedMod.class.isAssignableFrom(moduleClass)) { diff --git a/Core/jni/main/Android.mk b/Core/jni/main/Android.mk index b8bff4fe..0abc2c81 100644 --- a/Core/jni/main/Android.mk +++ b/Core/jni/main/Android.mk @@ -18,6 +18,7 @@ LOCAL_SRC_FILES:= \ yahfa/HookMain.c \ yahfa/trampoline.c \ java_hook/java_hook.cpp \ - inject/framework_hook.cpp + inject/framework_hook.cpp \ + inject/config_manager.cpp include $(BUILD_SHARED_LIBRARY) \ No newline at end of file diff --git a/Core/jni/main/inject/config_manager.cpp b/Core/jni/main/inject/config_manager.cpp new file mode 100644 index 00000000..24683687 --- /dev/null +++ b/Core/jni/main/inject/config_manager.cpp @@ -0,0 +1,65 @@ +// +// Created by Solo on 2019/1/27. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "config_manager.h" + +#define BLACK_LIST_PATH "/data/misc/riru/modules/edxposed/blacklist/" +#define WHITE_LIST_PATH "/data/misc/riru/modules/edxposed/whitelist/" +#define USE_WHITE_LIST "/data/misc/riru/modules/edxposed/usewhitelist" +#define GLOBAL_MODE "/data/misc/riru/modules/edxposed/forceglobal" + +static char package_name[256]; + +// default is true +int is_app_need_hook(JNIEnv *env, jstring appDataDir) { + if (is_global_mode()) { + return 1; + } + if (!appDataDir) { + LOGW("appDataDir is null"); + return 1; + } + const char *app_data_dir = env->GetStringUTFChars(appDataDir, nullptr); + int user = 0; + if (sscanf(app_data_dir, "/data/%*[^/]/%d/%s", &user, package_name) != 2) { + if (sscanf(app_data_dir, "/data/%*[^/]/%s", package_name) != 1) { + package_name[0] = '\0'; + LOGW("can't parse %s", app_data_dir); + return 1; + } + } + env->ReleaseStringUTFChars(appDataDir, app_data_dir); + bool use_white_list = access(USE_WHITE_LIST, F_OK) == 0; + bool white_list_exists = access(WHITE_LIST_PATH, F_OK) == 0; + bool black_list_exists = access(BLACK_LIST_PATH, F_OK) == 0; + if (use_white_list && white_list_exists) { + char path[PATH_MAX]; + snprintf(path, PATH_MAX, WHITE_LIST_PATH "%s", package_name); + int res = access(path, F_OK) == 0; + LOGD("use whitelist, res=%d", res); + return res; + } else if (!use_white_list && black_list_exists) { + char path[PATH_MAX]; + snprintf(path, PATH_MAX, BLACK_LIST_PATH "%s", package_name); + int res = access(path, F_OK) != 0; + LOGD("use blacklist, res=%d", res); + return res; + } else { + LOGD("use nonlist, res=%d", 1); + return 1; + } +} + +int is_global_mode() { + return access(GLOBAL_MODE, F_OK) == 0; +} diff --git a/Core/jni/main/inject/config_manager.h b/Core/jni/main/inject/config_manager.h new file mode 100644 index 00000000..8cc0d4b8 --- /dev/null +++ b/Core/jni/main/inject/config_manager.h @@ -0,0 +1,12 @@ +// +// Created by Solo on 2019/1/27. +// + +#ifndef EDXPOSED_CONFIG_MANAGER_H +#define EDXPOSED_CONFIG_MANAGER_H + +int is_app_need_hook(JNIEnv *env, jstring appDataDir); + +int is_global_mode(); + +#endif //EDXPOSED_CONFIG_MANAGER_H diff --git a/Core/jni/main/inject/framework_hook.cpp b/Core/jni/main/inject/framework_hook.cpp index 69730328..2a61235c 100644 --- a/Core/jni/main/inject/framework_hook.cpp +++ b/Core/jni/main/inject/framework_hook.cpp @@ -5,6 +5,9 @@ #include #include "framework_hook.h" #include "include/misc.h" +#include "config_manager.h" + +#define SYSTEM_SERVER_DATA_DIR "/data/user/0/android/" static jclass sEntryClass; static jstring sAppDataDir; @@ -38,6 +41,9 @@ void findAndCall(JNIEnv *env, const char *methodName, const char *methodSig, ... void onNativeForkSystemServerPre(JNIEnv *env, jclass clazz, uid_t uid, gid_t gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jlong permittedCapabilities, jlong effectiveCapabilities) { + if (!is_app_need_hook(env, env->NewStringUTF(SYSTEM_SERVER_DATA_DIR))) { + return; + } prepareJavaEnv(env); // jump to java code findAndCall(env, "forkSystemServerPre", "(II[II[[IJJ)V", uid, gid, gids, runtime_flags, rlimits, @@ -47,6 +53,9 @@ void onNativeForkSystemServerPre(JNIEnv *env, jclass clazz, uid_t uid, gid_t gid int onNativeForkSystemServerPost(JNIEnv *env, jclass clazz, jint res) { if (res == 0) { + if (!is_app_need_hook(env, env->NewStringUTF(SYSTEM_SERVER_DATA_DIR))) { + return 0; + } prepareJavaEnv(env); // only do work in child since findAndCall would print log findAndCall(env, "forkSystemServerPost", "(I)V", res); @@ -70,17 +79,23 @@ void onNativeForkAndSpecializePre(JNIEnv *env, jclass clazz, jboolean is_child_zygote, jstring instructionSet, jstring appDataDir) { + sAppDataDir = appDataDir; + if (!is_app_need_hook(env, appDataDir)) { + return; + } prepareJavaEnv(env); findAndCall(env, "forkAndSpecializePre", - "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;)V", + "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;Z)V", uid, gid, gids, runtime_flags, rlimits, _mount_external, se_info, se_name, fdsToClose, fdsToIgnore, - is_child_zygote, instructionSet, appDataDir); - sAppDataDir = appDataDir; + is_child_zygote, instructionSet, appDataDir, is_global_mode()); } int onNativeForkAndSpecializePost(JNIEnv *env, jclass clazz, jint res) { if (res == 0) { + if (!is_app_need_hook(env, sAppDataDir)) { + return 0; + } prepareJavaEnv(env); findAndCall(env, "forkAndSpecializePost", "(ILjava/lang/String;)V", res, sAppDataDir); } else {