SandHook: Cherry-pick from branch sandhook
e027b877732e90f41bf5ac48b5e652909ffc2140, 66d21874edb5b918ba16b2c8e3aebb80cc1558ff, 713e2e3b03038d87f2349a642d52a74c8695a6a9, eccdb67251c39910ff22f968597f9a309c9601b7, 9af84bdf02bd4321e9c1bd54b39d9638aa43a810, 68ce389a48c8bd5ae4eeefdbbc2e74363d103d89, dd7960c771a7c0ad453b5073df05c80a988ddb5e, 061288a6b835207c4e9e3948b366f2aba1d85d24, 8d2ea787e70e6e992581e54053f080aacafd9e25, 227fc5a43c94e8a0a976050fc1f2f43fdc9b0047
This commit is contained in:
parent
d546ecd81c
commit
d3cf2246ec
|
|
@ -12,4 +12,8 @@
|
|||
|
||||
#define ENTRY_CLASS_NAME "com.elderdrivers.riru.edxp.Main"
|
||||
|
||||
#define CLASS_SAND_HOOK "com.swift.sandhook.SandHook"
|
||||
|
||||
#define CLASS_NEVER_CALL "com.swift.sandhook.ClassNeverCall"
|
||||
|
||||
#endif //CONFIG_H
|
||||
|
|
@ -168,6 +168,29 @@ void loadDexAndInit(JNIEnv *env, const char *dexPath) {
|
|||
} else {
|
||||
LOGE("HookEntry class is null. %d", getpid());
|
||||
}
|
||||
|
||||
//load lib sandhook
|
||||
void* lib_sandhook;
|
||||
if (sizeof(void*) == 8) {
|
||||
lib_sandhook = dlopen("/system/lib64/libsandhook.edxp.so", RTLD_NOW);
|
||||
} else {
|
||||
lib_sandhook = dlopen("/system/lib/libsandhook.edxp.so", RTLD_NOW);
|
||||
}
|
||||
if (!lib_sandhook) {
|
||||
LOGW("libsandhook open failed. %s", dlerror());
|
||||
return;
|
||||
}
|
||||
bool* (*jni_load)(JNIEnv*, jclass, jclass) = reinterpret_cast<bool *(*)(JNIEnv *, jclass,
|
||||
jclass)>(dlsym(lib_sandhook, "JNI_Load_Ex"));
|
||||
|
||||
jclass sandhook_class = findClassFromLoader(env, myClassLoader, CLASS_SAND_HOOK);
|
||||
jclass nevercall_class = findClassFromLoader(env, myClassLoader, CLASS_NEVER_CALL);
|
||||
if (!sandhook_class || !nevercall_class) { // fail-fast
|
||||
return;
|
||||
}
|
||||
if (!jni_load(env, sandhook_class, nevercall_class)) {
|
||||
LOGE("SandHook: HookEntry class error. %d", getpid());
|
||||
}
|
||||
}
|
||||
|
||||
jstring getThrowableMessage(JNIEnv *env, jobject throwable) {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ dependencies {
|
|||
compileOnly files("libs/framework-stub.jar")
|
||||
implementation project(':edxp-common')
|
||||
implementation project(':xposed-bridge')
|
||||
implementation 'com.swift.sandhook:hooklib:3.0.1'
|
||||
implementation 'com.swift.sandhook:hooklib:3.2.2'
|
||||
compileOnly project(':dexmaker')
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,8 +60,9 @@ TEMP_STUB_INFO = """
|
|||
"""
|
||||
|
||||
|
||||
STUB_SIZES = [10,20,30,30,30,30,30,20,10,10,5,5,3]
|
||||
HAS_BACKUP = False;
|
||||
STUB_SIZES_32 = [10,20,30,30,30,30,30,20,10,10,5,5,3]
|
||||
STUB_SIZES_64 = [10,20,30,30,30,30,50,50]
|
||||
HAS_BACKUP = False
|
||||
|
||||
|
||||
def getMethodId(args, index):
|
||||
|
|
@ -126,20 +127,29 @@ def genCallOriginClass(is64Bit, args, index):
|
|||
method = TEMP_STUB_CALL_ORIGIN_CLASS % (getCallOriginClassName(args, index), getMethodBackupName(index), genArgsListForCallOriginMethod(is64Bit, args))
|
||||
return method
|
||||
|
||||
def genStubInfo():
|
||||
def genStubInfo32():
|
||||
hasStub = "true" if HAS_BACKUP else "false"
|
||||
stubSizes = ""
|
||||
for args in range(len(STUB_SIZES)):
|
||||
for args in range(len(STUB_SIZES_32)):
|
||||
if (args != 0):
|
||||
stubSizes += ", "
|
||||
stubSizes += str(STUB_SIZES[args])
|
||||
stubSizes += str(STUB_SIZES_32[args])
|
||||
return TEMP_STUB_INFO % (hasStub, stubSizes)
|
||||
|
||||
def genStubInfo64():
|
||||
hasStub = "true" if HAS_BACKUP else "false"
|
||||
stubSizes = ""
|
||||
for args in range(len(STUB_SIZES_64)):
|
||||
if (args != 0):
|
||||
stubSizes += ", "
|
||||
stubSizes += str(STUB_SIZES_64[args])
|
||||
return TEMP_STUB_INFO % (hasStub, stubSizes)
|
||||
|
||||
def gen32Stub(packageDir):
|
||||
class_content = genStubInfo()
|
||||
class_content = genStubInfo32()
|
||||
class_name = STUB_FILE_NAME + "32"
|
||||
for args in range(len(STUB_SIZES)):
|
||||
for index in range(STUB_SIZES[args]):
|
||||
for args in range(len(STUB_SIZES_32)):
|
||||
for index in range(STUB_SIZES_32[args]):
|
||||
class_content += """\n\n\t//stub of arg size %d, index %d""" % (args, index)
|
||||
class_content += genHookMethod(False, args, index)
|
||||
if HAS_BACKUP:
|
||||
|
|
@ -155,10 +165,10 @@ def gen32Stub(packageDir):
|
|||
|
||||
|
||||
def gen64Stub(packageDir):
|
||||
class_content = genStubInfo()
|
||||
class_content = genStubInfo64()
|
||||
class_name = STUB_FILE_NAME + "64"
|
||||
for args in range(len(STUB_SIZES)):
|
||||
for index in range(STUB_SIZES[args]):
|
||||
for args in range(len(STUB_SIZES_64)):
|
||||
for index in range(STUB_SIZES_64[args]):
|
||||
class_content += """\n\n\t//stub of arg size %d, index %d""" % (args, index)
|
||||
class_content += genHookMethod(True, args, index)
|
||||
if HAS_BACKUP:
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.elderdrivers.riru.edxp.sandhook.core.HookMethodResolver;
|
|||
import com.elderdrivers.riru.edxp.sandhook.entry.Router;
|
||||
import com.elderdrivers.riru.edxp.sandhook.proxy.BlackWhiteListProxy;
|
||||
import com.elderdrivers.riru.edxp.sandhook.proxy.NormalProxy;
|
||||
import com.swift.sandhook.xposedcompat.XposedCompat;
|
||||
import com.swift.sandhook.xposedcompat.methodgen.SandHookXposedBridge;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
|
@ -31,7 +32,12 @@ public class Main implements KeepAll {
|
|||
HookMethodResolver.init();
|
||||
Router.injectConfig();
|
||||
InstallerChooser.setInstallerPackageName(getInstallerPkgName());
|
||||
SandHookXposedBridge.setLibPath();
|
||||
SandHookXposedBridge.init();
|
||||
}
|
||||
|
||||
public static void setAppDataDir(String appDataDir) {
|
||||
Main.appDataDir = appDataDir;
|
||||
XposedCompat.appDataDir = appDataDir;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -1,11 +1,15 @@
|
|||
package com.elderdrivers.riru.edxp.sandhook.config;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.elderdrivers.riru.edxp.hook.HookProvider;
|
||||
import com.elderdrivers.riru.edxp.sandhook.dexmaker.DexMakerUtils;
|
||||
import com.elderdrivers.riru.edxp.sandhook.dexmaker.DynamicBridge;
|
||||
import com.elderdrivers.riru.edxp.sandhook.util.PrebuiltMethodsDeopter;
|
||||
import com.swift.sandhook.xposedcompat.XposedCompat;
|
||||
import com.swift.sandhook.xposedcompat.methodgen.SandHookXposedBridge;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Member;
|
||||
|
||||
import de.robv.android.xposed.XposedBridge;
|
||||
|
|
@ -13,12 +17,27 @@ import de.robv.android.xposed.XposedBridge;
|
|||
public class SandHookProvider implements HookProvider {
|
||||
@Override
|
||||
public void hookMethod(Member method, XposedBridge.AdditionalHookInfo additionalInfo) {
|
||||
if (SandHookXposedBridge.hooked(method) || DynamicBridge.hooked(method)) {
|
||||
return;
|
||||
}
|
||||
if (method.getDeclaringClass() == Log.class) {
|
||||
Log.e(XposedBridge.TAG, "some one hook Log!");
|
||||
return;
|
||||
}
|
||||
XposedCompat.hookMethod(method, additionalInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invokeOriginalMethod(Member method, long methodId, Object thisObject, Object[] args) throws Throwable {
|
||||
return SandHookXposedBridge.invokeOriginalMethod(method, thisObject, args);
|
||||
if (SandHookXposedBridge.hooked(method)) {
|
||||
try {
|
||||
return SandHookXposedBridge.invokeOriginalMethod(method, thisObject, args);
|
||||
} catch (Throwable throwable) {
|
||||
throw new InvocationTargetException(throwable);
|
||||
}
|
||||
} else {
|
||||
return DynamicBridge.invokeOriginalMethod(method, thisObject, args);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import java.lang.reflect.Member;
|
|||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import de.robv.android.xposed.XposedBridge;
|
||||
|
|
@ -20,7 +21,7 @@ import static com.elderdrivers.riru.edxp.sandhook.dexmaker.DexMakerUtils.shouldU
|
|||
|
||||
public final class DynamicBridge {
|
||||
|
||||
private static final HashMap<Member, Method> hookedInfo = new HashMap<>();
|
||||
private static final ConcurrentHashMap<Member, Method> hookedInfo = new ConcurrentHashMap<>();
|
||||
private static final HookerDexMaker dexMaker = new HookerDexMaker();
|
||||
private static final AtomicBoolean dexPathInited = new AtomicBoolean(false);
|
||||
private static File dexDir;
|
||||
|
|
@ -33,6 +34,10 @@ public final class DynamicBridge {
|
|||
dexPathInited.set(false);
|
||||
}
|
||||
|
||||
public static boolean hooked(Member member) {
|
||||
return hookedInfo.containsKey(member);
|
||||
}
|
||||
|
||||
public static synchronized void hookMethod(Member hookMethod, XposedBridge.AdditionalHookInfo additionalHookInfo) {
|
||||
DexLog.d("hooking " + hookMethod);
|
||||
if (!checkMember(hookMethod)) {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ import com.elderdrivers.riru.edxp.sandhook.entry.bootstrap.SysBootstrapHookInfo;
|
|||
import com.elderdrivers.riru.edxp.sandhook.entry.bootstrap.SysInnerHookInfo;
|
||||
import com.elderdrivers.riru.edxp.sandhook.entry.bootstrap.WorkAroundHookInfo;
|
||||
import com.elderdrivers.riru.edxp.sandhook.entry.hooker.SystemMainHooker;
|
||||
import com.swift.sandhook.SandHookConfig;
|
||||
import com.swift.sandhook.xposedcompat.XposedCompat;
|
||||
import com.swift.sandhook.xposedcompat.methodgen.SandHookXposedBridge;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
|
@ -21,6 +23,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||
import de.robv.android.xposed.XposedBridge;
|
||||
import de.robv.android.xposed.XposedInit;
|
||||
|
||||
import static de.robv.android.xposed.XposedInit.startsSystemServer;
|
||||
|
||||
public class Router {
|
||||
|
||||
public volatile static boolean forkCompleted = false;
|
||||
|
|
@ -30,7 +34,7 @@ public class Router {
|
|||
|
||||
public static void prepare(boolean isSystem) {
|
||||
// this flag is needed when loadModules
|
||||
XposedInit.startsSystemServer = isSystem;
|
||||
startsSystemServer = isSystem;
|
||||
// InstallerChooser.setup();
|
||||
}
|
||||
|
||||
|
|
@ -81,19 +85,22 @@ public class Router {
|
|||
Router.class.getClassLoader(),
|
||||
classLoader,
|
||||
SysBootstrapHookInfo.class.getName());
|
||||
XposedCompat.addHookers(classLoader, SysBootstrapHookInfo.hookItems);
|
||||
} else {
|
||||
HookMain.doHookDefault(
|
||||
Router.class.getClassLoader(),
|
||||
classLoader,
|
||||
AppBootstrapHookInfo.class.getName());
|
||||
XposedCompat.addHookers(classLoader, AppBootstrapHookInfo.hookItems);
|
||||
}
|
||||
}
|
||||
|
||||
public static void startSystemServerHook() {
|
||||
HookMain.doHookDefault(
|
||||
Router.class.getClassLoader(),
|
||||
SystemMainHooker.systemServerCL,
|
||||
SysInnerHookInfo.class.getName());
|
||||
// HookMain.doHookDefault(
|
||||
// Router.class.getClassLoader(),
|
||||
// SystemMainHooker.systemServerCL,
|
||||
// SysInnerHookInfo.class.getName());
|
||||
XposedCompat.addHookers(SystemMainHooker.systemServerCL, SysInnerHookInfo.hookItems);
|
||||
}
|
||||
|
||||
public static void startWorkAroundHook() {
|
||||
|
|
@ -106,7 +113,8 @@ public class Router {
|
|||
public static void onEnterChildProcess() {
|
||||
forkCompleted = true;
|
||||
DynamicBridge.onForkPost();
|
||||
SandHookXposedBridge.onForkPost();
|
||||
//enable compile in child process
|
||||
//SandHook.enableCompiler(!XposedInit.startsSystemServer);
|
||||
}
|
||||
|
||||
public static void logD(String prefix) {
|
||||
|
|
@ -122,5 +130,6 @@ public class Router {
|
|||
public static void injectConfig() {
|
||||
EdXpConfigGlobal.sConfig = new SandHookEdxpConfig();
|
||||
EdXpConfigGlobal.sHookProvider = new SandHookProvider();
|
||||
SandHookConfig.compiler = !startsSystemServer;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,11 @@ import com.elderdrivers.riru.edxp.sandhook.entry.hooker.OnePlusWorkAroundHooker;
|
|||
|
||||
public class AppBootstrapHookInfo implements KeepMembers {
|
||||
public static String[] hookItemNames = {
|
||||
HandleBindAppHooker.class.getName(),
|
||||
LoadedApkConstructorHooker.class.getName(),
|
||||
OnePlusWorkAroundHooker.class.getName()
|
||||
};
|
||||
|
||||
public static Class[] hookItems = {
|
||||
HandleBindAppHooker.class,
|
||||
LoadedApkConstructorHooker.class
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,12 @@ import com.elderdrivers.riru.edxp.sandhook.entry.hooker.SystemMainHooker;
|
|||
|
||||
public class SysBootstrapHookInfo implements KeepMembers {
|
||||
public static String[] hookItemNames = {
|
||||
HandleBindAppHooker.class.getName(),
|
||||
SystemMainHooker.class.getName(),
|
||||
LoadedApkConstructorHooker.class.getName(),
|
||||
OnePlusWorkAroundHooker.class.getName()
|
||||
};
|
||||
|
||||
public static Class[] hookItems = {
|
||||
HandleBindAppHooker.class,
|
||||
SystemMainHooker.class,
|
||||
LoadedApkConstructorHooker.class
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,4 +7,8 @@ public class SysInnerHookInfo implements KeepMembers {
|
|||
public static String[] hookItemNames = {
|
||||
StartBootstrapServicesHooker.class.getName()
|
||||
};
|
||||
|
||||
public static Class[] hookItems = {
|
||||
StartBootstrapServicesHooker.class
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,4 +7,7 @@ public class WorkAroundHookInfo implements KeepMembers {
|
|||
public static String[] hookItemNames = {
|
||||
OnePlusWorkAroundHooker.class.getName()
|
||||
};
|
||||
|
||||
public static Class[] hookItems = {
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,16 @@ import com.elderdrivers.riru.common.KeepMembers;
|
|||
import com.elderdrivers.riru.edxp.util.Utils;
|
||||
import com.elderdrivers.riru.edxp.Main;
|
||||
import com.elderdrivers.riru.edxp.sandhook.entry.Router;
|
||||
import com.swift.sandhook.SandHook;
|
||||
import com.swift.sandhook.annotation.HookClass;
|
||||
import com.swift.sandhook.annotation.HookMethod;
|
||||
import com.swift.sandhook.annotation.HookMethodBackup;
|
||||
import com.swift.sandhook.annotation.HookMode;
|
||||
import com.swift.sandhook.annotation.Param;
|
||||
import com.swift.sandhook.annotation.SkipParamCheck;
|
||||
import com.swift.sandhook.annotation.ThisObject;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import de.robv.android.xposed.XposedBridge;
|
||||
import de.robv.android.xposed.XposedHelpers;
|
||||
|
|
@ -21,15 +31,21 @@ import static com.elderdrivers.riru.edxp.util.ClassLoaderUtils.replaceParentClas
|
|||
import static com.elderdrivers.riru.edxp.sandhook.entry.hooker.XposedBlackListHooker.BLACK_LIST_PACKAGE_NAME;
|
||||
|
||||
// normal process initialization (for new Activity, Service, BroadcastReceiver etc.)
|
||||
@HookClass(ActivityThread.class)
|
||||
public class HandleBindAppHooker implements KeepMembers {
|
||||
|
||||
public static String className = "android.app.ActivityThread";
|
||||
public static String methodName = "handleBindApplication";
|
||||
public static String methodSig = "(Landroid/app/ActivityThread$AppBindData;)V";
|
||||
|
||||
public static void hook(Object thiz, Object bindData) {
|
||||
@HookMethodBackup("handleBindApplication")
|
||||
@SkipParamCheck
|
||||
static Method backup;
|
||||
|
||||
@HookMethod("handleBindApplication")
|
||||
public static void hook(@ThisObject ActivityThread thiz, @Param("android.app.ActivityThread$AppBindData") Object bindData) throws Throwable {
|
||||
if (XposedBlackListHooker.shouldDisableHooks("")) {
|
||||
backup(thiz, bindData);
|
||||
SandHook.callOriginByBackup(backup, thiz, bindData);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
|
|
@ -80,7 +96,7 @@ public class HandleBindAppHooker implements KeepMembers {
|
|||
} catch (Throwable t) {
|
||||
Router.logE("error when hooking bindApp", t);
|
||||
} finally {
|
||||
backup(thiz, bindData);
|
||||
SandHook.callOriginByBackup(backup, thiz, bindData);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,14 @@ import android.util.Log;
|
|||
|
||||
import com.elderdrivers.riru.common.KeepMembers;
|
||||
import com.elderdrivers.riru.edxp.sandhook.entry.Router;
|
||||
import com.swift.sandhook.SandHook;
|
||||
import com.swift.sandhook.annotation.HookClass;
|
||||
import com.swift.sandhook.annotation.HookMethod;
|
||||
import com.swift.sandhook.annotation.HookMethodBackup;
|
||||
import com.swift.sandhook.annotation.SkipParamCheck;
|
||||
import com.swift.sandhook.annotation.ThisObject;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import de.robv.android.xposed.XposedBridge;
|
||||
import de.robv.android.xposed.XposedHelpers;
|
||||
|
|
@ -19,6 +27,7 @@ import static com.elderdrivers.riru.edxp.util.ClassLoaderUtils.replaceParentClas
|
|||
|
||||
// when a package is loaded for an existing process, trigger the callbacks as well
|
||||
// ed: remove resources related hooking
|
||||
@HookClass(LoadedApk.class)
|
||||
public class LoadedApkConstructorHooker implements KeepMembers {
|
||||
public static String className = "android.app.LoadedApk";
|
||||
public static String methodName = "<init>";
|
||||
|
|
@ -27,20 +36,24 @@ public class LoadedApkConstructorHooker implements KeepMembers {
|
|||
"Landroid/content/res/CompatibilityInfo;" +
|
||||
"Ljava/lang/ClassLoader;ZZZ)V";
|
||||
|
||||
public static void hook(Object thiz, ActivityThread activityThread,
|
||||
@HookMethodBackup
|
||||
@SkipParamCheck
|
||||
static Method backup;
|
||||
|
||||
@HookMethod
|
||||
public static void hook(@ThisObject Object thiz, ActivityThread activityThread,
|
||||
ApplicationInfo aInfo, CompatibilityInfo compatInfo,
|
||||
ClassLoader baseLoader, boolean securityViolation,
|
||||
boolean includeCode, boolean registerPackage) {
|
||||
boolean includeCode, boolean registerPackage) throws Throwable {
|
||||
|
||||
if (XposedBlackListHooker.shouldDisableHooks("")) {
|
||||
backup(thiz, activityThread, aInfo, compatInfo, baseLoader, securityViolation,
|
||||
includeCode, registerPackage);
|
||||
SandHook.callOriginByBackup(backup, thiz, activityThread, aInfo, compatInfo, baseLoader, securityViolation, includeCode, registerPackage);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Router.logD("LoadedApk#<init> starts");
|
||||
backup(thiz, activityThread, aInfo, compatInfo, baseLoader, securityViolation,
|
||||
includeCode, registerPackage);
|
||||
SandHook.callOriginByBackup(backup, thiz, activityThread, aInfo, compatInfo, baseLoader, securityViolation, includeCode, registerPackage);
|
||||
|
||||
try {
|
||||
LoadedApk loadedApk = (LoadedApk) thiz;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,14 @@ package com.elderdrivers.riru.edxp.sandhook.entry.hooker;
|
|||
import com.elderdrivers.riru.common.KeepMembers;
|
||||
import com.elderdrivers.riru.edxp.Main;
|
||||
import com.elderdrivers.riru.edxp.sandhook.entry.Router;
|
||||
import com.swift.sandhook.annotation.HookClass;
|
||||
import com.swift.sandhook.annotation.HookMethod;
|
||||
import com.swift.sandhook.annotation.HookMethodBackup;
|
||||
import com.swift.sandhook.annotation.SkipParamCheck;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import dalvik.system.BaseDexClassLoader;
|
||||
import de.robv.android.xposed.XposedBridge;
|
||||
|
||||
/**
|
||||
|
|
@ -21,12 +28,18 @@ import de.robv.android.xposed.XposedBridge;
|
|||
* open of /dev/binder and we haven't found side effects yet.
|
||||
* Other roms might share the same problems but not reported too.
|
||||
*/
|
||||
@HookClass(BaseDexClassLoader.class)
|
||||
public class OnePlusWorkAroundHooker implements KeepMembers {
|
||||
|
||||
public static String className = "dalvik.system.BaseDexClassLoader";
|
||||
public static String methodName = "inCompatConfigList";
|
||||
public static String methodSig = "(ILjava/lang/String;)Z";
|
||||
|
||||
@HookMethodBackup("inCompatConfigList")
|
||||
@SkipParamCheck
|
||||
static Method backup;
|
||||
|
||||
@HookMethod("inCompatConfigList")
|
||||
public static boolean hook(int type, String packageName) {
|
||||
if (XposedBridge.disableHooks || Router.forkCompleted) {
|
||||
return backup(type, packageName);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,15 @@ import android.os.Build;
|
|||
|
||||
import com.elderdrivers.riru.common.KeepMembers;
|
||||
import com.elderdrivers.riru.edxp.sandhook.entry.Router;
|
||||
import com.swift.sandhook.SandHook;
|
||||
import com.swift.sandhook.annotation.HookMethod;
|
||||
import com.swift.sandhook.annotation.HookMethodBackup;
|
||||
import com.swift.sandhook.annotation.HookMode;
|
||||
import com.swift.sandhook.annotation.HookReflectClass;
|
||||
import com.swift.sandhook.annotation.SkipParamCheck;
|
||||
import com.swift.sandhook.annotation.ThisObject;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import de.robv.android.xposed.XC_MethodReplacement;
|
||||
import de.robv.android.xposed.XposedBridge;
|
||||
|
|
@ -15,15 +24,21 @@ import static com.elderdrivers.riru.edxp.util.ClassLoaderUtils.replaceParentClas
|
|||
import static com.elderdrivers.riru.edxp.util.Utils.logD;
|
||||
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
|
||||
|
||||
@HookReflectClass("com.android.server.SystemServer")
|
||||
public class StartBootstrapServicesHooker implements KeepMembers {
|
||||
public static String className = "com.android.server.SystemServer";
|
||||
public static String methodName = "startBootstrapServices";
|
||||
public static String methodSig = "()V";
|
||||
|
||||
public static void hook(Object systemServer) {
|
||||
@HookMethodBackup("startBootstrapServices")
|
||||
@SkipParamCheck
|
||||
static Method backup;
|
||||
|
||||
@HookMethod("startBootstrapServices")
|
||||
public static void hook(@ThisObject Object systemServer) throws Throwable {
|
||||
|
||||
if (XposedBridge.disableHooks) {
|
||||
backup(systemServer);
|
||||
SandHook.callOriginByBackup(backup, systemServer);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -56,7 +71,7 @@ public class StartBootstrapServicesHooker implements KeepMembers {
|
|||
} catch (Throwable t) {
|
||||
Router.logE("error when hooking startBootstrapServices", t);
|
||||
} finally {
|
||||
backup(systemServer);
|
||||
SandHook.callOriginByBackup(backup, systemServer);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,12 +5,20 @@ import android.app.ActivityThread;
|
|||
import com.elderdrivers.riru.common.KeepMembers;
|
||||
import com.elderdrivers.riru.edxp.sandhook.entry.Router;
|
||||
import com.elderdrivers.riru.edxp.sandhook.util.PrebuiltMethodsDeopter;
|
||||
import com.swift.sandhook.SandHook;
|
||||
import com.swift.sandhook.annotation.HookClass;
|
||||
import com.swift.sandhook.annotation.HookMethod;
|
||||
import com.swift.sandhook.annotation.HookMethodBackup;
|
||||
import com.swift.sandhook.annotation.HookMode;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import de.robv.android.xposed.XposedBridge;
|
||||
|
||||
|
||||
// system_server initialization
|
||||
// ed: only support sdk >= 21 for now
|
||||
@HookClass(ActivityThread.class)
|
||||
public class SystemMainHooker implements KeepMembers {
|
||||
|
||||
public static String className = "android.app.ActivityThread";
|
||||
|
|
@ -19,12 +27,16 @@ public class SystemMainHooker implements KeepMembers {
|
|||
|
||||
public static ClassLoader systemServerCL;
|
||||
|
||||
public static ActivityThread hook() {
|
||||
@HookMethodBackup("systemMain")
|
||||
static Method backup;
|
||||
|
||||
@HookMethod("systemMain")
|
||||
public static ActivityThread hook() throws Throwable {
|
||||
if (XposedBridge.disableHooks) {
|
||||
return backup();
|
||||
return (ActivityThread) SandHook.callOriginByBackup(backup, null);
|
||||
}
|
||||
Router.logD("ActivityThread#systemMain() starts");
|
||||
ActivityThread activityThread = backup();
|
||||
ActivityThread activityThread = (ActivityThread) SandHook.callOriginByBackup(backup, null);
|
||||
try {
|
||||
// get system_server classLoader
|
||||
systemServerCL = Thread.currentThread().getContextClassLoader();
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ public class BlackWhiteListProxy {
|
|||
}
|
||||
|
||||
private static void onForkPostCommon(boolean isSystemServer, String appDataDir, String niceName) {
|
||||
Main.appDataDir = appDataDir;
|
||||
Main.setAppDataDir(appDataDir);
|
||||
Main.niceName = niceName;
|
||||
final boolean isDynamicModulesMode = Main.isDynamicModulesEnabled();
|
||||
ConfigManager.setDynamicModulesMode(isDynamicModulesMode);
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ public class NormalProxy {
|
|||
|
||||
public static void forkAndSpecializePost(int pid, String appDataDir, String niceName) {
|
||||
// TODO consider processes without forkAndSpecializePost called
|
||||
Main.appDataDir = appDataDir;
|
||||
Main.setAppDataDir(appDataDir);
|
||||
Main.niceName = niceName;
|
||||
Router.prepare(false);
|
||||
Main.reopenFilesAfterForkNative();
|
||||
|
|
@ -58,7 +58,7 @@ public class NormalProxy {
|
|||
|
||||
public static void forkSystemServerPost(int pid) {
|
||||
// in system_server process
|
||||
Main.appDataDir = getDataPathPrefix() + "android";
|
||||
Main.setAppDataDir(getDataPathPrefix() + "android");
|
||||
Main.niceName = "system_server";
|
||||
Router.prepare(true);
|
||||
Main.reopenFilesAfterForkNative();
|
||||
|
|
|
|||
|
|
@ -1,23 +1,65 @@
|
|||
package com.swift.sandhook.xposedcompat;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Process;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.swift.sandhook.SandHook;
|
||||
import com.swift.sandhook.xposedcompat.classloaders.ComposeClassLoader;
|
||||
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;
|
||||
|
||||
public class XposedCompat {
|
||||
|
||||
public static volatile String appDataDir;
|
||||
|
||||
// TODO initialize these variables
|
||||
public static volatile File cacheDir;
|
||||
public static volatile ClassLoader classLoader;
|
||||
|
||||
//try to use internal stub hooker & backup method to speed up hook
|
||||
public static volatile boolean useInternalStub = true;
|
||||
public static volatile boolean useNewDexMaker = true;
|
||||
public static volatile boolean useNewCallBackup = true;
|
||||
public static volatile boolean retryWhenCallOriginError = false;
|
||||
|
||||
private static ClassLoader sandHookXposedClassLoader;
|
||||
|
||||
public static void addHookers(ClassLoader classLoader, Class[] hookers) {
|
||||
if (hookers == null)
|
||||
return;
|
||||
for (Class hooker:hookers) {
|
||||
try {
|
||||
SandHook.addHookClass(classLoader, hooker);
|
||||
} catch (Throwable throwable) {}
|
||||
}
|
||||
}
|
||||
|
||||
public static File getCacheDir() {
|
||||
if (cacheDir == null) {
|
||||
String fixedAppDataDir = getDataPathPrefix() + getPackageName(appDataDir) + "/";
|
||||
cacheDir = new File(fixedAppDataDir, "/cache/sandhook/"
|
||||
+ ProcessUtils.getProcessName().replace(":", "_") + "/");
|
||||
}
|
||||
return cacheDir;
|
||||
}
|
||||
|
||||
public static ClassLoader getClassLoader() {
|
||||
if (classLoader == null) {
|
||||
classLoader = getSandHookXposedClassLoader(ApplicationUtils.currentApplication().getClassLoader(), XposedCompat.class.getClassLoader());
|
||||
}
|
||||
return classLoader;
|
||||
}
|
||||
|
||||
public static synchronized void hookMethod(Member hookMethod, XposedBridge.AdditionalHookInfo additionalHookInfo) {
|
||||
SandHookXposedBridge.hookMethod(hookMethod, additionalHookInfo);
|
||||
}
|
||||
|
|
@ -31,18 +73,37 @@ public class XposedCompat {
|
|||
}
|
||||
}
|
||||
|
||||
// public static boolean clearCache() {
|
||||
// try {
|
||||
// FileUtils.delete(cacheDir);
|
||||
// cacheDir.mkdirs();
|
||||
// return true;
|
||||
// } catch (Throwable throwable) {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public static void clearOatCache() {
|
||||
// SandHookXposedBridge.clearOatFile();
|
||||
// }
|
||||
public static boolean clearCache() {
|
||||
try {
|
||||
FileUtils.delete(getCacheDir());
|
||||
getCacheDir().mkdirs();
|
||||
return true;
|
||||
} catch (Throwable throwable) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void clearOatCache() {
|
||||
SandHookXposedBridge.clearOatFile();
|
||||
}
|
||||
|
||||
public static String getPackageName(String dataDir) {
|
||||
if (TextUtils.isEmpty(dataDir)) {
|
||||
return "";
|
||||
}
|
||||
int lastIndex = dataDir.lastIndexOf("/");
|
||||
if (lastIndex < 0) {
|
||||
return dataDir;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import com.swift.sandhook.SandHook;
|
|||
import com.swift.sandhook.SandHookMethodResolver;
|
||||
import com.swift.sandhook.utils.ParamWrapper;
|
||||
import com.swift.sandhook.wrapper.BackupMethodStubs;
|
||||
import com.swift.sandhook.xposedcompat.XposedCompat;
|
||||
import com.swift.sandhook.xposedcompat.utils.DexLog;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
|
@ -23,12 +24,15 @@ import static de.robv.android.xposed.XposedBridge.sHookedMethodCallbacks;
|
|||
|
||||
public class HookStubManager {
|
||||
|
||||
public static volatile boolean is64Bit;
|
||||
//64bits arg0 - arg7 is in reg x1 - x7 and > 7 is in stack, but can not match
|
||||
public final static int MAX_64_ARGS = 7;
|
||||
|
||||
public static int MAX_STUB_ARGS = 0;
|
||||
|
||||
public static int[] stubSizes;
|
||||
|
||||
public static boolean hasStubBackup = false;
|
||||
public static boolean hasStubBackup;
|
||||
|
||||
public static AtomicInteger[] curUseStubIndexes;
|
||||
|
||||
|
|
@ -41,10 +45,11 @@ public class HookStubManager {
|
|||
= sHookedMethodCallbacks;
|
||||
|
||||
static {
|
||||
Class stubClass = SandHook.is64Bit() ? MethodHookerStubs64.class : MethodHookerStubs32.class;
|
||||
is64Bit = SandHook.is64Bit();
|
||||
Class stubClass = is64Bit ? MethodHookerStubs64.class : MethodHookerStubs32.class;
|
||||
stubSizes = (int[]) XposedHelpers.getStaticObjectField(stubClass, "stubSizes");
|
||||
Boolean hasBackup = (Boolean) XposedHelpers.getStaticObjectField(stubClass, "hasStubBackup");
|
||||
hasStubBackup = hasBackup == null ? false : hasBackup;
|
||||
hasStubBackup = hasBackup != null && (hasBackup && !XposedCompat.useNewCallBackup);
|
||||
if (stubSizes != null && stubSizes.length > 0) {
|
||||
MAX_STUB_ARGS = stubSizes.length - 1;
|
||||
curUseStubIndexes = new AtomicInteger[MAX_STUB_ARGS + 1];
|
||||
|
|
@ -89,6 +94,8 @@ public class HookStubManager {
|
|||
needStubArgCount += parType.length;
|
||||
if (needStubArgCount > MAX_STUB_ARGS)
|
||||
return null;
|
||||
if (is64Bit && needStubArgCount > MAX_64_ARGS)
|
||||
return null;
|
||||
for (Class par:parType) {
|
||||
if (!ParamWrapper.support(par))
|
||||
return null;
|
||||
|
|
@ -98,7 +105,7 @@ public class HookStubManager {
|
|||
}
|
||||
|
||||
synchronized (HookStubManager.class) {
|
||||
StubMethodsInfo stubMethodInfo = getStubMethodPair(SandHook.is64Bit(), needStubArgCount);
|
||||
StubMethodsInfo stubMethodInfo = getStubMethodPair(is64Bit, needStubArgCount);
|
||||
if (stubMethodInfo == null)
|
||||
return null;
|
||||
HookMethodEntity entity = new HookMethodEntity(origin, stubMethodInfo.hook, stubMethodInfo.backup);
|
||||
|
|
@ -180,7 +187,7 @@ public class HookStubManager {
|
|||
}
|
||||
|
||||
public static Method getCallOriginMethod(int args, int index) {
|
||||
Class stubClass = SandHook.is64Bit() ? MethodHookerStubs64.class : MethodHookerStubs32.class;
|
||||
Class stubClass = is64Bit ? MethodHookerStubs64.class : MethodHookerStubs32.class;
|
||||
String className = stubClass.getName();
|
||||
className += "$";
|
||||
className += getCallOriginClassName(args, index);
|
||||
|
|
@ -294,7 +301,6 @@ public class HookStubManager {
|
|||
param.setResult(SandHook.callOriginMethod(originMethod, thiz, param.args));
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
XposedBridge.log(e);
|
||||
param.setThrowable(e);
|
||||
}
|
||||
}
|
||||
|
|
@ -365,7 +371,6 @@ public class HookStubManager {
|
|||
try {
|
||||
param.setResult(SandHook.callOriginMethod(origin, thiz, param.args));
|
||||
} catch (Throwable e) {
|
||||
XposedBridge.log(e);
|
||||
param.setThrowable(e);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -9,12 +9,15 @@ 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;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Map;
|
||||
|
||||
import dalvik.system.InMemoryDexClassLoader;
|
||||
import de.robv.android.xposed.XC_MethodHook;
|
||||
import de.robv.android.xposed.XposedBridge;
|
||||
import external.com.android.dx.BinaryOp;
|
||||
|
|
@ -218,7 +221,13 @@ public class HookerDexMaker implements HookMaker {
|
|||
throw new IllegalArgumentException("dexDirPath should not be empty!!!");
|
||||
}
|
||||
// Create the dex file and load it.
|
||||
loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(mDexDirPath), dexName);
|
||||
try {
|
||||
loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(mDexDirPath), dexName);
|
||||
} catch (IOException e) {
|
||||
//can not write file
|
||||
byte[] dexBytes = mDexMaker.generate();
|
||||
loader = new InMemoryDexClassLoader(ByteBuffer.wrap(dexBytes), mAppClassLoader);
|
||||
}
|
||||
return loadHookerClass(loader, className);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,12 +7,15 @@ import com.swift.sandhook.wrapper.HookWrapper;
|
|||
import com.swift.sandhook.xposedcompat.hookstub.HookStubManager;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Map;
|
||||
|
||||
import dalvik.system.InMemoryDexClassLoader;
|
||||
import de.robv.android.xposed.XposedBridge;
|
||||
import de.robv.android.xposed.XposedHelpers;
|
||||
import external.com.android.dx.Code;
|
||||
|
|
@ -172,7 +175,13 @@ public class HookerDexMakerNew implements HookMaker {
|
|||
throw new IllegalArgumentException("dexDirPath should not be empty!!!");
|
||||
}
|
||||
// Create the dex file and load it.
|
||||
loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(mDexDirPath), dexName);
|
||||
try {
|
||||
loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(mDexDirPath), dexName);
|
||||
} catch (IOException e) {
|
||||
//can not write file
|
||||
byte[] dexBytes = mDexMaker.generate();
|
||||
loader = new InMemoryDexClassLoader(ByteBuffer.wrap(dexBytes), mAppClassLoader);
|
||||
}
|
||||
return loadHookerClass(loader, className);
|
||||
}
|
||||
|
||||
|
|
@ -233,7 +242,7 @@ public class HookerDexMakerNew implements HookMaker {
|
|||
Code code = mDexMaker.declare(mHookMethodId, Modifier.PUBLIC | Modifier.STATIC);
|
||||
|
||||
Local<Member> method = code.newLocal(memberTypeId);
|
||||
// Local<Method> backupMethod = code.newLocal(methodTypeId);
|
||||
// Local<Method> backupMethod = code.newLocal(methodTypeId);
|
||||
Local<Object> thisObject = code.newLocal(TypeId.OBJECT);
|
||||
Local<Object[]> args = code.newLocal(objArrayTypeId);
|
||||
Local<Integer> actualParamSize = code.newLocal(TypeId.INT);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package com.swift.sandhook.xposedcompat.methodgen;
|
|||
import android.os.Process;
|
||||
import android.os.Trace;
|
||||
|
||||
import com.elderdrivers.riru.edxp.Main;
|
||||
import com.swift.sandhook.SandHook;
|
||||
import com.swift.sandhook.SandHookConfig;
|
||||
import com.swift.sandhook.wrapper.HookWrapper;
|
||||
|
|
@ -18,27 +17,23 @@ import java.lang.reflect.Constructor;
|
|||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import de.robv.android.xposed.XposedBridge;
|
||||
|
||||
import static com.elderdrivers.riru.edxp.util.FileUtils.getDataPathPrefix;
|
||||
import static com.elderdrivers.riru.edxp.util.FileUtils.getPackageName;
|
||||
import static com.elderdrivers.riru.edxp.util.ProcessUtils.getCurrentProcessName;
|
||||
|
||||
public final class SandHookXposedBridge {
|
||||
|
||||
private static final HashMap<Member, Method> hookedInfo = new HashMap<>();
|
||||
private static HookMaker hookMaker = XposedCompat.useNewDexMaker ? new HookerDexMakerNew() : new HookerDexMaker();
|
||||
private static final Map<Member, Method> hookedInfo = new ConcurrentHashMap<>();
|
||||
private static HookMaker hookMaker = 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 HashMap<>();
|
||||
public static Map<Member,HookMethodEntity> entityMap = new ConcurrentHashMap<>();
|
||||
|
||||
public static void onForkPost() {
|
||||
dexPathInited.set(false);
|
||||
public static boolean hooked(Member member) {
|
||||
return hookedInfo.containsKey(member) || entityMap.containsKey(member);
|
||||
}
|
||||
|
||||
public static synchronized void hookMethod(Member hookMethod, XposedBridge.AdditionalHookInfo additionalHookInfo) {
|
||||
|
|
@ -53,8 +48,17 @@ public final class SandHookXposedBridge {
|
|||
}
|
||||
|
||||
try {
|
||||
setupDexCachePath();
|
||||
Trace.beginSection("SandHook-Xposed");
|
||||
if (dexPathInited.compareAndSet(false, true)) {
|
||||
try {
|
||||
String fixedAppDataDir = XposedCompat.getCacheDir().getAbsolutePath();
|
||||
dexDir = new File(fixedAppDataDir, "/hookers/");
|
||||
if (!dexDir.exists())
|
||||
dexDir.mkdirs();
|
||||
} catch (Throwable throwable) {
|
||||
DexLog.e("error when init dex path", throwable);
|
||||
}
|
||||
}
|
||||
Trace.beginSection("SandXposed");
|
||||
long timeStart = System.currentTimeMillis();
|
||||
HookMethodEntity stub = null;
|
||||
if (XposedCompat.useInternalStub) {
|
||||
|
|
@ -65,7 +69,7 @@ public final class SandHookXposedBridge {
|
|||
entityMap.put(hookMethod, stub);
|
||||
} else {
|
||||
hookMaker.start(hookMethod, additionalHookInfo,
|
||||
null, dexDir == null ? null : dexDir.getAbsolutePath());
|
||||
hookMethod.getDeclaringClass().getClassLoader(), dexDir == null ? null : dexDir.getAbsolutePath());
|
||||
hookedInfo.put(hookMethod, hookMaker.getCallBackupMethod());
|
||||
}
|
||||
DexLog.d("hook method <" + hookMethod.toString() + "> cost " + (System.currentTimeMillis() - timeStart) + " ms, by " + (stub != null ? "internal stub." : "dex maker"));
|
||||
|
|
@ -75,35 +79,18 @@ public final class SandHookXposedBridge {
|
|||
}
|
||||
}
|
||||
|
||||
private static void setupDexCachePath() {
|
||||
// using file based DexClassLoader
|
||||
if (!dexPathInited.compareAndSet(false, true)) {
|
||||
public static void clearOatFile() {
|
||||
String fixedAppDataDir = XposedCompat.getCacheDir().getAbsolutePath();
|
||||
File dexOatDir = new File(fixedAppDataDir, "/hookers/oat/");
|
||||
if (!dexOatDir.exists())
|
||||
return;
|
||||
}
|
||||
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.appDataDir) + "/";
|
||||
dexDir = new File(fixedAppDataDir, "/cache/sandxposed/"
|
||||
+ getCurrentProcessName(Main.appProcessName).replace(":", "_") + "/");
|
||||
dexDir.mkdirs();
|
||||
FileUtils.delete(dexOatDir);
|
||||
dexOatDir.mkdirs();
|
||||
} catch (Throwable throwable) {
|
||||
com.elderdrivers.riru.edxp.sandhook.dexmaker.DexLog.e("error when init dex path", throwable);
|
||||
}
|
||||
}
|
||||
|
||||
// public static void clearOatFile() {
|
||||
// String fixedAppDataDir = XposedCompat.cacheDir.getAbsolutePath();
|
||||
// File dexOatDir = new File(fixedAppDataDir, "/sandxposed/oat/");
|
||||
// if (!dexOatDir.exists())
|
||||
// return;
|
||||
// try {
|
||||
// FileUtils.delete(dexOatDir);
|
||||
// dexOatDir.mkdirs();
|
||||
// } catch (Throwable throwable) {
|
||||
// }
|
||||
// }
|
||||
|
||||
private static boolean checkMember(Member member) {
|
||||
|
||||
if (member instanceof Method) {
|
||||
|
|
@ -124,37 +111,24 @@ public final class SandHookXposedBridge {
|
|||
|
||||
public static Object invokeOriginalMethod(Member method, Object thisObject, Object[] args)
|
||||
throws Throwable {
|
||||
Method callBackup = hookedInfo.get(method);
|
||||
if (callBackup == null) {
|
||||
//method hook use internal stub
|
||||
return SandHook.callOriginMethod(method, thisObject, args);
|
||||
}
|
||||
if (!Modifier.isStatic(callBackup.getModifiers())) {
|
||||
throw new IllegalStateException("original method is not static, something must be wrong!");
|
||||
}
|
||||
callBackup.setAccessible(true);
|
||||
if (args == null) {
|
||||
args = new Object[0];
|
||||
}
|
||||
final int argsSize = args.length;
|
||||
if (Modifier.isStatic(method.getModifiers())) {
|
||||
return callBackup.invoke(null, args);
|
||||
} else {
|
||||
Object[] newArgs = new Object[argsSize + 1];
|
||||
newArgs[0] = thisObject;
|
||||
for (int i = 1; i < newArgs.length; i++) {
|
||||
newArgs[i] = args[i - 1];
|
||||
}
|
||||
return callBackup.invoke(null, newArgs);
|
||||
}
|
||||
return SandHook.callOriginMethod(method, thisObject, args);
|
||||
}
|
||||
|
||||
public static void setLibPath() {
|
||||
public static void init() {
|
||||
if (Process.is64Bit()) {
|
||||
SandHookConfig.libSandHookPath = "/system/lib64/libsandhook.edxp.so";
|
||||
} else {
|
||||
SandHookConfig.libSandHookPath = "/system/lib/libsandhook.edxp.so";
|
||||
}
|
||||
SandHookConfig.libLoader = new SandHookConfig.LibLoader() {
|
||||
@Override
|
||||
public void loadLib() {
|
||||
//do it in loadDexAndInit
|
||||
}
|
||||
};
|
||||
SandHookConfig.DEBUG = true;
|
||||
//in zygote disable compile
|
||||
SandHookConfig.compiler = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,12 +7,16 @@ import java.lang.reflect.Member;
|
|||
|
||||
public class DexLog {
|
||||
|
||||
public static final String TAG = "SandXposed-dexmaker";
|
||||
public static final String TAG = "SandXposed";
|
||||
|
||||
public static boolean DEBUG = true;
|
||||
public static volatile boolean DEBUG = true;
|
||||
|
||||
public static int v(String s) {
|
||||
return Log.v(TAG, s);
|
||||
if (DEBUG) {
|
||||
return Log.v(TAG, s);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static int i(String s) {
|
||||
|
|
@ -25,26 +29,38 @@ public class DexLog {
|
|||
|
||||
public static void printMethodHookIn(Member member) {
|
||||
if (DEBUG && member != null) {
|
||||
Log.d("SandHook-Xposed", "method <" + member.toString() + "> hook in");
|
||||
Log.d("SandHook", "method <" + member.toString() + "> hook in");
|
||||
}
|
||||
}
|
||||
|
||||
public static void printCallOriginError(Member member) {
|
||||
if (member != null) {
|
||||
Log.e("SandHook-Xposed", "method <" + member.toString() + "> call origin error!");
|
||||
if (DEBUG && member != null) {
|
||||
Log.d("SandHook", "method <" + member.toString() + "> call origin error!");
|
||||
}
|
||||
}
|
||||
|
||||
public static int w(String s) {
|
||||
return Log.w(TAG, s);
|
||||
if (DEBUG) {
|
||||
return Log.w(TAG, s);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static int e(String s) {
|
||||
return Log.e(TAG, s);
|
||||
if (DEBUG) {
|
||||
return Log.e(TAG, s);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static int e(String s, Throwable t) {
|
||||
return Log.e(TAG, s, t);
|
||||
if (DEBUG) {
|
||||
return Log.e(TAG, s, t);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,12 @@ 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;
|
||||
|
||||
|
|
@ -18,10 +22,10 @@ public class ProcessUtils {
|
|||
|
||||
private static volatile String processName = null;
|
||||
|
||||
public static String getProcessName(Context context) {
|
||||
public static String getProcessName() {
|
||||
if (!TextUtils.isEmpty(processName))
|
||||
return processName;
|
||||
processName = doGetProcessName(context);
|
||||
processName = getProcessName(Process.myPid());
|
||||
return processName;
|
||||
}
|
||||
|
||||
|
|
@ -41,8 +45,35 @@ public class ProcessUtils {
|
|||
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(context);
|
||||
String processName = getProcessName();
|
||||
String pkgName = context.getPackageName();
|
||||
if (!TextUtils.isEmpty(processName) && !TextUtils.equals(processName, pkgName)) {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
libsandhook.edxp.so
|
||||
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue