remove duplicated codes in edxp-sandhook

use the ones from `edxp-common` instead
This commit is contained in:
Victor Tseng 2020-03-23 22:09:16 +08:00 committed by Jim Wu
parent 12c74f165d
commit 9695a983b8
6 changed files with 5 additions and 354 deletions

View File

@ -1,24 +1,22 @@
package com.swift.sandhook.xposedcompat;
import android.annotation.SuppressLint;
import android.os.Process;
import android.text.TextUtils;
import com.elderdrivers.riru.edxp.config.ConfigManager;
import com.elderdrivers.riru.edxp.util.FileUtils;
import com.elderdrivers.riru.edxp.util.ProcessUtils;
import com.elderdrivers.riru.edxp.util.ProxyClassLoader;
import com.swift.sandhook.wrapper.HookWrapper;
import com.swift.sandhook.xposedcompat.methodgen.SandHookXposedBridge;
import com.swift.sandhook.xposedcompat.utils.ApplicationUtils;
import com.swift.sandhook.xposedcompat.utils.FileUtils;
import com.swift.sandhook.xposedcompat.utils.ProcessUtils;
import java.io.File;
import java.lang.reflect.Member;
import de.robv.android.xposed.XposedBridge;
import static com.elderdrivers.riru.edxp.util.ProcessUtils.PER_USER_RANGE;
import static com.swift.sandhook.xposedcompat.utils.FileUtils.IS_USING_PROTECTED_STORAGE;
import static com.elderdrivers.riru.edxp.util.FileUtils.getDataPathPrefix;
public class XposedCompat {
@ -54,7 +52,7 @@ public class XposedCompat {
if (cacheDir == null) {
String fixedAppDataDir = getDataPathPrefix() + getPackageName(ConfigManager.appDataDir) + "/";
cacheDir = new File(fixedAppDataDir, "/cache/sandhook/"
+ ProcessUtils.getProcessName().replace(":", "_") + "/");
+ ProcessUtils.getProcessName(Process.myPid()).replace(":", "_") + "/");
}
return cacheDir;
}
@ -104,12 +102,4 @@ public class XposedCompat {
return dataDir.substring(lastIndex + 1);
}
// FIXME: Although multi-users is considered here, but compat mode doesn't support other users' apps on Oreo and later yet.
@SuppressLint("SdCardPath")
public static String getDataPathPrefix() {
int userId = Process.myUid() / PER_USER_RANGE;
String format = IS_USING_PROTECTED_STORAGE ? "/data/user_de/%d/" : "/data/user/%d/";
return String.format(format, userId);
}
}

View File

@ -6,6 +6,7 @@ import android.os.Trace;
import android.util.Log;
import com.elderdrivers.riru.edxp.util.ClassLoaderUtils;
import com.elderdrivers.riru.edxp.util.FileUtils;
import com.swift.sandhook.SandHook;
import com.swift.sandhook.SandHookConfig;
import com.swift.sandhook.blacklist.HookBlackList;
@ -14,7 +15,6 @@ import com.swift.sandhook.xposedcompat.XposedCompat;
import com.swift.sandhook.xposedcompat.hookstub.HookMethodEntity;
import com.swift.sandhook.xposedcompat.hookstub.HookStubManager;
import com.swift.sandhook.xposedcompat.utils.DexLog;
import com.swift.sandhook.xposedcompat.utils.FileUtils;
import java.io.File;
import java.lang.reflect.Constructor;

View File

@ -1,106 +0,0 @@
package com.swift.sandhook.xposedcompat.utils;
import android.os.Build;
import android.util.ArrayMap;
import com.elderdrivers.riru.edxp.sandhook.BuildConfig;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import dalvik.system.PathClassLoader;
public class ClassLoaderUtils {
public static final String DEXPATH = "/system/framework/edxposed.dex:/system/framework/eddalvikdx.dex:/system/framework/eddexmaker.dex";
public static void replaceParentClassLoader(ClassLoader appClassLoader) {
if (appClassLoader == null) {
DexLog.e("appClassLoader is null, you might be kidding me?");
return;
}
try {
ClassLoader curCL = ClassLoaderUtils.class.getClassLoader();
ClassLoader parent = appClassLoader;
ClassLoader lastChild = appClassLoader;
while (parent != null) {
ClassLoader tmp = parent.getParent();
if (tmp == curCL) {
DexLog.d("replacing has been done before, skip.");
return;
}
if (tmp == null) {
DexLog.d("before replacing =========================================>");
dumpClassLoaders(appClassLoader);
Field parentField = ClassLoader.class.getDeclaredField("parent");
parentField.setAccessible(true);
parentField.set(curCL, parent);
parentField.set(lastChild, curCL);
DexLog.d("after replacing ==========================================>");
dumpClassLoaders(appClassLoader);
}
lastChild = parent;
parent = tmp;
}
} catch (Throwable throwable) {
DexLog.e("error when replacing class loader.", throwable);
}
}
private static void dumpClassLoaders(ClassLoader classLoader) {
if (BuildConfig.DEBUG) {
while (classLoader != null) {
DexLog.d(classLoader + " =>");
classLoader = classLoader.getParent();
}
}
}
public static List<ClassLoader> getAppClassLoader() {
List<ClassLoader> cacheLoaders = new ArrayList<>(0);
try {
DexLog.d("start getting app classloader");
Class appLoadersClass = Class.forName("android.app.ApplicationLoaders");
Field loadersField = appLoadersClass.getDeclaredField("gApplicationLoaders");
loadersField.setAccessible(true);
Object loaders = loadersField.get(null);
Field mLoaderMapField = loaders.getClass().getDeclaredField("mLoaders");
mLoaderMapField.setAccessible(true);
ArrayMap<String, ClassLoader> mLoaderMap = (ArrayMap<String, ClassLoader>) mLoaderMapField.get(loaders);
DexLog.d("mLoaders size = " + mLoaderMap.size());
cacheLoaders = new ArrayList<>(mLoaderMap.values());
} catch (Exception ex) {
DexLog.e("error get app class loader.", ex);
}
return cacheLoaders;
}
private static HashSet<ClassLoader> classLoaders = new HashSet<>();
public static boolean addPathToClassLoader(ClassLoader classLoader) {
if (!(classLoader instanceof PathClassLoader)) {
DexLog.w(classLoader + " is not a BaseDexClassLoader!!!");
return false;
}
if (classLoaders.contains(classLoader)) {
DexLog.d(classLoader + " has been hooked before");
return true;
}
try {
PathClassLoader baseDexClassLoader = (PathClassLoader) classLoader;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
//baseDexClassLoader.addDexPath(DEXPATH);
} else {
DexUtils.injectDexAtFirst(DEXPATH, baseDexClassLoader);
}
classLoaders.add(classLoader);
return true;
} catch (Throwable throwable) {
DexLog.e("error when addPath to ClassLoader: " + classLoader, throwable);
}
return false;
}
}

View File

@ -1,66 +0,0 @@
package com.swift.sandhook.xposedcompat.utils;
import android.annotation.TargetApi;
import android.os.Build;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import dalvik.system.BaseDexClassLoader;
import dalvik.system.DexClassLoader;
/**
* For 6.0 only.
*/
@TargetApi(Build.VERSION_CODES.M)
public class DexUtils {
public static void injectDexAtFirst(String dexPath, BaseDexClassLoader classLoader) throws NoSuchFieldException, IllegalAccessException, ClassNotFoundException {
DexClassLoader dexClassLoader = new DexClassLoader(dexPath, null, dexPath, classLoader);
Object baseDexElements = getDexElements(getPathList(classLoader));
Object newDexElements = getDexElements(getPathList(dexClassLoader));
Object allDexElements = combineArray(newDexElements, baseDexElements);
Object pathList = getPathList(classLoader);
setField(pathList, pathList.getClass(), "dexElements", allDexElements);
}
private static Object getDexElements(Object paramObject)
throws IllegalArgumentException, NoSuchFieldException, IllegalAccessException {
return getField(paramObject, paramObject.getClass(), "dexElements");
}
private static Object getPathList(Object baseDexClassLoader)
throws IllegalArgumentException, NoSuchFieldException, IllegalAccessException, ClassNotFoundException {
return getField(baseDexClassLoader, Class.forName("dalvik.system.BaseDexClassLoader"), "pathList");
}
private static Object combineArray(Object firstArray, Object secondArray) {
Class<?> localClass = firstArray.getClass().getComponentType();
int firstArrayLength = Array.getLength(firstArray);
int allLength = firstArrayLength + Array.getLength(secondArray);
Object result = Array.newInstance(localClass, allLength);
for (int k = 0; k < allLength; ++k) {
if (k < firstArrayLength) {
Array.set(result, k, Array.get(firstArray, k));
} else {
Array.set(result, k, Array.get(secondArray, k - firstArrayLength));
}
}
return result;
}
public static Object getField(Object obj, Class<?> cl, String field)
throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
Field localField = cl.getDeclaredField(field);
localField.setAccessible(true);
return localField.get(obj);
}
public static void setField(Object obj, Class<?> cl, String field, Object value)
throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
Field localField = cl.getDeclaredField(field);
localField.setAccessible(true);
localField.set(obj, value);
}
}

View File

@ -1,77 +0,0 @@
package com.swift.sandhook.xposedcompat.utils;
import android.os.Build;
import android.text.TextUtils;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class FileUtils {
public static final boolean IS_USING_PROTECTED_STORAGE = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N;
/**
* Delete a file or a directory and its children.
*
* @param file The directory to delete.
* @throws IOException Exception when problem occurs during deleting the directory.
*/
public static void delete(File file) throws IOException {
for (File childFile : file.listFiles()) {
if (childFile.isDirectory()) {
delete(childFile);
} else {
if (!childFile.delete()) {
throw new IOException();
}
}
}
if (!file.delete()) {
throw new IOException();
}
}
public static String readLine(File file) {
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
return reader.readLine();
} catch (Throwable throwable) {
return "";
}
}
public static void writeLine(File file, String line) {
try {
file.createNewFile();
} catch (IOException ex) {
}
try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
writer.write(line);
writer.flush();
} catch (Throwable throwable) {
DexLog.e("error writing line to file " + file + ": " + throwable.getMessage());
}
}
public static String getPackageName(String dataDir) {
if (TextUtils.isEmpty(dataDir)) {
DexLog.e("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/";
}
}

View File

@ -1,90 +0,0 @@
package com.swift.sandhook.xposedcompat.utils;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Process;
import android.text.TextUtils;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
/**
* Created by swift_gan on 2017/11/23.
*/
public class ProcessUtils {
public static String getProcessName() {
return getProcessName(Process.myPid());
}
private static String doGetProcessName(Context context) {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> runningApps = am.getRunningAppProcesses();
if (runningApps == null) {
return null;
}
for (ActivityManager.RunningAppProcessInfo proInfo : runningApps) {
if (proInfo.pid == android.os.Process.myPid()) {
if (proInfo.processName != null) {
return proInfo.processName;
}
}
}
return context.getPackageName();
}
public static String getProcessName(int pid) {
BufferedReader cmdlineReader = null;
try {
cmdlineReader = new BufferedReader(new InputStreamReader(
new FileInputStream(
"/proc/" + pid + "/cmdline"),
"iso-8859-1"));
int c;
StringBuilder processName = new StringBuilder();
while ((c = cmdlineReader.read()) > 0) {
processName.append((char) c);
}
return processName.toString();
} catch (Throwable throwable) {
DexLog.w("getProcessName: " + throwable.getMessage());
} finally {
try {
if (cmdlineReader != null) {
cmdlineReader.close();
}
} catch (Throwable throwable) {
DexLog.e("getProcessName: " + throwable.getMessage());
}
}
return "";
}
public static boolean isMainProcess(Context context) {
String processName = getProcessName();
String pkgName = context.getPackageName();
if (!TextUtils.isEmpty(processName) && !TextUtils.equals(processName, pkgName)) {
return false;
} else {
return true;
}
}
public static List<ResolveInfo> findActivitiesForPackage(Context context, String packageName) {
final PackageManager packageManager = context.getPackageManager();
final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
mainIntent.setPackage(packageName);
final List<ResolveInfo> apps = packageManager.queryIntentActivities(mainIntent, 0);
return apps != null ? apps : new ArrayList<ResolveInfo>();
}
}