Borrow Xposed BlackList module app to implement our own black list in kinda tricky way
This commit is contained in:
parent
1aa63822d9
commit
cda4ebba42
|
|
@ -11,6 +11,7 @@ import com.elderdrivers.riru.common.KeepMembers;
|
|||
import de.robv.android.xposed.XposedBridge;
|
||||
import de.robv.android.xposed.callbacks.XC_LoadPackage;
|
||||
|
||||
import static com.elderdrivers.riru.xposed.entry.hooker.XposedBlackListHooker.BLACK_LIST_PACKAGE_NAME;
|
||||
import static com.elderdrivers.riru.xposed.util.ClassLoaderUtils.replaceParentClassLoader;
|
||||
import static de.robv.android.xposed.XposedHelpers.getObjectField;
|
||||
import static de.robv.android.xposed.XposedHelpers.setObjectField;
|
||||
|
|
@ -27,7 +28,7 @@ public class HandleBindAppHooker implements KeepMembers {
|
|||
public static String methodSig = "(Landroid/app/ActivityThread$AppBindData;)V";
|
||||
|
||||
public static void hook(Object thiz, Object bindData) {
|
||||
if (XposedBridge.disableHooks) {
|
||||
if (XposedBlackListHooker.shouldDisableHooks("")) {
|
||||
backup(thiz, bindData);
|
||||
return;
|
||||
}
|
||||
|
|
@ -36,6 +37,11 @@ public class HandleBindAppHooker implements KeepMembers {
|
|||
ActivityThread activityThread = (ActivityThread) thiz;
|
||||
ApplicationInfo appInfo = (ApplicationInfo) getObjectField(bindData, "appInfo");
|
||||
String reportedPackageName = appInfo.packageName.equals("android") ? "system" : appInfo.packageName;
|
||||
|
||||
if (XposedBlackListHooker.shouldDisableHooks(reportedPackageName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ComponentName instrumentationName = (ComponentName) getObjectField(bindData, "instrumentationName");
|
||||
if (instrumentationName != null) {
|
||||
logD("Instrumentation detected, disabling framework for");
|
||||
|
|
@ -64,6 +70,9 @@ public class HandleBindAppHooker implements KeepMembers {
|
|||
if (reportedPackageName.equals(INSTALLER_PACKAGE_NAME)) {
|
||||
XposedInstallerHooker.hookXposedInstaller(lpparam.classLoader);
|
||||
}
|
||||
if (reportedPackageName.equals(BLACK_LIST_PACKAGE_NAME)) {
|
||||
XposedBlackListHooker.hook(lpparam.classLoader);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
logE("error when hooking bindApp", t);
|
||||
} finally {
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ public class LoadedApkConstructorHooker implements KeepMembers {
|
|||
ClassLoader baseLoader, boolean securityViolation,
|
||||
boolean includeCode, boolean registerPackage) {
|
||||
|
||||
if (XposedBridge.disableHooks) {
|
||||
if (XposedBlackListHooker.shouldDisableHooks("")) {
|
||||
backup(thiz, activityThread, aInfo, compatInfo, baseLoader, securityViolation,
|
||||
includeCode, registerPackage);
|
||||
return;
|
||||
|
|
@ -48,6 +48,11 @@ public class LoadedApkConstructorHooker implements KeepMembers {
|
|||
String packageName = loadedApk.getPackageName();
|
||||
Object mAppDir = getObjectField(thiz, "mAppDir");
|
||||
logD("LoadedApk#<init> ends: " + mAppDir);
|
||||
|
||||
if (XposedBlackListHooker.shouldDisableHooks(packageName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (packageName.equals("android")) {
|
||||
logD("LoadedApk#<init> is android, skip: " + mAppDir);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,87 @@
|
|||
package com.elderdrivers.riru.xposed.entry.hooker;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.os.Build;
|
||||
|
||||
import com.elderdrivers.riru.xposed.util.Utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import de.robv.android.xposed.XC_MethodHook;
|
||||
import de.robv.android.xposed.XSharedPreferences;
|
||||
import de.robv.android.xposed.XposedBridge;
|
||||
|
||||
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
|
||||
import static de.robv.android.xposed.XposedInit.INSTALLER_PACKAGE_NAME;
|
||||
|
||||
public class XposedBlackListHooker {
|
||||
|
||||
public static final String BLACK_LIST_PACKAGE_NAME = "com.flarejune.xposedblacklist";
|
||||
private static final boolean IS_USING_PROTECTED_STORAGE = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N;
|
||||
private static final String BLACK_LIST_PREF_NAME = "list";
|
||||
private static final String PREF_KEY_BLACK_LIST = "blackList";
|
||||
public static final String PREF_FILE_PATH = (IS_USING_PROTECTED_STORAGE ? "/data/user_de/0/" : "/data/data")
|
||||
+ BLACK_LIST_PACKAGE_NAME + "/shared_prefs/" + BLACK_LIST_PREF_NAME + ".xml";
|
||||
private static final XSharedPreferences PREFERENCES = new XSharedPreferences(new File(PREF_FILE_PATH));
|
||||
// always white list. empty string is to make sure blackList does not contain empty packageName
|
||||
private static final List<String> WHITE_LIST = Arrays.asList(INSTALLER_PACKAGE_NAME, BLACK_LIST_PACKAGE_NAME, "");
|
||||
|
||||
static {
|
||||
try {
|
||||
PREFERENCES.makeWorldReadable();
|
||||
} catch (Throwable throwable) {
|
||||
Utils.logE("error making pref worldReadable", throwable);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean shouldDisableHooks(String packageName) {
|
||||
return XposedBridge.disableHooks || getBlackList().contains(packageName);
|
||||
}
|
||||
|
||||
public static Set<String> getBlackList() {
|
||||
try {
|
||||
PREFERENCES.reload();
|
||||
Set<String> result = PREFERENCES.getStringSet(PREF_KEY_BLACK_LIST, new HashSet<String>());
|
||||
if (result != null) result.removeAll(WHITE_LIST);
|
||||
return result;
|
||||
} catch (Throwable throwable) {
|
||||
Utils.logE("error when reading black list", throwable);
|
||||
return new HashSet<>();
|
||||
}
|
||||
}
|
||||
|
||||
public static void hook(ClassLoader classLoader) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
findAndHookMethod(ContextWrapper.class, "getSharedPreferences", String.class, int.class, new XC_MethodHook() {
|
||||
@TargetApi(Build.VERSION_CODES.N)
|
||||
@Override
|
||||
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
|
||||
try {
|
||||
String prefName = (String) param.args[0];
|
||||
if (!prefName.equals(BLACK_LIST_PREF_NAME)) {
|
||||
return;
|
||||
}
|
||||
Activity activity = (Activity) param.thisObject;
|
||||
Context context = activity.createDeviceProtectedStorageContext();
|
||||
context.moveSharedPreferencesFrom(activity, prefName);
|
||||
param.setResult(context.getSharedPreferences(prefName, (int) param.args[1]));
|
||||
} catch (Throwable throwable) {
|
||||
Utils.logE("error hooking Xposed BlackList", throwable);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (Throwable throwable) {
|
||||
Utils.logE("error hooking Xposed BlackList", throwable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ package de.robv.android.xposed;
|
|||
import android.annotation.SuppressLint;
|
||||
import android.app.AndroidAppHelper;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.os.ZygoteInit;
|
||||
|
|
@ -23,6 +24,7 @@ import dalvik.system.DexFile;
|
|||
import dalvik.system.PathClassLoader;
|
||||
import de.robv.android.xposed.services.BaseService;
|
||||
|
||||
import static com.elderdrivers.riru.xposed.entry.hooker.XposedBlackListHooker.BLACK_LIST_PACKAGE_NAME;
|
||||
import static de.robv.android.xposed.XposedHelpers.closeSilently;
|
||||
import static de.robv.android.xposed.XposedHelpers.findClass;
|
||||
import static de.robv.android.xposed.XposedHelpers.findFieldIfExists;
|
||||
|
|
@ -122,6 +124,11 @@ public final class XposedInit {
|
|||
private static void loadModule(String apk, ClassLoader topClassLoader) {
|
||||
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...");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!new File(apk).exists()) {
|
||||
Log.e(TAG, " File does not exist");
|
||||
return;
|
||||
|
|
|
|||
Loading…
Reference in New Issue