From 9553af5bb7018afe59bc75613797a3c403676228 Mon Sep 17 00:00:00 2001 From: LoveSy Date: Thu, 24 Dec 2020 20:22:42 +0800 Subject: [PATCH] Move sandhook cache to /data/misc Close #681 --- .../xposedcompat/methodgen/HookMaker.java | 2 +- .../methodgen/HookerDexMaker.java | 27 ++++++++--------- .../methodgen/HookerDexMakerNew.java | 20 +++++++------ .../methodgen/SandHookXposedBridge.java | 16 +--------- .../xposedcompat/utils/DexMakerUtils.java | 30 +++++++++++++++++++ .../edxp/yahfa/dexmaker/DexMakerUtils.java | 3 +- 6 files changed, 57 insertions(+), 41 deletions(-) diff --git a/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/HookMaker.java b/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/HookMaker.java index ae5c05e7..5433f603 100644 --- a/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/HookMaker.java +++ b/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/HookMaker.java @@ -7,7 +7,7 @@ import de.robv.android.xposed.XposedBridge; public interface HookMaker { void start(Member member, XposedBridge.AdditionalHookInfo hookInfo, - ClassLoader appClassLoader, String dexDirPath) throws Exception; + ClassLoader appClassLoader) throws Exception; Method getHookMethod(); Method getBackupMethod(); Method getCallBackupMethod(); diff --git a/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/HookerDexMaker.java b/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/HookerDexMaker.java index 465b2533..fa200569 100644 --- a/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/HookerDexMaker.java +++ b/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/HookerDexMaker.java @@ -1,7 +1,6 @@ package com.swift.sandhook.xposedcompat.methodgen; -import android.text.TextUtils; - +import com.elderdrivers.riru.edxp.config.ConfigManager; import com.swift.sandhook.SandHook; import com.swift.sandhook.SandHookMethodResolver; import com.swift.sandhook.wrapper.HookWrapper; @@ -9,7 +8,6 @@ import com.swift.sandhook.xposedcompat.XposedCompat; import com.swift.sandhook.xposedcompat.utils.DexLog; import java.io.File; -import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.Member; import java.lang.reflect.Method; @@ -33,8 +31,10 @@ import external.com.android.dx.TypeId; import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.MD5; import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.autoBoxIfNecessary; import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.autoUnboxIfNecessary; +import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.canCache; import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.createResultLocals; import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.getObjTypeIdIfPrimitive; +import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.getSha1Hex; public class HookerDexMaker implements HookMaker { @@ -110,7 +110,6 @@ public class HookerDexMaker implements HookMaker { private Method mHookMethod; private Method mBackupMethod; private Method mCallBackupMethod; - private String mDexDirPath; private static TypeId[] getParameterTypeIds(Class[] parameterTypes, boolean isStatic) { int parameterSize = parameterTypes.length; @@ -141,7 +140,7 @@ public class HookerDexMaker implements HookMaker { } public void start(Member member, XposedBridge.AdditionalHookInfo hookInfo, - ClassLoader appClassLoader, String dexDirPath) throws Exception { + ClassLoader appClassLoader) throws Exception { if (member instanceof Method) { Method method = (Method) member; mIsStatic = Modifier.isStatic(method.getModifiers()); @@ -174,7 +173,6 @@ public class HookerDexMaker implements HookMaker { } mMember = member; mHookInfo = hookInfo; - mDexDirPath = dexDirPath; if (appClassLoader == null || appClassLoader.getClass().getName().equals("java.lang.BootClassLoader")) { mAppClassLoader = this.getClass().getClassLoader(); @@ -190,7 +188,7 @@ public class HookerDexMaker implements HookMaker { HookWrapper.HookEntity hookEntity = null; //try load cache first try { - ClassLoader loader = mDexMaker.loadClassDirect(mAppClassLoader, new File(mDexDirPath), dexName); + ClassLoader loader = mDexMaker.loadClassDirect(mAppClassLoader, new File(ConfigManager.getCachePath("")), dexName); if (loader != null) { hookEntity = loadHookerClass(loader, className); } @@ -217,13 +215,12 @@ public class HookerDexMaker implements HookMaker { generateHookMethod(); ClassLoader loader; - if (TextUtils.isEmpty(mDexDirPath)) { - throw new IllegalArgumentException("dexDirPath should not be empty!!!"); - } - // Create the dex file and load it. - try { - loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(mDexDirPath), dexName, true); - } catch (IOException e) { + if (canCache) { + loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(ConfigManager.getCachePath("")), dexName, true); + File dexFile = new File(ConfigManager.getCachePath(dexName)); + dexFile.setWritable(true, false); + dexFile.setReadable(true, false); + } else { //can not write file byte[] dexBytes = mDexMaker.generate(); loader = new InMemoryDexClassLoader(ByteBuffer.wrap(dexBytes), mAppClassLoader); @@ -245,7 +242,7 @@ public class HookerDexMaker implements HookMaker { } private String getClassName(Member originMethod) { - return CLASS_NAME_PREFIX + "_" + MD5(originMethod.toString()); + return CLASS_NAME_PREFIX + "_" + getSha1Hex(originMethod.toString()); } public Method getHookMethod() { diff --git a/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/HookerDexMakerNew.java b/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/HookerDexMakerNew.java index 15902eae..cbc8fe18 100644 --- a/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/HookerDexMakerNew.java +++ b/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/HookerDexMakerNew.java @@ -1,7 +1,6 @@ package com.swift.sandhook.xposedcompat.methodgen; -import android.text.TextUtils; - +import com.elderdrivers.riru.edxp.config.ConfigManager; import com.swift.sandhook.SandHook; import com.swift.sandhook.wrapper.HookWrapper; import com.swift.sandhook.xposedcompat.hookstub.HookStubManager; @@ -28,8 +27,10 @@ import external.com.android.dx.TypeId; import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.MD5; import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.autoBoxIfNecessary; import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.autoUnboxIfNecessary; +import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.canCache; import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.createResultLocals; import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.getObjTypeIdIfPrimitive; +import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.getSha1Hex; public class HookerDexMakerNew implements HookMaker { @@ -70,7 +71,6 @@ public class HookerDexMakerNew implements HookMaker { private Class mHookClass; private Method mHookMethod; private Method mBackupMethod; - private String mDexDirPath; private static TypeId[] getParameterTypeIds(Class[] parameterTypes, boolean isStatic) { int parameterSize = parameterTypes.length; @@ -101,7 +101,7 @@ public class HookerDexMakerNew implements HookMaker { } public void start(Member member, XposedBridge.AdditionalHookInfo hookInfo, - ClassLoader appClassLoader, String dexDirPath) throws Exception { + ClassLoader appClassLoader) throws Exception { if (member instanceof Method) { Method method = (Method) member; mIsStatic = Modifier.isStatic(method.getModifiers()); @@ -134,7 +134,6 @@ public class HookerDexMakerNew implements HookMaker { } mMember = member; mHookInfo = hookInfo; - mDexDirPath = dexDirPath; if (appClassLoader == null || appClassLoader.getClass().getName().equals("java.lang.BootClassLoader")) { mAppClassLoader = this.getClass().getClassLoader(); @@ -150,7 +149,7 @@ public class HookerDexMakerNew implements HookMaker { HookWrapper.HookEntity hookEntity = null; //try load cache first try { - ClassLoader loader = mDexMaker.loadClassDirect(mAppClassLoader, new File(mDexDirPath), dexName); + ClassLoader loader = mDexMaker.loadClassDirect(mAppClassLoader, new File(ConfigManager.getCachePath("")), dexName); if (loader != null) { hookEntity = loadHookerClass(loader, className); } @@ -171,14 +170,17 @@ public class HookerDexMakerNew implements HookMaker { generateBackupMethod(); ClassLoader loader; - if (TextUtils.isEmpty(mDexDirPath)) { + if (!canCache) { byte[] dexBytes = mDexMaker.generate(); loader = new InMemoryDexClassLoader(ByteBuffer.wrap(dexBytes), mAppClassLoader); return loadHookerClass(loader, className); } // Create the dex file and load it. try { - loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(mDexDirPath), dexName, true); + loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(ConfigManager.getCachePath("")), dexName, true); + File dexFile = new File(ConfigManager.getCachePath(dexName)); + dexFile.setWritable(true, false); + dexFile.setReadable(true, false); } catch (IOException e) { //can not write file byte[] dexBytes = mDexMaker.generate(); @@ -203,7 +205,7 @@ public class HookerDexMakerNew implements HookMaker { } private String getClassName(Member originMethod) { - return CLASS_NAME_PREFIX + "_" + MD5(originMethod.toString()); + return CLASS_NAME_PREFIX + "_" + getSha1Hex(originMethod.toString()); } public Method getHookMethod() { diff --git a/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/SandHookXposedBridge.java b/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/SandHookXposedBridge.java index 45fcda7d..294dc459 100644 --- a/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/SandHookXposedBridge.java +++ b/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/SandHookXposedBridge.java @@ -33,13 +33,10 @@ public final class SandHookXposedBridge { private static final Map hookedInfo = new ConcurrentHashMap<>(); private static HookMaker defaultHookMaker = XposedCompat.useNewCallBackup ? new HookerDexMakerNew() : new HookerDexMaker(); - private static final AtomicBoolean dexPathInited = new AtomicBoolean(false); - private static File dexDir; public static Map entityMap = new ConcurrentHashMap<>(); public static void onForkPost() { - dexPathInited.set(false); XposedCompat.onForkProcess(); } @@ -61,16 +58,6 @@ public final class SandHookXposedBridge { Yahfa.recordHooked(hookMethod); // in case static method got reset. try { - if (dexPathInited.compareAndSet(false, true)) { - try { - String fixedAppDataDir = XposedCompat.getCacheDir().getAbsolutePath(); - dexDir = new File(fixedAppDataDir, "/hookers/"); - if (!dexDir.exists()) - dexDir.mkdirs(); - } catch (Throwable throwable) { - Log.e("SandHook", "error when init dex path", throwable); - } - } Trace.beginSection("SandXposed"); long timeStart = System.currentTimeMillis(); HookMethodEntity stub = null; @@ -89,8 +76,7 @@ public final class SandHookXposedBridge { } hookMaker.start(hookMethod, additionalHookInfo, ClassLoaderUtils.createProxyClassLoader( - hookMethod.getDeclaringClass().getClassLoader()), - dexDir == null ? null : dexDir.getAbsolutePath()); + hookMethod.getDeclaringClass().getClassLoader())); hookedInfo.put(hookMethod, hookMaker.getCallBackupMethod()); } DexLog.d("hook method <" + hookMethod.toString() + "> cost " + (System.currentTimeMillis() - timeStart) + " ms, by " + (stub != null ? "internal stub" : "dex maker")); diff --git a/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/utils/DexMakerUtils.java b/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/utils/DexMakerUtils.java index ad9142df..8f2e9e6b 100644 --- a/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/utils/DexMakerUtils.java +++ b/edxp-sandhook/src/main/java/com/swift/sandhook/xposedcompat/utils/DexMakerUtils.java @@ -1,6 +1,11 @@ package com.swift.sandhook.xposedcompat.utils; +import com.elderdrivers.riru.edxp.config.ConfigManager; +import com.elderdrivers.riru.edxp.util.Utils; + +import java.io.File; import java.lang.reflect.Method; import java.math.BigInteger; +import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.HashMap; @@ -12,6 +17,15 @@ import external.com.android.dx.TypeId; public class DexMakerUtils { + public static boolean canCache = true; + + static { + File cacheDir = new File(ConfigManager.getCachePath("")); + if(!cacheDir.canRead() || !cacheDir.canWrite()) { + Utils.logW("Cache disabled"); + canCache = false; + } + } private static volatile Method addInstMethod, specMethod; @@ -221,4 +235,20 @@ public class DexMakerUtils { } return source; } + + public static String getSha1Hex(String text) { + final MessageDigest digest; + try { + digest = MessageDigest.getInstance("SHA-1"); + byte[] result = digest.digest(text.getBytes(StandardCharsets.UTF_8)); + StringBuilder sb = new StringBuilder(); + for (byte b : result) { + sb.append(String.format("%02x", b)); + } + return sb.toString(); + } catch (Exception e) { + DexLog.e("error hashing target method: " + text, e); + } + return ""; + } } diff --git a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/dexmaker/DexMakerUtils.java b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/dexmaker/DexMakerUtils.java index 0cacd386..df9b36bb 100644 --- a/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/dexmaker/DexMakerUtils.java +++ b/edxp-yahfa/src/main/java/com/elderdrivers/riru/edxp/yahfa/dexmaker/DexMakerUtils.java @@ -4,6 +4,7 @@ import com.elderdrivers.riru.edxp.config.ConfigManager; import com.elderdrivers.riru.edxp.util.Utils; import java.io.File; +import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.util.HashMap; import java.util.Map; @@ -224,7 +225,7 @@ public class DexMakerUtils { final MessageDigest digest; try { digest = MessageDigest.getInstance("SHA-1"); - byte[] result = digest.digest(text.getBytes("UTF-8")); + byte[] result = digest.digest(text.getBytes(StandardCharsets.UTF_8)); StringBuilder sb = new StringBuilder(); for (byte b : result) { sb.append(String.format("%02x", b));