Fix wrong dex path when using compat mode in some cases
This commit is contained in:
parent
285ced4cf9
commit
5a2cf52450
|
|
@ -5,6 +5,7 @@ import android.os.Build;
|
|||
|
||||
import com.elderdrivers.riru.common.KeepAll;
|
||||
import com.elderdrivers.riru.xposed.core.HookMethodResolver;
|
||||
import com.elderdrivers.riru.xposed.dexmaker.DynamicBridge;
|
||||
import com.elderdrivers.riru.xposed.entry.Router;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
|
@ -55,9 +56,11 @@ public class Main implements KeepAll {
|
|||
sIsGlobalMode = isGlobalMode;
|
||||
sIsDynamicModules = isDynamicModules;
|
||||
if (isGlobalMode) {
|
||||
// do bootstrap hooking only once in zygote process
|
||||
Router.onProcessForked(false);
|
||||
}
|
||||
if (!sIsDynamicModules) {
|
||||
if (!isDynamicModules) {
|
||||
// load modules only once in zygote process
|
||||
Router.loadModulesSafely();
|
||||
}
|
||||
}
|
||||
|
|
@ -65,11 +68,14 @@ public class Main implements KeepAll {
|
|||
public static void forkAndSpecializePost(int pid, String appDataDir) {
|
||||
// Utils.logD(sForkAndSpecializePramsStr + " = " + pid);
|
||||
if (pid == 0) {
|
||||
DynamicBridge.onForkPost();
|
||||
// in app process
|
||||
if (!sIsGlobalMode) {
|
||||
// do bootstrap hooking separately for each app process
|
||||
Router.onProcessForked(false);
|
||||
}
|
||||
if (sIsDynamicModules) {
|
||||
// load modules for each app process on its forked
|
||||
Router.loadModulesSafely();
|
||||
}
|
||||
} else {
|
||||
|
|
@ -83,7 +89,8 @@ 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/";
|
||||
sAppDataDir = getDataPathPrefix() + "android";
|
||||
// system_server process doesn't need sIsGlobalMode and sIsDynamicModules
|
||||
}
|
||||
|
||||
public static void forkSystemServerPost(int pid) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
package com.elderdrivers.riru.xposed.dexmaker;
|
||||
|
||||
import android.app.AndroidAppHelper;
|
||||
|
||||
import com.elderdrivers.riru.xposed.Main;
|
||||
import com.elderdrivers.riru.xposed.util.FileUtils;
|
||||
|
||||
|
|
@ -18,22 +16,19 @@ import de.robv.android.xposed.XposedBridge;
|
|||
|
||||
import static com.elderdrivers.riru.xposed.dexmaker.DexMakerUtils.shouldUseInMemoryHook;
|
||||
import static com.elderdrivers.riru.xposed.util.FileUtils.getDataPathPrefix;
|
||||
import static com.elderdrivers.riru.xposed.util.FileUtils.getPackageName;
|
||||
import static com.elderdrivers.riru.xposed.util.ProcessUtils.getCurrentProcessName;
|
||||
|
||||
public final class DynamicBridge {
|
||||
|
||||
private static final HashMap<Member, Method> hookedInfo = new HashMap<>();
|
||||
private static final HookerDexMaker dexMaker = new HookerDexMaker();
|
||||
private static final AtomicBoolean dexPathInited = new AtomicBoolean(false);
|
||||
private static final File dexDir;
|
||||
private static final File dexOptDir;
|
||||
private static File dexDir;
|
||||
private static File dexOptDir;
|
||||
|
||||
static {
|
||||
// we always choose to use device encrypted storage data on android n and later
|
||||
// in case some app is installing hooks before phone is unlocked
|
||||
String fixedAppDataDir = getDataPathPrefix() + AndroidAppHelper.currentPackageName() + "/";
|
||||
dexDir = new File(fixedAppDataDir, "/cache/edhookers/"
|
||||
+ Main.sAppProcessName.replace(":", "_") + "/");
|
||||
dexOptDir = new File(dexDir, "oat");
|
||||
public static void onForkPost() {
|
||||
dexPathInited.set(false);
|
||||
}
|
||||
|
||||
public static synchronized void hookMethod(Member hookMethod, XposedBridge.AdditionalHookInfo additionalHookInfo) {
|
||||
|
|
@ -51,20 +46,30 @@ public final class DynamicBridge {
|
|||
try {
|
||||
// for Android Oreo and later use InMemoryClassLoader
|
||||
if (!shouldUseInMemoryHook()) {
|
||||
// under Android Oreo, using DexClassLoader
|
||||
// using file based DexClassLoader
|
||||
if (dexPathInited.compareAndSet(false, true)) {
|
||||
// delete previous compiled dex to prevent potential crashing
|
||||
// TODO find a way to reuse them in consideration of performance
|
||||
try {
|
||||
// we always choose to use device encrypted storage data on android N and later
|
||||
// in case some app is installing hooks before phone is unlocked
|
||||
String fixedAppDataDir = getDataPathPrefix() + getPackageName(Main.sAppDataDir) + "/";
|
||||
dexDir = new File(fixedAppDataDir, "/cache/edhookers/"
|
||||
+ getCurrentProcessName().replace(":", "_") + "/");
|
||||
dexOptDir = new File(dexDir, "oat");
|
||||
dexDir.mkdirs();
|
||||
DexLog.d(Main.sAppProcessName + " deleting dir: " + dexOptDir.getAbsolutePath());
|
||||
FileUtils.delete(dexOptDir);
|
||||
try {
|
||||
FileUtils.delete(dexOptDir);
|
||||
} catch (Throwable throwable) {
|
||||
}
|
||||
} catch (Throwable throwable) {
|
||||
DexLog.e("error when init dex path", throwable);
|
||||
}
|
||||
}
|
||||
}
|
||||
dexMaker.start(hookMethod, additionalHookInfo,
|
||||
hookMethod.getDeclaringClass().getClassLoader(), dexDir.getAbsolutePath());
|
||||
hookMethod.getDeclaringClass().getClassLoader(), dexDir == null ? null : dexDir.getAbsolutePath());
|
||||
hookedInfo.put(hookMethod, dexMaker.getCallBackupMethod());
|
||||
} catch (Exception e) {
|
||||
DexLog.e("error occur when generating dex. dexDir=" + dexDir, e);
|
||||
|
|
|
|||
|
|
@ -13,11 +13,11 @@ import de.robv.android.xposed.XposedInit;
|
|||
public class Router {
|
||||
|
||||
public static void onProcessForked(boolean isSystem) {
|
||||
// Initialize the Xposed framework and modules
|
||||
// Initialize the Xposed framework
|
||||
try {
|
||||
XposedInit.initForZygote(isSystem);
|
||||
} catch (Throwable t) {
|
||||
Utils.logE("Errors during Xposed initialization", t);
|
||||
Utils.logE("error during Xposed initialization", t);
|
||||
XposedBridge.disableHooks = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.elderdrivers.riru.xposed.util;
|
||||
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
|
|
@ -58,6 +59,18 @@ public class FileUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public static String getPackageName(String dataDir) {
|
||||
if (TextUtils.isEmpty(dataDir)) {
|
||||
Utils.logE("getPackageName using empty dataDir");
|
||||
return "";
|
||||
}
|
||||
int lastIndex = dataDir.lastIndexOf("/");
|
||||
if (lastIndex < 0) {
|
||||
return dataDir;
|
||||
}
|
||||
return dataDir.substring(lastIndex + 1);
|
||||
}
|
||||
|
||||
public static String getDataPathPrefix() {
|
||||
return IS_USING_PROTECTED_STORAGE ? "/data/user_de/0/" : "/data/data/";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,10 @@
|
|||
package com.elderdrivers.riru.xposed.util;
|
||||
|
||||
import android.os.Process;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.elderdrivers.riru.xposed.Main;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
|
|
@ -7,6 +12,14 @@ import java.io.InputStreamReader;
|
|||
|
||||
public class ProcessUtils {
|
||||
|
||||
public static String getCurrentProcessName() {
|
||||
String prettyName = Main.sAppProcessName;
|
||||
if (!TextUtils.isEmpty(prettyName)) {
|
||||
return prettyName;
|
||||
}
|
||||
return getProcessName(Process.myPid());
|
||||
}
|
||||
|
||||
/**
|
||||
* a common solution from https://stackoverflow.com/a/21389402
|
||||
* <p>
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ public final class XposedInit {
|
|||
public static final String INSTALLER_PACKAGE_NAME = "com.solohsu.android.edxp.manager";
|
||||
public static final String INSTALLER_LEGACY_PACKAGE_NAME = "de.robv.android.xposed.installer";
|
||||
@SuppressLint("SdCardPath")
|
||||
private static final String BASE_DIR = Build.VERSION.SDK_INT >= 24
|
||||
public static final String INSTALLER_DATA_BASE_DIR = Build.VERSION.SDK_INT >= 24
|
||||
? "/data/user_de/0/" + INSTALLER_PACKAGE_NAME + "/"
|
||||
: "/data/data/" + INSTALLER_PACKAGE_NAME + "/";
|
||||
private static final String INSTANT_RUN_CLASS = "com.android.tools.fd.runtime.BootstrapApplication";
|
||||
|
|
@ -89,7 +89,7 @@ public final class XposedInit {
|
|||
}
|
||||
|
||||
/**
|
||||
* Try to load all modules defined in <code>BASE_DIR/conf/modules.list</code>
|
||||
* Try to load all modules defined in <code>INSTALLER_DATA_BASE_DIR/conf/modules.list</code>
|
||||
*/
|
||||
private static volatile AtomicBoolean modulesLoaded = new AtomicBoolean(false);
|
||||
|
||||
|
|
@ -97,7 +97,7 @@ public final class XposedInit {
|
|||
if (!modulesLoaded.compareAndSet(false, true)) {
|
||||
return;
|
||||
}
|
||||
final String filename = BASE_DIR + "conf/modules.list";
|
||||
final String filename = INSTALLER_DATA_BASE_DIR + "conf/modules.list";
|
||||
BaseService service = SELinuxHelper.getAppDataFileService();
|
||||
if (!service.checkFileExists(filename)) {
|
||||
Log.e(TAG, "Cannot load any modules because " + filename + " was not found");
|
||||
|
|
|
|||
Loading…
Reference in New Issue