Move sandhook cache to /data/misc

Close #681
This commit is contained in:
LoveSy 2020-12-24 20:22:42 +08:00 committed by 双草酸酯
parent c84c09b2d5
commit 9553af5bb7
6 changed files with 57 additions and 41 deletions

View File

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

View File

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

View File

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

View File

@ -33,13 +33,10 @@ public final class SandHookXposedBridge {
private static final Map<Member, Method> 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<Member, HookMethodEntity> 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"));

View File

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

View File

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