parent
c84c09b2d5
commit
9553af5bb7
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
|
|
|
|||
|
|
@ -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 "";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
Loading…
Reference in New Issue