Borrow Xposed BlackList module app to implement our own black list in kinda tricky way

This commit is contained in:
solohsu 2019-01-23 01:12:08 +08:00
parent 1aa63822d9
commit cda4ebba42
4 changed files with 110 additions and 2 deletions

View File

@ -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 {

View File

@ -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;

View File

@ -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);
}
}
}

View File

@ -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;