diff --git a/Bridge/build.gradle b/Bridge/build.gradle index 5099f5edb..f79d18273 100644 --- a/Bridge/build.gradle +++ b/Bridge/build.gradle @@ -108,6 +108,7 @@ tasks.preBuild.dependsOn fixIml dependencies { compileOnly files("libs/framework-stub.jar") compileOnly project(':dexmaker') + compileOnly project(':sandhook') } afterEvaluate { diff --git a/Bridge/src/main/java/com/elderdrivers/riru/xposed/Main.java b/Bridge/src/main/java/com/elderdrivers/riru/xposed/Main.java index 0b27948f9..dd284977a 100644 --- a/Bridge/src/main/java/com/elderdrivers/riru/xposed/Main.java +++ b/Bridge/src/main/java/com/elderdrivers/riru/xposed/Main.java @@ -16,6 +16,8 @@ @SuppressLint("DefaultLocale") public class Main implements KeepAll { + public volatile static boolean useSandHook = true; + public static String appDataDir = ""; public static String appProcessName = ""; private static String forkAndSpecializePramsStr = ""; diff --git a/Bridge/src/main/java/de/robv/android/xposed/XposedBridge.java b/Bridge/src/main/java/de/robv/android/xposed/XposedBridge.java index 851d12ab4..b5860b25d 100644 --- a/Bridge/src/main/java/de/robv/android/xposed/XposedBridge.java +++ b/Bridge/src/main/java/de/robv/android/xposed/XposedBridge.java @@ -3,9 +3,11 @@ import android.annotation.SuppressLint; import android.util.Log; +import com.elderdrivers.riru.xposed.Main; import com.elderdrivers.riru.xposed.core.HookMain; import com.elderdrivers.riru.xposed.dexmaker.DynamicBridge; import com.elderdrivers.riru.xposed.dexmaker.MethodInfo; +import com.swift.sandhook.xposedcompat.XposedCompat; import java.io.File; import java.io.IOException; @@ -62,7 +64,7 @@ public final class XposedBridge { private static final Object[] EMPTY_ARRAY = new Object[0]; // built-in handlers - private static final Map> sHookedMethodCallbacks = new HashMap<>(); + public static final Map> sHookedMethodCallbacks = new HashMap<>(); public static final CopyOnWriteSortedSet sLoadedPackageCallbacks = new CopyOnWriteSortedSet<>(); /*package*/ static final CopyOnWriteSortedSet sInitPackageResourcesCallbacks = new CopyOnWriteSortedSet<>(); @@ -399,7 +401,11 @@ public static void hookInitPackageResources(XC_InitPackageResources callback) { */ private synchronized static void hookMethodNative(final Member method, Class declaringClass, int slot, final Object additionalInfoObj) { - DynamicBridge.hookMethod(method, (AdditionalHookInfo) additionalInfoObj); + if (Main.useSandHook) { + XposedCompat.hookMethod(method, (AdditionalHookInfo) additionalInfoObj); + } else { + DynamicBridge.hookMethod(method, (AdditionalHookInfo) additionalInfoObj); + } } private static Object invokeOriginalMethodNative(Member method, int methodId, diff --git a/dexmaker/src/main/java/external/com/android/dx/DexMaker.java b/dexmaker/src/main/java/external/com/android/dx/DexMaker.java index 411418f8c..4cfd282ad 100644 --- a/dexmaker/src/main/java/external/com/android/dx/DexMaker.java +++ b/dexmaker/src/main/java/external/com/android/dx/DexMaker.java @@ -230,7 +230,7 @@ TypeDeclaration getTypeDeclaration(TypeId type) { * Modifier#FINAL} and {@link Modifier#ABSTRACT}. */ public void declare(TypeId type, String sourceFile, int flags, - TypeId supertype, TypeId... interfaces) { + TypeId supertype, TypeId... interfaces) { TypeDeclaration declaration = getTypeDeclaration(type); int supportedFlags = Modifier.PUBLIC | Modifier.FINAL | Modifier.ABSTRACT | AccessFlags.ACC_SYNTHETIC; @@ -471,6 +471,21 @@ private ClassLoader generateClassLoader(File result, File dexCache, ClassLoader } } + public ClassLoader loadClassDirect(ClassLoader parent, File dexCache, String dexFileName) { + File result = new File(dexCache, dexFileName); + // Check that the file exists. If it does, return a DexClassLoader and skip all + // the dex bytecode generation. + if (result.exists()) { + return generateClassLoader(result, dexCache, parent); + } else { + return null; + } + } + + public ClassLoader generateAndLoad(ClassLoader parent, File dexCache) throws IOException { + return generateAndLoad(parent, dexCache, generateFileName()); + } + /** * Generates a dex file and loads its types into the current process. * @@ -497,7 +512,7 @@ private ClassLoader generateClassLoader(File result, File dexCache, ClassLoader * dex files will be written. If null, this class will try to guess the * application's private data dir. */ - public ClassLoader generateAndLoad(ClassLoader parent, File dexCache) throws IOException { + public ClassLoader generateAndLoad(ClassLoader parent, File dexCache, String dexFileName) throws IOException { if (dexCache == null) { String property = System.getProperty("dexmaker.dexcache"); if (property != null) { @@ -511,11 +526,12 @@ public ClassLoader generateAndLoad(ClassLoader parent, File dexCache) throws IOE } } - File result = new File(dexCache, generateFileName()); - // Check that the file exists. If it does, return a DexClassLoader and skip all - // the dex bytecode generation. + File result = new File(dexCache, dexFileName); + if (result.exists()) { - return generateClassLoader(result, dexCache, parent); + try { + deleteOldDex(result); + } catch (Throwable throwable) {} } byte[] dex = generate(); @@ -527,6 +543,12 @@ public ClassLoader generateAndLoad(ClassLoader parent, File dexCache) throws IOE * * TODO: load the dex from memory where supported. */ + + File parentDir = result.getParentFile(); + if (!parentDir.exists()) { + parentDir.mkdirs(); + } + result.createNewFile(); JarOutputStream jarOut = new JarOutputStream(new FileOutputStream(result)); JarEntry entry = new JarEntry(DexFormat.DEX_IN_JAR_NAME); @@ -538,6 +560,32 @@ public ClassLoader generateAndLoad(ClassLoader parent, File dexCache) throws IOE return generateClassLoader(result, dexCache, parent); } + public void deleteOldDex(File dexFile) { + dexFile.delete(); + String dexDir = dexFile.getParent(); + File oatDir = new File(dexDir, "/oat/"); + File oatDirArm = new File(oatDir, "/arm/"); + File oatDirArm64 = new File(oatDir, "/arm64/"); + if (!oatDir.exists()) + return; + String nameStart = dexFile.getName().replaceAll(".jar", ""); + doDeleteOatFiles(oatDir, nameStart); + doDeleteOatFiles(oatDirArm, nameStart); + doDeleteOatFiles(oatDirArm64, nameStart); + } + + private void doDeleteOatFiles(File dir, String nameStart) { + if (!dir.exists()) + return; + File[] oats = dir.listFiles(); + if (oats == null) + return; + for (File oatFile:oats) { + if (oatFile.isFile() && oatFile.getName().startsWith(nameStart)) + oatFile.delete(); + } + } + DexFile getDexFile() { if (outputDex == null) { DexOptions options = new DexOptions(); diff --git a/sandhook/.gitignore b/sandhook/.gitignore new file mode 100644 index 000000000..796b96d1c --- /dev/null +++ b/sandhook/.gitignore @@ -0,0 +1 @@ +/build diff --git a/sandhook/build.gradle b/sandhook/build.gradle new file mode 100644 index 000000000..8a3f87fb2 --- /dev/null +++ b/sandhook/build.gradle @@ -0,0 +1,34 @@ +apply plugin: 'com.android.library' + +android { + compileSdkVersion 28 + + + + defaultConfig { + minSdkVersion 19 + targetSdkVersion 28 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + +} + +dependencies { + implementation fileTree(include: ['*.jar'], dir: 'libs') + implementation 'com.jakewharton.android.repackaged:dalvik-dx:9.0.0_r3' + implementation 'com.swift.sandhook:hooklib:3.0.1' + compileOnly project(':dexmaker') + compileOnly project(':xposedapi') +} + diff --git a/sandhook/genhookstubs.py b/sandhook/genhookstubs.py new file mode 100644 index 000000000..feddcd897 --- /dev/null +++ b/sandhook/genhookstubs.py @@ -0,0 +1,186 @@ +#!/usr/bin/python + +import os + +STUB_FILE_NAME = "MethodHookerStubs" + +TEMP_STUB_CLASS_WRAPPER = """package com.swift.sandhook.xposedcompat.hookstub; + +import static com.swift.sandhook.xposedcompat.hookstub.HookStubManager.hookBridge; +import static com.swift.sandhook.xposedcompat.hookstub.HookStubManager.getMethodId; +import static com.swift.sandhook.xposedcompat.hookstub.HookStubManager.originMethods; +import static com.swift.sandhook.xposedcompat.utils.DexLog.printCallOriginError; + +/** +* this file is auto gen by genhookstubs.py +* it is for sandhook internal hooker & backup methods +**/ +public class MethodHookerStubs%d { +%s +} +""" + +TEMP_STUB_HOOK_METHOD_NAME = """stub_hook_%d""" +TEMP_STUB_HOOK_BACKUP_NAME = """stub_backup_%d""" +TEMP_STUB_CALL_ORIGIN_NAME = """call_origin_%d_%d""" + +TEMP_STUB_GET_METHOD_ID_NAME = """getMethodId(%d, %d)""" + +JAVA_TYPE_INT = "int" +JAVA_CAST_INT = "(int)" +JAVA_TYPE_LONG = "long" + +TEMP_STUB_HOOK_METHOD = """ + public static %s %s(%s) throws Throwable { + return %s hookBridge(%s, %s %s); + } +""" + +TEMP_STUB_BACKUP_METHOD = """ + public static %s %s(%s) throws Throwable { + try { + printCallOriginError(originMethods[%s]); + } catch (Throwable throwable) {} + return 0; + } +""" + +TEMP_STUB_CALL_ORIGIN_CLASS = """ + static class %s implements CallOriginCallBack { + @Override + public long call(long... args) throws Throwable { + return %s(%s); + } + } +""" + +TEMP_STUB_INFO = """ + public static boolean hasStubBackup = %s; + public static int[] stubSizes = {%s}; +""" + + +STUB_SIZES = [10,20,30,30,30,30,30,20,10,10,5,5,3] +HAS_BACKUP = False; + + +def getMethodId(args, index): + return TEMP_STUB_GET_METHOD_ID_NAME % (args, index) + +def getMethodHookName(index): + return TEMP_STUB_HOOK_METHOD_NAME % index + +def getMethodBackupName(index): + return TEMP_STUB_HOOK_BACKUP_NAME % index + +def getCallOriginClassName(args, index): + return TEMP_STUB_CALL_ORIGIN_NAME % (args, index) + + +def genArgsList(is64Bit, isDefine, length): + args_list = "" + for i in range(length): + if (i != 0): + args_list += ", " + if isDefine: + if (is64Bit): + args_list += (JAVA_TYPE_LONG + " " + "a" + str(i)) + else: + args_list += (JAVA_TYPE_INT + " " + "a" + str(i)) + else: + args_list += ("a" + str(i)) + return args_list + + +def genArgsListForCallOriginMethod(is64Bit, length): + arg_name = """args[%s]""" + args_list = "" + for i in range(length): + if (i != 0): + args_list += ", " + if (is64Bit): + args_list += arg_name % i + else: + args_list += (JAVA_CAST_INT + arg_name % i) + return args_list + + +def genHookMethod(is64Bit, args, index): + java_type = JAVA_TYPE_LONG if is64Bit else JAVA_TYPE_INT + cast = "" if is64Bit else JAVA_CAST_INT + args_list_pre = ", " if args > 0 else "" + args_list = genArgsList(is64Bit, False, args) + args_list_def = genArgsList(is64Bit, True, args) + call_origin_obj = ("new " + getCallOriginClassName(args, index) + "()") if HAS_BACKUP else "null" + method = TEMP_STUB_HOOK_METHOD % (java_type, getMethodHookName(index), args_list_def, cast, getMethodId(args, index), call_origin_obj, args_list_pre + args_list) + return method + + +def genBackupMethod(is64Bit, args, index): + java_type = JAVA_TYPE_LONG if is64Bit else JAVA_TYPE_INT + args_list_def = genArgsList(is64Bit, True, args) + method = TEMP_STUB_BACKUP_METHOD % (java_type, getMethodBackupName(index), args_list_def, getMethodId(args, index)) + return method + +def genCallOriginClass(is64Bit, args, index): + method = TEMP_STUB_CALL_ORIGIN_CLASS % (getCallOriginClassName(args, index), getMethodBackupName(index), genArgsListForCallOriginMethod(is64Bit, args)) + return method + +def genStubInfo(): + hasStub = "true" if HAS_BACKUP else "false" + stubSizes = "" + for args in range(len(STUB_SIZES)): + if (args != 0): + stubSizes += ", " + stubSizes += str(STUB_SIZES[args]) + return TEMP_STUB_INFO % (hasStub, stubSizes) + +def gen32Stub(packageDir): + class_content = genStubInfo() + class_name = STUB_FILE_NAME + "32" + for args in range(len(STUB_SIZES)): + for index in range(STUB_SIZES[args]): + class_content += """\n\n\t//stub of arg size %d, index %d""" % (args, index) + class_content += genHookMethod(False, args, index) + if HAS_BACKUP: + class_content += "\n" + class_content += genCallOriginClass(False, args, index) + class_content += "\n" + class_content += genBackupMethod(False, args, index) + class_content += "\n" + class_str = TEMP_STUB_CLASS_WRAPPER % (32, class_content) + javaFile = open(os.path.join(packageDir, class_name + ".java"), "w") + javaFile.write(class_str) + javaFile.close() + + +def gen64Stub(packageDir): + class_content = genStubInfo() + class_name = STUB_FILE_NAME + "64" + for args in range(len(STUB_SIZES)): + for index in range(STUB_SIZES[args]): + class_content += """\n\n\t//stub of arg size %d, index %d""" % (args, index) + class_content += genHookMethod(True, args, index) + if HAS_BACKUP: + class_content += "\n" + class_content += genCallOriginClass(True, args, index) + class_content += "\n" + class_content += genBackupMethod(True, args, index) + class_content += "\n" + class_str = TEMP_STUB_CLASS_WRAPPER % (64, class_content) + javaFile = open(os.path.join(packageDir, class_name + ".java"), "w") + javaFile.write(class_str) + javaFile.close() + + +def genStub(packageDir): + for fileName in os.listdir(packageDir): + if fileName.startswith(STUB_FILE_NAME): + os.remove(os.path.join(packageDir, fileName)) + gen32Stub(packageDir) + gen64Stub(packageDir) + + +if __name__ == "__main__": + genStub(os.path.join(os.path.dirname(os.path.realpath(__file__)), + "src/main/java/com/swift/sandhook/xposedcompat/hookstub")) diff --git a/sandhook/proguard-rules.pro b/sandhook/proguard-rules.pro new file mode 100644 index 000000000..f1b424510 --- /dev/null +++ b/sandhook/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/sandhook/src/main/AndroidManifest.xml b/sandhook/src/main/AndroidManifest.xml new file mode 100644 index 000000000..da51e6e47 --- /dev/null +++ b/sandhook/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + diff --git a/sandhook/src/main/java/com/swift/sandhook/xposedcompat/XposedCompat.java b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/XposedCompat.java new file mode 100644 index 000000000..a57a09f86 --- /dev/null +++ b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/XposedCompat.java @@ -0,0 +1,51 @@ +package com.swift.sandhook.xposedcompat; + +import com.swift.sandhook.xposedcompat.classloaders.ComposeClassLoader; +import com.swift.sandhook.xposedcompat.methodgen.SandHookXposedBridge; +import com.swift.sandhook.xposedcompat.utils.FileUtils; + +import java.io.File; +import java.lang.reflect.Member; + +import de.robv.android.xposed.XposedBridge; + +public class XposedCompat { + + public static 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 retryWhenCallOriginError = false; + + private static ClassLoader sandHookXposedClassLoader; + + public static synchronized void hookMethod(Member hookMethod, XposedBridge.AdditionalHookInfo additionalHookInfo) { + SandHookXposedBridge.hookMethod(hookMethod, additionalHookInfo); + } + + public static ClassLoader getSandHookXposedClassLoader(ClassLoader appOriginClassLoader, ClassLoader sandBoxHostClassLoader) { + if (sandHookXposedClassLoader != null) { + return sandHookXposedClassLoader; + } else { + sandHookXposedClassLoader = new ComposeClassLoader(sandBoxHostClassLoader, appOriginClassLoader); + return sandHookXposedClassLoader; + } + } + + public static boolean clearCache() { + try { + FileUtils.delete(cacheDir); + cacheDir.mkdirs(); + return true; + } catch (Throwable throwable) { + return false; + } + } + + public static void clearOatCache() { + SandHookXposedBridge.clearOatFile(); + } + +} diff --git a/sandhook/src/main/java/com/swift/sandhook/xposedcompat/classloaders/ComposeClassLoader.java b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/classloaders/ComposeClassLoader.java new file mode 100644 index 000000000..6d968f6f1 --- /dev/null +++ b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/classloaders/ComposeClassLoader.java @@ -0,0 +1,34 @@ +package com.swift.sandhook.xposedcompat.classloaders; + +/** + * Created by weishu on 17/11/30. + */ + +public class ComposeClassLoader extends ClassLoader { + + private final ClassLoader mAppClassLoader; + public ComposeClassLoader(ClassLoader parent, ClassLoader appClassLoader) { + super(parent); + mAppClassLoader = appClassLoader; + } + + @Override + protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + Class clazz = null; + + try { + clazz = mAppClassLoader.loadClass(name); + } catch (ClassNotFoundException e) { + // IGNORE. + } + if (clazz == null) { + clazz = super.loadClass(name, resolve); + } + + if (clazz == null) { + throw new ClassNotFoundException(); + } + + return clazz; + } +} diff --git a/sandhook/src/main/java/com/swift/sandhook/xposedcompat/hookstub/CallOriginCallBack.java b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/hookstub/CallOriginCallBack.java new file mode 100644 index 000000000..65657ef3e --- /dev/null +++ b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/hookstub/CallOriginCallBack.java @@ -0,0 +1,5 @@ +package com.swift.sandhook.xposedcompat.hookstub; + +public interface CallOriginCallBack { + long call(long... args) throws Throwable; +} diff --git a/sandhook/src/main/java/com/swift/sandhook/xposedcompat/hookstub/HookMethodEntity.java b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/hookstub/HookMethodEntity.java new file mode 100644 index 000000000..1436908c2 --- /dev/null +++ b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/hookstub/HookMethodEntity.java @@ -0,0 +1,93 @@ +package com.swift.sandhook.xposedcompat.hookstub; + +import com.swift.sandhook.SandHook; +import com.swift.sandhook.utils.ParamWrapper; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +public class HookMethodEntity { + + public Member origin; + public Method hook; + public Method backup; + public Class[] parType; + public Class retType; + + public HookMethodEntity(Member origin, Method hook, Method backup) { + this.origin = origin; + this.hook = hook; + this.backup = backup; + } + + public Object[] getArgs(long... addresses) { + if (addresses == null || addresses.length == 0) + return new Object[0]; + if (parType == null || parType.length == 0) + return new Object[0]; + int argStart = 0; + if (!isStatic()) { + argStart = 1; + } + Object[] args = new Object[parType.length]; + for (int i = argStart;i < parType.length + argStart;i++) { + args[i - argStart] = getArg(i - argStart, addresses[i]); + } + return args; + } + + public long[] getArgsAddress(long[] oldAddress, Object... args) { + if (oldAddress == null || oldAddress.length == 0) + return new long[0]; + long[] addresses; + int argStart = 0; + if (!isStatic()) { + argStart = 1; + addresses = new long[oldAddress.length + 1]; + addresses[0] = oldAddress[0]; + } else { + addresses = new long[oldAddress.length]; + } + for (int i = 0;i < parType.length;i++) { + addresses[i + argStart] = ParamWrapper.objectToAddress(parType[i], args[i]); + } + return addresses; + } + + public Object getThis(long address) { + if (isStatic()) + return null; + return SandHook.getObject(address); + } + + public Object getArg(int index, long address) { + return ParamWrapper.addressToObject(parType[index], address); + } + + public Object getResult(long address) { + if (isVoid()) + return null; + return ParamWrapper.addressToObject(retType, address); + } + + public long getResultAddress(Object result) { + if (isVoid()) + return 0; + return ParamWrapper.objectToAddress(retType, result); + } + + public boolean isVoid() { + return retType == null || Void.TYPE.equals(retType); + } + + public boolean isConstructor() { + return origin instanceof Constructor; + } + + public boolean isStatic() { + return Modifier.isStatic(origin.getModifiers()); + } + +} diff --git a/sandhook/src/main/java/com/swift/sandhook/xposedcompat/hookstub/HookStubManager.java b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/hookstub/HookStubManager.java new file mode 100644 index 000000000..1b27ed4ae --- /dev/null +++ b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/hookstub/HookStubManager.java @@ -0,0 +1,409 @@ +package com.swift.sandhook.xposedcompat.hookstub; + +import android.util.Log; + +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.utils.DexLog; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; + +import de.robv.android.xposed.XC_MethodHook; +import de.robv.android.xposed.XposedBridge; +import de.robv.android.xposed.XposedHelpers; + +import static de.robv.android.xposed.XposedBridge.sHookedMethodCallbacks; + +public class HookStubManager { + + + public static int MAX_STUB_ARGS = 0; + + public static int[] stubSizes; + + public static boolean hasStubBackup = false; + + public static AtomicInteger[] curUseStubIndexes; + + public static int ALL_STUB = 0; + + public static Member[] originMethods; + public static HookMethodEntity[] hookMethodEntities; + + private static final Map> hookCallbacks + = sHookedMethodCallbacks; + + static { + Class stubClass = SandHook.is64Bit() ? MethodHookerStubs64.class : MethodHookerStubs32.class; + stubSizes = (int[]) XposedHelpers.getStaticObjectField(stubClass, "stubSizes"); + Boolean hasBackup = (Boolean) XposedHelpers.getStaticObjectField(stubClass, "hasStubBackup"); + hasStubBackup = hasBackup == null ? false : hasBackup; + if (stubSizes != null && stubSizes.length > 0) { + MAX_STUB_ARGS = stubSizes.length - 1; + curUseStubIndexes = new AtomicInteger[MAX_STUB_ARGS + 1]; + for (int i = 0; i < MAX_STUB_ARGS + 1; i++) { + curUseStubIndexes[i] = new AtomicInteger(0); + ALL_STUB += stubSizes[i]; + } + originMethods = new Member[ALL_STUB]; + hookMethodEntities = new HookMethodEntity[ALL_STUB]; + } + } + + + public static HookMethodEntity getHookMethodEntity(Member origin) { + + if (!support()) { + return null; + } + + Class[] parType; + Class retType; + boolean isStatic = Modifier.isStatic(origin.getModifiers()); + + if (origin instanceof Method) { + Method method = (Method) origin; + retType = method.getReturnType(); + parType = method.getParameterTypes(); + } else if (origin instanceof Constructor) { + Constructor constructor = (Constructor) origin; + retType = Void.TYPE; + parType = constructor.getParameterTypes(); + } else { + return null; + } + + if (!ParamWrapper.support(retType)) + return null; + + int needStubArgCount = isStatic ? 0 : 1; + + if (parType != null) { + needStubArgCount += parType.length; + if (needStubArgCount > MAX_STUB_ARGS) + return null; + for (Class par:parType) { + if (!ParamWrapper.support(par)) + return null; + } + } else { + parType = new Class[0]; + } + + synchronized (HookStubManager.class) { + StubMethodsInfo stubMethodInfo = getStubMethodPair(SandHook.is64Bit(), needStubArgCount); + if (stubMethodInfo == null) + return null; + HookMethodEntity entity = new HookMethodEntity(origin, stubMethodInfo.hook, stubMethodInfo.backup); + entity.retType = retType; + entity.parType = parType; + int id = getMethodId(stubMethodInfo.args, stubMethodInfo.index); + originMethods[id] = origin; + hookMethodEntities[id] = entity; + if (hasStubBackup && !tryCompileAndResolveCallOriginMethod(entity.backup, stubMethodInfo.args, stubMethodInfo.index)) { + DexLog.w("internal stub <" + entity.hook.getName() + "> call origin compile failure, skip use internal stub"); + return null; + } else { + return entity; + } + } + } + + public static int getMethodId(int args, int index) { + int id = index; + for (int i = 0;i < args;i++) { + id += stubSizes[i]; + } + return id; + } + + public static String getHookMethodName(int index) { + return "stub_hook_" + index; + } + + public static String getBackupMethodName(int index) { + return "stub_backup_" + index; + } + + public static String getCallOriginClassName(int args, int index) { + return "call_origin_" + args + "_" + index; + } + + + static class StubMethodsInfo { + int args = 0; + int index = 0; + Method hook; + Method backup; + + public StubMethodsInfo(int args, int index, Method hook, Method backup) { + this.args = args; + this.index = index; + this.hook = hook; + this.backup = backup; + } + } + + private static synchronized StubMethodsInfo getStubMethodPair(boolean is64Bit, int stubArgs) { + + stubArgs = getMatchStubArgsCount(stubArgs); + + if (stubArgs < 0) + return null; + + int curUseStubIndex = curUseStubIndexes[stubArgs].getAndIncrement(); + Class[] pars = getFindMethodParTypes(is64Bit, stubArgs); + try { + if (is64Bit) { + Method hook = MethodHookerStubs64.class.getDeclaredMethod(getHookMethodName(curUseStubIndex), pars); + Method backup = hasStubBackup ? MethodHookerStubs64.class.getDeclaredMethod(getBackupMethodName(curUseStubIndex), pars) : BackupMethodStubs.getStubMethod(); + if (hook == null || backup == null) + return null; + return new StubMethodsInfo(stubArgs, curUseStubIndex, hook, backup); + } else { + Method hook = MethodHookerStubs32.class.getDeclaredMethod(getHookMethodName(curUseStubIndex), pars); + Method backup = hasStubBackup ? MethodHookerStubs32.class.getDeclaredMethod(getBackupMethodName(curUseStubIndex), pars) : BackupMethodStubs.getStubMethod(); + if (hook == null || backup == null) + return null; + return new StubMethodsInfo(stubArgs, curUseStubIndex, hook, backup); + } + } catch (Throwable throwable) { + return null; + } + } + + public static Method getCallOriginMethod(int args, int index) { + Class stubClass = SandHook.is64Bit() ? MethodHookerStubs64.class : MethodHookerStubs32.class; + String className = stubClass.getName(); + className += "$"; + className += getCallOriginClassName(args, index); + try { + Class callOriginClass = Class.forName(className, true, stubClass.getClassLoader()); + return callOriginClass.getDeclaredMethod("call", long[].class); + } catch (Throwable e) { + Log.e("HookStubManager", "load call origin class error!", e); + return null; + } + } + + public static boolean tryCompileAndResolveCallOriginMethod(Method backupMethod, int args, int index) { + Method method = getCallOriginMethod(args, index); + if (method != null) { + SandHookMethodResolver.resolveMethod(method, backupMethod); + return SandHook.compileMethod(method); + } else { + return false; + } + } + + public static int getMatchStubArgsCount(int stubArgs) { + for (int i = stubArgs;i <= MAX_STUB_ARGS;i++) { + if (curUseStubIndexes[i].get() < stubSizes[i]) + return i; + } + return -1; + } + + public static Class[] getFindMethodParTypes(boolean is64Bit, int stubArgs) { + if (stubArgs == 0) + return null; + Class[] args = new Class[stubArgs]; + if (is64Bit) { + for (int i = 0;i < stubArgs;i++) { + args[i] = long.class; + } + } else { + for (int i = 0;i < stubArgs;i++) { + args[i] = int.class; + } + } + return args; + } + + public static long hookBridge(int id, CallOriginCallBack callOrigin, long... stubArgs) throws Throwable { + + Member originMethod = originMethods[id]; + HookMethodEntity entity = hookMethodEntities[id]; + + Object thiz = null; + Object[] args = null; + + if (hasArgs(stubArgs)) { + thiz = entity.getThis(stubArgs[0]); + args = entity.getArgs(stubArgs); + } + + if (XposedBridge.disableHooks) { + if (hasStubBackup) { + return callOrigin.call(stubArgs); + } else { + return callOrigin(entity, originMethod, thiz, args); + } + } + + DexLog.printMethodHookIn(originMethod); + + Object[] snapshot = hookCallbacks.get(originMethod).getSnapshot(); + if (snapshot == null || snapshot.length == 0) { + if (hasStubBackup) { + return callOrigin.call(stubArgs); + } else { + return callOrigin(entity, originMethod, thiz, args); + } + } + + XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam(); + + param.method = originMethod; + param.thisObject = thiz; + param.args = args; + + int beforeIdx = 0; + do { + try { + ((XC_MethodHook) snapshot[beforeIdx]).callBeforeHookedMethod(param); + } catch (Throwable t) { + // reset result (ignoring what the unexpectedly exiting callback did) + param.setResult(null); + param.returnEarly = false; + continue; + } + + if (param.returnEarly) { + // skip remaining "before" callbacks and corresponding "after" callbacks + beforeIdx++; + break; + } + } while (++beforeIdx < snapshot.length); + + // call original method if not requested otherwise + if (!param.returnEarly) { + try { + if (hasStubBackup) { + //prepare new args + long[] newArgs = entity.getArgsAddress(stubArgs, param.args); + param.setResult(entity.getResult(callOrigin.call(newArgs))); + } else { + param.setResult(SandHook.callOriginMethod(originMethod, thiz, param.args)); + } + } catch (Throwable e) { + XposedBridge.log(e); + param.setThrowable(e); + } + } + + // call "after method" callbacks + int afterIdx = beforeIdx - 1; + do { + Object lastResult = param.getResult(); + Throwable lastThrowable = param.getThrowable(); + + try { + ((XC_MethodHook) snapshot[afterIdx]).callAfterHookedMethod(param); + } catch (Throwable t) { + XposedBridge.log(t); + if (lastThrowable == null) + param.setResult(lastResult); + else + param.setThrowable(lastThrowable); + } + } while (--afterIdx >= 0); + if (!param.hasThrowable()) { + return entity.getResultAddress(param.getResult()); + } else { + throw param.getThrowable(); + } + } + + public static Object hookBridge(Member origin, Object thiz, Object... args) throws Throwable { + + + if (XposedBridge.disableHooks) { + return SandHook.callOriginMethod(origin, thiz, args); + } + + DexLog.printMethodHookIn(origin); + + Object[] snapshot = hookCallbacks.get(origin).getSnapshot(); + if (snapshot == null || snapshot.length == 0) { + return SandHook.callOriginMethod(origin, thiz, args); + } + + XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam(); + + param.method = origin; + param.thisObject = thiz; + param.args = args; + + int beforeIdx = 0; + do { + try { + ((XC_MethodHook) snapshot[beforeIdx]).callBeforeHookedMethod(param); + } catch (Throwable t) { + // reset result (ignoring what the unexpectedly exiting callback did) + param.setResult(null); + param.returnEarly = false; + continue; + } + + if (param.returnEarly) { + // skip remaining "before" callbacks and corresponding "after" callbacks + beforeIdx++; + break; + } + } while (++beforeIdx < snapshot.length); + + // call original method if not requested otherwise + if (!param.returnEarly) { + try { + param.setResult(SandHook.callOriginMethod(origin, thiz, param.args)); + } catch (Throwable e) { + XposedBridge.log(e); + param.setThrowable(e); + } + } + + // call "after method" callbacks + int afterIdx = beforeIdx - 1; + do { + Object lastResult = param.getResult(); + Throwable lastThrowable = param.getThrowable(); + + try { + ((XC_MethodHook) snapshot[afterIdx]).callAfterHookedMethod(param); + } catch (Throwable t) { + XposedBridge.log(t); + if (lastThrowable == null) + param.setResult(lastResult); + else + param.setThrowable(lastThrowable); + } + } while (--afterIdx >= 0); + if (!param.hasThrowable()) { + return param.getResult(); + } else { + throw param.getThrowable(); + } + } + + public static long callOrigin(HookMethodEntity entity, Member origin, Object thiz, Object[] args) throws Throwable { + Object res = SandHook.callOriginMethod(origin, thiz, args); + return entity.getResultAddress(res); + } + + private static boolean hasArgs(long... args) { + return args != null && args.length > 0; + } + + public static boolean support() { + return MAX_STUB_ARGS > 0 && SandHook.canGetObject() && SandHook.canGetObjectAddress(); + } + +} diff --git a/sandhook/src/main/java/com/swift/sandhook/xposedcompat/hookstub/MethodHookerStubs32.java b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/hookstub/MethodHookerStubs32.java new file mode 100644 index 000000000..a1026f752 --- /dev/null +++ b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/hookstub/MethodHookerStubs32.java @@ -0,0 +1,1415 @@ +package com.swift.sandhook.xposedcompat.hookstub; + +import static com.swift.sandhook.xposedcompat.hookstub.HookStubManager.hookBridge; +import static com.swift.sandhook.xposedcompat.hookstub.HookStubManager.getMethodId; +import static com.swift.sandhook.xposedcompat.hookstub.HookStubManager.originMethods; +import static com.swift.sandhook.xposedcompat.utils.DexLog.printCallOriginError; + +/** +* this file is auto gen by genhookstubs.py +* it is for sandhook internal hooker & backup methods +**/ +public class MethodHookerStubs32 { + + public static boolean hasStubBackup = false; + public static int[] stubSizes = {10, 20, 30, 30, 30, 30, 30, 20, 10, 10, 5, 5, 3}; + + + //stub of arg size 0, index 0 + public static int stub_hook_0() throws Throwable { + return (int) hookBridge(getMethodId(0, 0), null ); + } + + + //stub of arg size 0, index 1 + public static int stub_hook_1() throws Throwable { + return (int) hookBridge(getMethodId(0, 1), null ); + } + + + //stub of arg size 0, index 2 + public static int stub_hook_2() throws Throwable { + return (int) hookBridge(getMethodId(0, 2), null ); + } + + + //stub of arg size 0, index 3 + public static int stub_hook_3() throws Throwable { + return (int) hookBridge(getMethodId(0, 3), null ); + } + + + //stub of arg size 0, index 4 + public static int stub_hook_4() throws Throwable { + return (int) hookBridge(getMethodId(0, 4), null ); + } + + + //stub of arg size 0, index 5 + public static int stub_hook_5() throws Throwable { + return (int) hookBridge(getMethodId(0, 5), null ); + } + + + //stub of arg size 0, index 6 + public static int stub_hook_6() throws Throwable { + return (int) hookBridge(getMethodId(0, 6), null ); + } + + + //stub of arg size 0, index 7 + public static int stub_hook_7() throws Throwable { + return (int) hookBridge(getMethodId(0, 7), null ); + } + + + //stub of arg size 0, index 8 + public static int stub_hook_8() throws Throwable { + return (int) hookBridge(getMethodId(0, 8), null ); + } + + + //stub of arg size 0, index 9 + public static int stub_hook_9() throws Throwable { + return (int) hookBridge(getMethodId(0, 9), null ); + } + + + //stub of arg size 1, index 0 + public static int stub_hook_0(int a0) throws Throwable { + return (int) hookBridge(getMethodId(1, 0), null , a0); + } + + + //stub of arg size 1, index 1 + public static int stub_hook_1(int a0) throws Throwable { + return (int) hookBridge(getMethodId(1, 1), null , a0); + } + + + //stub of arg size 1, index 2 + public static int stub_hook_2(int a0) throws Throwable { + return (int) hookBridge(getMethodId(1, 2), null , a0); + } + + + //stub of arg size 1, index 3 + public static int stub_hook_3(int a0) throws Throwable { + return (int) hookBridge(getMethodId(1, 3), null , a0); + } + + + //stub of arg size 1, index 4 + public static int stub_hook_4(int a0) throws Throwable { + return (int) hookBridge(getMethodId(1, 4), null , a0); + } + + + //stub of arg size 1, index 5 + public static int stub_hook_5(int a0) throws Throwable { + return (int) hookBridge(getMethodId(1, 5), null , a0); + } + + + //stub of arg size 1, index 6 + public static int stub_hook_6(int a0) throws Throwable { + return (int) hookBridge(getMethodId(1, 6), null , a0); + } + + + //stub of arg size 1, index 7 + public static int stub_hook_7(int a0) throws Throwable { + return (int) hookBridge(getMethodId(1, 7), null , a0); + } + + + //stub of arg size 1, index 8 + public static int stub_hook_8(int a0) throws Throwable { + return (int) hookBridge(getMethodId(1, 8), null , a0); + } + + + //stub of arg size 1, index 9 + public static int stub_hook_9(int a0) throws Throwable { + return (int) hookBridge(getMethodId(1, 9), null , a0); + } + + + //stub of arg size 1, index 10 + public static int stub_hook_10(int a0) throws Throwable { + return (int) hookBridge(getMethodId(1, 10), null , a0); + } + + + //stub of arg size 1, index 11 + public static int stub_hook_11(int a0) throws Throwable { + return (int) hookBridge(getMethodId(1, 11), null , a0); + } + + + //stub of arg size 1, index 12 + public static int stub_hook_12(int a0) throws Throwable { + return (int) hookBridge(getMethodId(1, 12), null , a0); + } + + + //stub of arg size 1, index 13 + public static int stub_hook_13(int a0) throws Throwable { + return (int) hookBridge(getMethodId(1, 13), null , a0); + } + + + //stub of arg size 1, index 14 + public static int stub_hook_14(int a0) throws Throwable { + return (int) hookBridge(getMethodId(1, 14), null , a0); + } + + + //stub of arg size 1, index 15 + public static int stub_hook_15(int a0) throws Throwable { + return (int) hookBridge(getMethodId(1, 15), null , a0); + } + + + //stub of arg size 1, index 16 + public static int stub_hook_16(int a0) throws Throwable { + return (int) hookBridge(getMethodId(1, 16), null , a0); + } + + + //stub of arg size 1, index 17 + public static int stub_hook_17(int a0) throws Throwable { + return (int) hookBridge(getMethodId(1, 17), null , a0); + } + + + //stub of arg size 1, index 18 + public static int stub_hook_18(int a0) throws Throwable { + return (int) hookBridge(getMethodId(1, 18), null , a0); + } + + + //stub of arg size 1, index 19 + public static int stub_hook_19(int a0) throws Throwable { + return (int) hookBridge(getMethodId(1, 19), null , a0); + } + + + //stub of arg size 2, index 0 + public static int stub_hook_0(int a0, int a1) throws Throwable { + return (int) hookBridge(getMethodId(2, 0), null , a0, a1); + } + + + //stub of arg size 2, index 1 + public static int stub_hook_1(int a0, int a1) throws Throwable { + return (int) hookBridge(getMethodId(2, 1), null , a0, a1); + } + + + //stub of arg size 2, index 2 + public static int stub_hook_2(int a0, int a1) throws Throwable { + return (int) hookBridge(getMethodId(2, 2), null , a0, a1); + } + + + //stub of arg size 2, index 3 + public static int stub_hook_3(int a0, int a1) throws Throwable { + return (int) hookBridge(getMethodId(2, 3), null , a0, a1); + } + + + //stub of arg size 2, index 4 + public static int stub_hook_4(int a0, int a1) throws Throwable { + return (int) hookBridge(getMethodId(2, 4), null , a0, a1); + } + + + //stub of arg size 2, index 5 + public static int stub_hook_5(int a0, int a1) throws Throwable { + return (int) hookBridge(getMethodId(2, 5), null , a0, a1); + } + + + //stub of arg size 2, index 6 + public static int stub_hook_6(int a0, int a1) throws Throwable { + return (int) hookBridge(getMethodId(2, 6), null , a0, a1); + } + + + //stub of arg size 2, index 7 + public static int stub_hook_7(int a0, int a1) throws Throwable { + return (int) hookBridge(getMethodId(2, 7), null , a0, a1); + } + + + //stub of arg size 2, index 8 + public static int stub_hook_8(int a0, int a1) throws Throwable { + return (int) hookBridge(getMethodId(2, 8), null , a0, a1); + } + + + //stub of arg size 2, index 9 + public static int stub_hook_9(int a0, int a1) throws Throwable { + return (int) hookBridge(getMethodId(2, 9), null , a0, a1); + } + + + //stub of arg size 2, index 10 + public static int stub_hook_10(int a0, int a1) throws Throwable { + return (int) hookBridge(getMethodId(2, 10), null , a0, a1); + } + + + //stub of arg size 2, index 11 + public static int stub_hook_11(int a0, int a1) throws Throwable { + return (int) hookBridge(getMethodId(2, 11), null , a0, a1); + } + + + //stub of arg size 2, index 12 + public static int stub_hook_12(int a0, int a1) throws Throwable { + return (int) hookBridge(getMethodId(2, 12), null , a0, a1); + } + + + //stub of arg size 2, index 13 + public static int stub_hook_13(int a0, int a1) throws Throwable { + return (int) hookBridge(getMethodId(2, 13), null , a0, a1); + } + + + //stub of arg size 2, index 14 + public static int stub_hook_14(int a0, int a1) throws Throwable { + return (int) hookBridge(getMethodId(2, 14), null , a0, a1); + } + + + //stub of arg size 2, index 15 + public static int stub_hook_15(int a0, int a1) throws Throwable { + return (int) hookBridge(getMethodId(2, 15), null , a0, a1); + } + + + //stub of arg size 2, index 16 + public static int stub_hook_16(int a0, int a1) throws Throwable { + return (int) hookBridge(getMethodId(2, 16), null , a0, a1); + } + + + //stub of arg size 2, index 17 + public static int stub_hook_17(int a0, int a1) throws Throwable { + return (int) hookBridge(getMethodId(2, 17), null , a0, a1); + } + + + //stub of arg size 2, index 18 + public static int stub_hook_18(int a0, int a1) throws Throwable { + return (int) hookBridge(getMethodId(2, 18), null , a0, a1); + } + + + //stub of arg size 2, index 19 + public static int stub_hook_19(int a0, int a1) throws Throwable { + return (int) hookBridge(getMethodId(2, 19), null , a0, a1); + } + + + //stub of arg size 2, index 20 + public static int stub_hook_20(int a0, int a1) throws Throwable { + return (int) hookBridge(getMethodId(2, 20), null , a0, a1); + } + + + //stub of arg size 2, index 21 + public static int stub_hook_21(int a0, int a1) throws Throwable { + return (int) hookBridge(getMethodId(2, 21), null , a0, a1); + } + + + //stub of arg size 2, index 22 + public static int stub_hook_22(int a0, int a1) throws Throwable { + return (int) hookBridge(getMethodId(2, 22), null , a0, a1); + } + + + //stub of arg size 2, index 23 + public static int stub_hook_23(int a0, int a1) throws Throwable { + return (int) hookBridge(getMethodId(2, 23), null , a0, a1); + } + + + //stub of arg size 2, index 24 + public static int stub_hook_24(int a0, int a1) throws Throwable { + return (int) hookBridge(getMethodId(2, 24), null , a0, a1); + } + + + //stub of arg size 2, index 25 + public static int stub_hook_25(int a0, int a1) throws Throwable { + return (int) hookBridge(getMethodId(2, 25), null , a0, a1); + } + + + //stub of arg size 2, index 26 + public static int stub_hook_26(int a0, int a1) throws Throwable { + return (int) hookBridge(getMethodId(2, 26), null , a0, a1); + } + + + //stub of arg size 2, index 27 + public static int stub_hook_27(int a0, int a1) throws Throwable { + return (int) hookBridge(getMethodId(2, 27), null , a0, a1); + } + + + //stub of arg size 2, index 28 + public static int stub_hook_28(int a0, int a1) throws Throwable { + return (int) hookBridge(getMethodId(2, 28), null , a0, a1); + } + + + //stub of arg size 2, index 29 + public static int stub_hook_29(int a0, int a1) throws Throwable { + return (int) hookBridge(getMethodId(2, 29), null , a0, a1); + } + + + //stub of arg size 3, index 0 + public static int stub_hook_0(int a0, int a1, int a2) throws Throwable { + return (int) hookBridge(getMethodId(3, 0), null , a0, a1, a2); + } + + + //stub of arg size 3, index 1 + public static int stub_hook_1(int a0, int a1, int a2) throws Throwable { + return (int) hookBridge(getMethodId(3, 1), null , a0, a1, a2); + } + + + //stub of arg size 3, index 2 + public static int stub_hook_2(int a0, int a1, int a2) throws Throwable { + return (int) hookBridge(getMethodId(3, 2), null , a0, a1, a2); + } + + + //stub of arg size 3, index 3 + public static int stub_hook_3(int a0, int a1, int a2) throws Throwable { + return (int) hookBridge(getMethodId(3, 3), null , a0, a1, a2); + } + + + //stub of arg size 3, index 4 + public static int stub_hook_4(int a0, int a1, int a2) throws Throwable { + return (int) hookBridge(getMethodId(3, 4), null , a0, a1, a2); + } + + + //stub of arg size 3, index 5 + public static int stub_hook_5(int a0, int a1, int a2) throws Throwable { + return (int) hookBridge(getMethodId(3, 5), null , a0, a1, a2); + } + + + //stub of arg size 3, index 6 + public static int stub_hook_6(int a0, int a1, int a2) throws Throwable { + return (int) hookBridge(getMethodId(3, 6), null , a0, a1, a2); + } + + + //stub of arg size 3, index 7 + public static int stub_hook_7(int a0, int a1, int a2) throws Throwable { + return (int) hookBridge(getMethodId(3, 7), null , a0, a1, a2); + } + + + //stub of arg size 3, index 8 + public static int stub_hook_8(int a0, int a1, int a2) throws Throwable { + return (int) hookBridge(getMethodId(3, 8), null , a0, a1, a2); + } + + + //stub of arg size 3, index 9 + public static int stub_hook_9(int a0, int a1, int a2) throws Throwable { + return (int) hookBridge(getMethodId(3, 9), null , a0, a1, a2); + } + + + //stub of arg size 3, index 10 + public static int stub_hook_10(int a0, int a1, int a2) throws Throwable { + return (int) hookBridge(getMethodId(3, 10), null , a0, a1, a2); + } + + + //stub of arg size 3, index 11 + public static int stub_hook_11(int a0, int a1, int a2) throws Throwable { + return (int) hookBridge(getMethodId(3, 11), null , a0, a1, a2); + } + + + //stub of arg size 3, index 12 + public static int stub_hook_12(int a0, int a1, int a2) throws Throwable { + return (int) hookBridge(getMethodId(3, 12), null , a0, a1, a2); + } + + + //stub of arg size 3, index 13 + public static int stub_hook_13(int a0, int a1, int a2) throws Throwable { + return (int) hookBridge(getMethodId(3, 13), null , a0, a1, a2); + } + + + //stub of arg size 3, index 14 + public static int stub_hook_14(int a0, int a1, int a2) throws Throwable { + return (int) hookBridge(getMethodId(3, 14), null , a0, a1, a2); + } + + + //stub of arg size 3, index 15 + public static int stub_hook_15(int a0, int a1, int a2) throws Throwable { + return (int) hookBridge(getMethodId(3, 15), null , a0, a1, a2); + } + + + //stub of arg size 3, index 16 + public static int stub_hook_16(int a0, int a1, int a2) throws Throwable { + return (int) hookBridge(getMethodId(3, 16), null , a0, a1, a2); + } + + + //stub of arg size 3, index 17 + public static int stub_hook_17(int a0, int a1, int a2) throws Throwable { + return (int) hookBridge(getMethodId(3, 17), null , a0, a1, a2); + } + + + //stub of arg size 3, index 18 + public static int stub_hook_18(int a0, int a1, int a2) throws Throwable { + return (int) hookBridge(getMethodId(3, 18), null , a0, a1, a2); + } + + + //stub of arg size 3, index 19 + public static int stub_hook_19(int a0, int a1, int a2) throws Throwable { + return (int) hookBridge(getMethodId(3, 19), null , a0, a1, a2); + } + + + //stub of arg size 3, index 20 + public static int stub_hook_20(int a0, int a1, int a2) throws Throwable { + return (int) hookBridge(getMethodId(3, 20), null , a0, a1, a2); + } + + + //stub of arg size 3, index 21 + public static int stub_hook_21(int a0, int a1, int a2) throws Throwable { + return (int) hookBridge(getMethodId(3, 21), null , a0, a1, a2); + } + + + //stub of arg size 3, index 22 + public static int stub_hook_22(int a0, int a1, int a2) throws Throwable { + return (int) hookBridge(getMethodId(3, 22), null , a0, a1, a2); + } + + + //stub of arg size 3, index 23 + public static int stub_hook_23(int a0, int a1, int a2) throws Throwable { + return (int) hookBridge(getMethodId(3, 23), null , a0, a1, a2); + } + + + //stub of arg size 3, index 24 + public static int stub_hook_24(int a0, int a1, int a2) throws Throwable { + return (int) hookBridge(getMethodId(3, 24), null , a0, a1, a2); + } + + + //stub of arg size 3, index 25 + public static int stub_hook_25(int a0, int a1, int a2) throws Throwable { + return (int) hookBridge(getMethodId(3, 25), null , a0, a1, a2); + } + + + //stub of arg size 3, index 26 + public static int stub_hook_26(int a0, int a1, int a2) throws Throwable { + return (int) hookBridge(getMethodId(3, 26), null , a0, a1, a2); + } + + + //stub of arg size 3, index 27 + public static int stub_hook_27(int a0, int a1, int a2) throws Throwable { + return (int) hookBridge(getMethodId(3, 27), null , a0, a1, a2); + } + + + //stub of arg size 3, index 28 + public static int stub_hook_28(int a0, int a1, int a2) throws Throwable { + return (int) hookBridge(getMethodId(3, 28), null , a0, a1, a2); + } + + + //stub of arg size 3, index 29 + public static int stub_hook_29(int a0, int a1, int a2) throws Throwable { + return (int) hookBridge(getMethodId(3, 29), null , a0, a1, a2); + } + + + //stub of arg size 4, index 0 + public static int stub_hook_0(int a0, int a1, int a2, int a3) throws Throwable { + return (int) hookBridge(getMethodId(4, 0), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 1 + public static int stub_hook_1(int a0, int a1, int a2, int a3) throws Throwable { + return (int) hookBridge(getMethodId(4, 1), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 2 + public static int stub_hook_2(int a0, int a1, int a2, int a3) throws Throwable { + return (int) hookBridge(getMethodId(4, 2), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 3 + public static int stub_hook_3(int a0, int a1, int a2, int a3) throws Throwable { + return (int) hookBridge(getMethodId(4, 3), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 4 + public static int stub_hook_4(int a0, int a1, int a2, int a3) throws Throwable { + return (int) hookBridge(getMethodId(4, 4), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 5 + public static int stub_hook_5(int a0, int a1, int a2, int a3) throws Throwable { + return (int) hookBridge(getMethodId(4, 5), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 6 + public static int stub_hook_6(int a0, int a1, int a2, int a3) throws Throwable { + return (int) hookBridge(getMethodId(4, 6), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 7 + public static int stub_hook_7(int a0, int a1, int a2, int a3) throws Throwable { + return (int) hookBridge(getMethodId(4, 7), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 8 + public static int stub_hook_8(int a0, int a1, int a2, int a3) throws Throwable { + return (int) hookBridge(getMethodId(4, 8), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 9 + public static int stub_hook_9(int a0, int a1, int a2, int a3) throws Throwable { + return (int) hookBridge(getMethodId(4, 9), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 10 + public static int stub_hook_10(int a0, int a1, int a2, int a3) throws Throwable { + return (int) hookBridge(getMethodId(4, 10), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 11 + public static int stub_hook_11(int a0, int a1, int a2, int a3) throws Throwable { + return (int) hookBridge(getMethodId(4, 11), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 12 + public static int stub_hook_12(int a0, int a1, int a2, int a3) throws Throwable { + return (int) hookBridge(getMethodId(4, 12), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 13 + public static int stub_hook_13(int a0, int a1, int a2, int a3) throws Throwable { + return (int) hookBridge(getMethodId(4, 13), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 14 + public static int stub_hook_14(int a0, int a1, int a2, int a3) throws Throwable { + return (int) hookBridge(getMethodId(4, 14), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 15 + public static int stub_hook_15(int a0, int a1, int a2, int a3) throws Throwable { + return (int) hookBridge(getMethodId(4, 15), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 16 + public static int stub_hook_16(int a0, int a1, int a2, int a3) throws Throwable { + return (int) hookBridge(getMethodId(4, 16), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 17 + public static int stub_hook_17(int a0, int a1, int a2, int a3) throws Throwable { + return (int) hookBridge(getMethodId(4, 17), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 18 + public static int stub_hook_18(int a0, int a1, int a2, int a3) throws Throwable { + return (int) hookBridge(getMethodId(4, 18), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 19 + public static int stub_hook_19(int a0, int a1, int a2, int a3) throws Throwable { + return (int) hookBridge(getMethodId(4, 19), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 20 + public static int stub_hook_20(int a0, int a1, int a2, int a3) throws Throwable { + return (int) hookBridge(getMethodId(4, 20), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 21 + public static int stub_hook_21(int a0, int a1, int a2, int a3) throws Throwable { + return (int) hookBridge(getMethodId(4, 21), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 22 + public static int stub_hook_22(int a0, int a1, int a2, int a3) throws Throwable { + return (int) hookBridge(getMethodId(4, 22), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 23 + public static int stub_hook_23(int a0, int a1, int a2, int a3) throws Throwable { + return (int) hookBridge(getMethodId(4, 23), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 24 + public static int stub_hook_24(int a0, int a1, int a2, int a3) throws Throwable { + return (int) hookBridge(getMethodId(4, 24), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 25 + public static int stub_hook_25(int a0, int a1, int a2, int a3) throws Throwable { + return (int) hookBridge(getMethodId(4, 25), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 26 + public static int stub_hook_26(int a0, int a1, int a2, int a3) throws Throwable { + return (int) hookBridge(getMethodId(4, 26), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 27 + public static int stub_hook_27(int a0, int a1, int a2, int a3) throws Throwable { + return (int) hookBridge(getMethodId(4, 27), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 28 + public static int stub_hook_28(int a0, int a1, int a2, int a3) throws Throwable { + return (int) hookBridge(getMethodId(4, 28), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 29 + public static int stub_hook_29(int a0, int a1, int a2, int a3) throws Throwable { + return (int) hookBridge(getMethodId(4, 29), null , a0, a1, a2, a3); + } + + + //stub of arg size 5, index 0 + public static int stub_hook_0(int a0, int a1, int a2, int a3, int a4) throws Throwable { + return (int) hookBridge(getMethodId(5, 0), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 1 + public static int stub_hook_1(int a0, int a1, int a2, int a3, int a4) throws Throwable { + return (int) hookBridge(getMethodId(5, 1), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 2 + public static int stub_hook_2(int a0, int a1, int a2, int a3, int a4) throws Throwable { + return (int) hookBridge(getMethodId(5, 2), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 3 + public static int stub_hook_3(int a0, int a1, int a2, int a3, int a4) throws Throwable { + return (int) hookBridge(getMethodId(5, 3), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 4 + public static int stub_hook_4(int a0, int a1, int a2, int a3, int a4) throws Throwable { + return (int) hookBridge(getMethodId(5, 4), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 5 + public static int stub_hook_5(int a0, int a1, int a2, int a3, int a4) throws Throwable { + return (int) hookBridge(getMethodId(5, 5), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 6 + public static int stub_hook_6(int a0, int a1, int a2, int a3, int a4) throws Throwable { + return (int) hookBridge(getMethodId(5, 6), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 7 + public static int stub_hook_7(int a0, int a1, int a2, int a3, int a4) throws Throwable { + return (int) hookBridge(getMethodId(5, 7), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 8 + public static int stub_hook_8(int a0, int a1, int a2, int a3, int a4) throws Throwable { + return (int) hookBridge(getMethodId(5, 8), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 9 + public static int stub_hook_9(int a0, int a1, int a2, int a3, int a4) throws Throwable { + return (int) hookBridge(getMethodId(5, 9), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 10 + public static int stub_hook_10(int a0, int a1, int a2, int a3, int a4) throws Throwable { + return (int) hookBridge(getMethodId(5, 10), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 11 + public static int stub_hook_11(int a0, int a1, int a2, int a3, int a4) throws Throwable { + return (int) hookBridge(getMethodId(5, 11), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 12 + public static int stub_hook_12(int a0, int a1, int a2, int a3, int a4) throws Throwable { + return (int) hookBridge(getMethodId(5, 12), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 13 + public static int stub_hook_13(int a0, int a1, int a2, int a3, int a4) throws Throwable { + return (int) hookBridge(getMethodId(5, 13), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 14 + public static int stub_hook_14(int a0, int a1, int a2, int a3, int a4) throws Throwable { + return (int) hookBridge(getMethodId(5, 14), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 15 + public static int stub_hook_15(int a0, int a1, int a2, int a3, int a4) throws Throwable { + return (int) hookBridge(getMethodId(5, 15), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 16 + public static int stub_hook_16(int a0, int a1, int a2, int a3, int a4) throws Throwable { + return (int) hookBridge(getMethodId(5, 16), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 17 + public static int stub_hook_17(int a0, int a1, int a2, int a3, int a4) throws Throwable { + return (int) hookBridge(getMethodId(5, 17), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 18 + public static int stub_hook_18(int a0, int a1, int a2, int a3, int a4) throws Throwable { + return (int) hookBridge(getMethodId(5, 18), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 19 + public static int stub_hook_19(int a0, int a1, int a2, int a3, int a4) throws Throwable { + return (int) hookBridge(getMethodId(5, 19), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 20 + public static int stub_hook_20(int a0, int a1, int a2, int a3, int a4) throws Throwable { + return (int) hookBridge(getMethodId(5, 20), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 21 + public static int stub_hook_21(int a0, int a1, int a2, int a3, int a4) throws Throwable { + return (int) hookBridge(getMethodId(5, 21), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 22 + public static int stub_hook_22(int a0, int a1, int a2, int a3, int a4) throws Throwable { + return (int) hookBridge(getMethodId(5, 22), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 23 + public static int stub_hook_23(int a0, int a1, int a2, int a3, int a4) throws Throwable { + return (int) hookBridge(getMethodId(5, 23), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 24 + public static int stub_hook_24(int a0, int a1, int a2, int a3, int a4) throws Throwable { + return (int) hookBridge(getMethodId(5, 24), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 25 + public static int stub_hook_25(int a0, int a1, int a2, int a3, int a4) throws Throwable { + return (int) hookBridge(getMethodId(5, 25), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 26 + public static int stub_hook_26(int a0, int a1, int a2, int a3, int a4) throws Throwable { + return (int) hookBridge(getMethodId(5, 26), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 27 + public static int stub_hook_27(int a0, int a1, int a2, int a3, int a4) throws Throwable { + return (int) hookBridge(getMethodId(5, 27), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 28 + public static int stub_hook_28(int a0, int a1, int a2, int a3, int a4) throws Throwable { + return (int) hookBridge(getMethodId(5, 28), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 29 + public static int stub_hook_29(int a0, int a1, int a2, int a3, int a4) throws Throwable { + return (int) hookBridge(getMethodId(5, 29), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 6, index 0 + public static int stub_hook_0(int a0, int a1, int a2, int a3, int a4, int a5) throws Throwable { + return (int) hookBridge(getMethodId(6, 0), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 1 + public static int stub_hook_1(int a0, int a1, int a2, int a3, int a4, int a5) throws Throwable { + return (int) hookBridge(getMethodId(6, 1), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 2 + public static int stub_hook_2(int a0, int a1, int a2, int a3, int a4, int a5) throws Throwable { + return (int) hookBridge(getMethodId(6, 2), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 3 + public static int stub_hook_3(int a0, int a1, int a2, int a3, int a4, int a5) throws Throwable { + return (int) hookBridge(getMethodId(6, 3), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 4 + public static int stub_hook_4(int a0, int a1, int a2, int a3, int a4, int a5) throws Throwable { + return (int) hookBridge(getMethodId(6, 4), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 5 + public static int stub_hook_5(int a0, int a1, int a2, int a3, int a4, int a5) throws Throwable { + return (int) hookBridge(getMethodId(6, 5), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 6 + public static int stub_hook_6(int a0, int a1, int a2, int a3, int a4, int a5) throws Throwable { + return (int) hookBridge(getMethodId(6, 6), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 7 + public static int stub_hook_7(int a0, int a1, int a2, int a3, int a4, int a5) throws Throwable { + return (int) hookBridge(getMethodId(6, 7), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 8 + public static int stub_hook_8(int a0, int a1, int a2, int a3, int a4, int a5) throws Throwable { + return (int) hookBridge(getMethodId(6, 8), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 9 + public static int stub_hook_9(int a0, int a1, int a2, int a3, int a4, int a5) throws Throwable { + return (int) hookBridge(getMethodId(6, 9), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 10 + public static int stub_hook_10(int a0, int a1, int a2, int a3, int a4, int a5) throws Throwable { + return (int) hookBridge(getMethodId(6, 10), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 11 + public static int stub_hook_11(int a0, int a1, int a2, int a3, int a4, int a5) throws Throwable { + return (int) hookBridge(getMethodId(6, 11), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 12 + public static int stub_hook_12(int a0, int a1, int a2, int a3, int a4, int a5) throws Throwable { + return (int) hookBridge(getMethodId(6, 12), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 13 + public static int stub_hook_13(int a0, int a1, int a2, int a3, int a4, int a5) throws Throwable { + return (int) hookBridge(getMethodId(6, 13), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 14 + public static int stub_hook_14(int a0, int a1, int a2, int a3, int a4, int a5) throws Throwable { + return (int) hookBridge(getMethodId(6, 14), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 15 + public static int stub_hook_15(int a0, int a1, int a2, int a3, int a4, int a5) throws Throwable { + return (int) hookBridge(getMethodId(6, 15), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 16 + public static int stub_hook_16(int a0, int a1, int a2, int a3, int a4, int a5) throws Throwable { + return (int) hookBridge(getMethodId(6, 16), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 17 + public static int stub_hook_17(int a0, int a1, int a2, int a3, int a4, int a5) throws Throwable { + return (int) hookBridge(getMethodId(6, 17), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 18 + public static int stub_hook_18(int a0, int a1, int a2, int a3, int a4, int a5) throws Throwable { + return (int) hookBridge(getMethodId(6, 18), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 19 + public static int stub_hook_19(int a0, int a1, int a2, int a3, int a4, int a5) throws Throwable { + return (int) hookBridge(getMethodId(6, 19), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 20 + public static int stub_hook_20(int a0, int a1, int a2, int a3, int a4, int a5) throws Throwable { + return (int) hookBridge(getMethodId(6, 20), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 21 + public static int stub_hook_21(int a0, int a1, int a2, int a3, int a4, int a5) throws Throwable { + return (int) hookBridge(getMethodId(6, 21), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 22 + public static int stub_hook_22(int a0, int a1, int a2, int a3, int a4, int a5) throws Throwable { + return (int) hookBridge(getMethodId(6, 22), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 23 + public static int stub_hook_23(int a0, int a1, int a2, int a3, int a4, int a5) throws Throwable { + return (int) hookBridge(getMethodId(6, 23), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 24 + public static int stub_hook_24(int a0, int a1, int a2, int a3, int a4, int a5) throws Throwable { + return (int) hookBridge(getMethodId(6, 24), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 25 + public static int stub_hook_25(int a0, int a1, int a2, int a3, int a4, int a5) throws Throwable { + return (int) hookBridge(getMethodId(6, 25), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 26 + public static int stub_hook_26(int a0, int a1, int a2, int a3, int a4, int a5) throws Throwable { + return (int) hookBridge(getMethodId(6, 26), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 27 + public static int stub_hook_27(int a0, int a1, int a2, int a3, int a4, int a5) throws Throwable { + return (int) hookBridge(getMethodId(6, 27), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 28 + public static int stub_hook_28(int a0, int a1, int a2, int a3, int a4, int a5) throws Throwable { + return (int) hookBridge(getMethodId(6, 28), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 29 + public static int stub_hook_29(int a0, int a1, int a2, int a3, int a4, int a5) throws Throwable { + return (int) hookBridge(getMethodId(6, 29), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 7, index 0 + public static int stub_hook_0(int a0, int a1, int a2, int a3, int a4, int a5, int a6) throws Throwable { + return (int) hookBridge(getMethodId(7, 0), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 1 + public static int stub_hook_1(int a0, int a1, int a2, int a3, int a4, int a5, int a6) throws Throwable { + return (int) hookBridge(getMethodId(7, 1), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 2 + public static int stub_hook_2(int a0, int a1, int a2, int a3, int a4, int a5, int a6) throws Throwable { + return (int) hookBridge(getMethodId(7, 2), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 3 + public static int stub_hook_3(int a0, int a1, int a2, int a3, int a4, int a5, int a6) throws Throwable { + return (int) hookBridge(getMethodId(7, 3), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 4 + public static int stub_hook_4(int a0, int a1, int a2, int a3, int a4, int a5, int a6) throws Throwable { + return (int) hookBridge(getMethodId(7, 4), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 5 + public static int stub_hook_5(int a0, int a1, int a2, int a3, int a4, int a5, int a6) throws Throwable { + return (int) hookBridge(getMethodId(7, 5), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 6 + public static int stub_hook_6(int a0, int a1, int a2, int a3, int a4, int a5, int a6) throws Throwable { + return (int) hookBridge(getMethodId(7, 6), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 7 + public static int stub_hook_7(int a0, int a1, int a2, int a3, int a4, int a5, int a6) throws Throwable { + return (int) hookBridge(getMethodId(7, 7), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 8 + public static int stub_hook_8(int a0, int a1, int a2, int a3, int a4, int a5, int a6) throws Throwable { + return (int) hookBridge(getMethodId(7, 8), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 9 + public static int stub_hook_9(int a0, int a1, int a2, int a3, int a4, int a5, int a6) throws Throwable { + return (int) hookBridge(getMethodId(7, 9), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 10 + public static int stub_hook_10(int a0, int a1, int a2, int a3, int a4, int a5, int a6) throws Throwable { + return (int) hookBridge(getMethodId(7, 10), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 11 + public static int stub_hook_11(int a0, int a1, int a2, int a3, int a4, int a5, int a6) throws Throwable { + return (int) hookBridge(getMethodId(7, 11), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 12 + public static int stub_hook_12(int a0, int a1, int a2, int a3, int a4, int a5, int a6) throws Throwable { + return (int) hookBridge(getMethodId(7, 12), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 13 + public static int stub_hook_13(int a0, int a1, int a2, int a3, int a4, int a5, int a6) throws Throwable { + return (int) hookBridge(getMethodId(7, 13), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 14 + public static int stub_hook_14(int a0, int a1, int a2, int a3, int a4, int a5, int a6) throws Throwable { + return (int) hookBridge(getMethodId(7, 14), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 15 + public static int stub_hook_15(int a0, int a1, int a2, int a3, int a4, int a5, int a6) throws Throwable { + return (int) hookBridge(getMethodId(7, 15), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 16 + public static int stub_hook_16(int a0, int a1, int a2, int a3, int a4, int a5, int a6) throws Throwable { + return (int) hookBridge(getMethodId(7, 16), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 17 + public static int stub_hook_17(int a0, int a1, int a2, int a3, int a4, int a5, int a6) throws Throwable { + return (int) hookBridge(getMethodId(7, 17), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 18 + public static int stub_hook_18(int a0, int a1, int a2, int a3, int a4, int a5, int a6) throws Throwable { + return (int) hookBridge(getMethodId(7, 18), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 19 + public static int stub_hook_19(int a0, int a1, int a2, int a3, int a4, int a5, int a6) throws Throwable { + return (int) hookBridge(getMethodId(7, 19), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 8, index 0 + public static int stub_hook_0(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7) throws Throwable { + return (int) hookBridge(getMethodId(8, 0), null , a0, a1, a2, a3, a4, a5, a6, a7); + } + + + //stub of arg size 8, index 1 + public static int stub_hook_1(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7) throws Throwable { + return (int) hookBridge(getMethodId(8, 1), null , a0, a1, a2, a3, a4, a5, a6, a7); + } + + + //stub of arg size 8, index 2 + public static int stub_hook_2(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7) throws Throwable { + return (int) hookBridge(getMethodId(8, 2), null , a0, a1, a2, a3, a4, a5, a6, a7); + } + + + //stub of arg size 8, index 3 + public static int stub_hook_3(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7) throws Throwable { + return (int) hookBridge(getMethodId(8, 3), null , a0, a1, a2, a3, a4, a5, a6, a7); + } + + + //stub of arg size 8, index 4 + public static int stub_hook_4(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7) throws Throwable { + return (int) hookBridge(getMethodId(8, 4), null , a0, a1, a2, a3, a4, a5, a6, a7); + } + + + //stub of arg size 8, index 5 + public static int stub_hook_5(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7) throws Throwable { + return (int) hookBridge(getMethodId(8, 5), null , a0, a1, a2, a3, a4, a5, a6, a7); + } + + + //stub of arg size 8, index 6 + public static int stub_hook_6(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7) throws Throwable { + return (int) hookBridge(getMethodId(8, 6), null , a0, a1, a2, a3, a4, a5, a6, a7); + } + + + //stub of arg size 8, index 7 + public static int stub_hook_7(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7) throws Throwable { + return (int) hookBridge(getMethodId(8, 7), null , a0, a1, a2, a3, a4, a5, a6, a7); + } + + + //stub of arg size 8, index 8 + public static int stub_hook_8(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7) throws Throwable { + return (int) hookBridge(getMethodId(8, 8), null , a0, a1, a2, a3, a4, a5, a6, a7); + } + + + //stub of arg size 8, index 9 + public static int stub_hook_9(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7) throws Throwable { + return (int) hookBridge(getMethodId(8, 9), null , a0, a1, a2, a3, a4, a5, a6, a7); + } + + + //stub of arg size 9, index 0 + public static int stub_hook_0(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) throws Throwable { + return (int) hookBridge(getMethodId(9, 0), null , a0, a1, a2, a3, a4, a5, a6, a7, a8); + } + + + //stub of arg size 9, index 1 + public static int stub_hook_1(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) throws Throwable { + return (int) hookBridge(getMethodId(9, 1), null , a0, a1, a2, a3, a4, a5, a6, a7, a8); + } + + + //stub of arg size 9, index 2 + public static int stub_hook_2(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) throws Throwable { + return (int) hookBridge(getMethodId(9, 2), null , a0, a1, a2, a3, a4, a5, a6, a7, a8); + } + + + //stub of arg size 9, index 3 + public static int stub_hook_3(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) throws Throwable { + return (int) hookBridge(getMethodId(9, 3), null , a0, a1, a2, a3, a4, a5, a6, a7, a8); + } + + + //stub of arg size 9, index 4 + public static int stub_hook_4(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) throws Throwable { + return (int) hookBridge(getMethodId(9, 4), null , a0, a1, a2, a3, a4, a5, a6, a7, a8); + } + + + //stub of arg size 9, index 5 + public static int stub_hook_5(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) throws Throwable { + return (int) hookBridge(getMethodId(9, 5), null , a0, a1, a2, a3, a4, a5, a6, a7, a8); + } + + + //stub of arg size 9, index 6 + public static int stub_hook_6(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) throws Throwable { + return (int) hookBridge(getMethodId(9, 6), null , a0, a1, a2, a3, a4, a5, a6, a7, a8); + } + + + //stub of arg size 9, index 7 + public static int stub_hook_7(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) throws Throwable { + return (int) hookBridge(getMethodId(9, 7), null , a0, a1, a2, a3, a4, a5, a6, a7, a8); + } + + + //stub of arg size 9, index 8 + public static int stub_hook_8(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) throws Throwable { + return (int) hookBridge(getMethodId(9, 8), null , a0, a1, a2, a3, a4, a5, a6, a7, a8); + } + + + //stub of arg size 9, index 9 + public static int stub_hook_9(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) throws Throwable { + return (int) hookBridge(getMethodId(9, 9), null , a0, a1, a2, a3, a4, a5, a6, a7, a8); + } + + + //stub of arg size 10, index 0 + public static int stub_hook_0(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9) throws Throwable { + return (int) hookBridge(getMethodId(10, 0), null , a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); + } + + + //stub of arg size 10, index 1 + public static int stub_hook_1(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9) throws Throwable { + return (int) hookBridge(getMethodId(10, 1), null , a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); + } + + + //stub of arg size 10, index 2 + public static int stub_hook_2(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9) throws Throwable { + return (int) hookBridge(getMethodId(10, 2), null , a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); + } + + + //stub of arg size 10, index 3 + public static int stub_hook_3(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9) throws Throwable { + return (int) hookBridge(getMethodId(10, 3), null , a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); + } + + + //stub of arg size 10, index 4 + public static int stub_hook_4(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9) throws Throwable { + return (int) hookBridge(getMethodId(10, 4), null , a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); + } + + + //stub of arg size 11, index 0 + public static int stub_hook_0(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10) throws Throwable { + return (int) hookBridge(getMethodId(11, 0), null , a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); + } + + + //stub of arg size 11, index 1 + public static int stub_hook_1(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10) throws Throwable { + return (int) hookBridge(getMethodId(11, 1), null , a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); + } + + + //stub of arg size 11, index 2 + public static int stub_hook_2(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10) throws Throwable { + return (int) hookBridge(getMethodId(11, 2), null , a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); + } + + + //stub of arg size 11, index 3 + public static int stub_hook_3(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10) throws Throwable { + return (int) hookBridge(getMethodId(11, 3), null , a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); + } + + + //stub of arg size 11, index 4 + public static int stub_hook_4(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10) throws Throwable { + return (int) hookBridge(getMethodId(11, 4), null , a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); + } + + + //stub of arg size 12, index 0 + public static int stub_hook_0(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11) throws Throwable { + return (int) hookBridge(getMethodId(12, 0), null , a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); + } + + + //stub of arg size 12, index 1 + public static int stub_hook_1(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11) throws Throwable { + return (int) hookBridge(getMethodId(12, 1), null , a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); + } + + + //stub of arg size 12, index 2 + public static int stub_hook_2(int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11) throws Throwable { + return (int) hookBridge(getMethodId(12, 2), null , a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); + } + +} diff --git a/sandhook/src/main/java/com/swift/sandhook/xposedcompat/hookstub/MethodHookerStubs64.java b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/hookstub/MethodHookerStubs64.java new file mode 100644 index 000000000..6fa645cd3 --- /dev/null +++ b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/hookstub/MethodHookerStubs64.java @@ -0,0 +1,1415 @@ +package com.swift.sandhook.xposedcompat.hookstub; + +import static com.swift.sandhook.xposedcompat.hookstub.HookStubManager.hookBridge; +import static com.swift.sandhook.xposedcompat.hookstub.HookStubManager.getMethodId; +import static com.swift.sandhook.xposedcompat.hookstub.HookStubManager.originMethods; +import static com.swift.sandhook.xposedcompat.utils.DexLog.printCallOriginError; + +/** +* this file is auto gen by genhookstubs.py +* it is for sandhook internal hooker & backup methods +**/ +public class MethodHookerStubs64 { + + public static boolean hasStubBackup = false; + public static int[] stubSizes = {10, 20, 30, 30, 30, 30, 30, 20, 10, 10, 5, 5, 3}; + + + //stub of arg size 0, index 0 + public static long stub_hook_0() throws Throwable { + return hookBridge(getMethodId(0, 0), null ); + } + + + //stub of arg size 0, index 1 + public static long stub_hook_1() throws Throwable { + return hookBridge(getMethodId(0, 1), null ); + } + + + //stub of arg size 0, index 2 + public static long stub_hook_2() throws Throwable { + return hookBridge(getMethodId(0, 2), null ); + } + + + //stub of arg size 0, index 3 + public static long stub_hook_3() throws Throwable { + return hookBridge(getMethodId(0, 3), null ); + } + + + //stub of arg size 0, index 4 + public static long stub_hook_4() throws Throwable { + return hookBridge(getMethodId(0, 4), null ); + } + + + //stub of arg size 0, index 5 + public static long stub_hook_5() throws Throwable { + return hookBridge(getMethodId(0, 5), null ); + } + + + //stub of arg size 0, index 6 + public static long stub_hook_6() throws Throwable { + return hookBridge(getMethodId(0, 6), null ); + } + + + //stub of arg size 0, index 7 + public static long stub_hook_7() throws Throwable { + return hookBridge(getMethodId(0, 7), null ); + } + + + //stub of arg size 0, index 8 + public static long stub_hook_8() throws Throwable { + return hookBridge(getMethodId(0, 8), null ); + } + + + //stub of arg size 0, index 9 + public static long stub_hook_9() throws Throwable { + return hookBridge(getMethodId(0, 9), null ); + } + + + //stub of arg size 1, index 0 + public static long stub_hook_0(long a0) throws Throwable { + return hookBridge(getMethodId(1, 0), null , a0); + } + + + //stub of arg size 1, index 1 + public static long stub_hook_1(long a0) throws Throwable { + return hookBridge(getMethodId(1, 1), null , a0); + } + + + //stub of arg size 1, index 2 + public static long stub_hook_2(long a0) throws Throwable { + return hookBridge(getMethodId(1, 2), null , a0); + } + + + //stub of arg size 1, index 3 + public static long stub_hook_3(long a0) throws Throwable { + return hookBridge(getMethodId(1, 3), null , a0); + } + + + //stub of arg size 1, index 4 + public static long stub_hook_4(long a0) throws Throwable { + return hookBridge(getMethodId(1, 4), null , a0); + } + + + //stub of arg size 1, index 5 + public static long stub_hook_5(long a0) throws Throwable { + return hookBridge(getMethodId(1, 5), null , a0); + } + + + //stub of arg size 1, index 6 + public static long stub_hook_6(long a0) throws Throwable { + return hookBridge(getMethodId(1, 6), null , a0); + } + + + //stub of arg size 1, index 7 + public static long stub_hook_7(long a0) throws Throwable { + return hookBridge(getMethodId(1, 7), null , a0); + } + + + //stub of arg size 1, index 8 + public static long stub_hook_8(long a0) throws Throwable { + return hookBridge(getMethodId(1, 8), null , a0); + } + + + //stub of arg size 1, index 9 + public static long stub_hook_9(long a0) throws Throwable { + return hookBridge(getMethodId(1, 9), null , a0); + } + + + //stub of arg size 1, index 10 + public static long stub_hook_10(long a0) throws Throwable { + return hookBridge(getMethodId(1, 10), null , a0); + } + + + //stub of arg size 1, index 11 + public static long stub_hook_11(long a0) throws Throwable { + return hookBridge(getMethodId(1, 11), null , a0); + } + + + //stub of arg size 1, index 12 + public static long stub_hook_12(long a0) throws Throwable { + return hookBridge(getMethodId(1, 12), null , a0); + } + + + //stub of arg size 1, index 13 + public static long stub_hook_13(long a0) throws Throwable { + return hookBridge(getMethodId(1, 13), null , a0); + } + + + //stub of arg size 1, index 14 + public static long stub_hook_14(long a0) throws Throwable { + return hookBridge(getMethodId(1, 14), null , a0); + } + + + //stub of arg size 1, index 15 + public static long stub_hook_15(long a0) throws Throwable { + return hookBridge(getMethodId(1, 15), null , a0); + } + + + //stub of arg size 1, index 16 + public static long stub_hook_16(long a0) throws Throwable { + return hookBridge(getMethodId(1, 16), null , a0); + } + + + //stub of arg size 1, index 17 + public static long stub_hook_17(long a0) throws Throwable { + return hookBridge(getMethodId(1, 17), null , a0); + } + + + //stub of arg size 1, index 18 + public static long stub_hook_18(long a0) throws Throwable { + return hookBridge(getMethodId(1, 18), null , a0); + } + + + //stub of arg size 1, index 19 + public static long stub_hook_19(long a0) throws Throwable { + return hookBridge(getMethodId(1, 19), null , a0); + } + + + //stub of arg size 2, index 0 + public static long stub_hook_0(long a0, long a1) throws Throwable { + return hookBridge(getMethodId(2, 0), null , a0, a1); + } + + + //stub of arg size 2, index 1 + public static long stub_hook_1(long a0, long a1) throws Throwable { + return hookBridge(getMethodId(2, 1), null , a0, a1); + } + + + //stub of arg size 2, index 2 + public static long stub_hook_2(long a0, long a1) throws Throwable { + return hookBridge(getMethodId(2, 2), null , a0, a1); + } + + + //stub of arg size 2, index 3 + public static long stub_hook_3(long a0, long a1) throws Throwable { + return hookBridge(getMethodId(2, 3), null , a0, a1); + } + + + //stub of arg size 2, index 4 + public static long stub_hook_4(long a0, long a1) throws Throwable { + return hookBridge(getMethodId(2, 4), null , a0, a1); + } + + + //stub of arg size 2, index 5 + public static long stub_hook_5(long a0, long a1) throws Throwable { + return hookBridge(getMethodId(2, 5), null , a0, a1); + } + + + //stub of arg size 2, index 6 + public static long stub_hook_6(long a0, long a1) throws Throwable { + return hookBridge(getMethodId(2, 6), null , a0, a1); + } + + + //stub of arg size 2, index 7 + public static long stub_hook_7(long a0, long a1) throws Throwable { + return hookBridge(getMethodId(2, 7), null , a0, a1); + } + + + //stub of arg size 2, index 8 + public static long stub_hook_8(long a0, long a1) throws Throwable { + return hookBridge(getMethodId(2, 8), null , a0, a1); + } + + + //stub of arg size 2, index 9 + public static long stub_hook_9(long a0, long a1) throws Throwable { + return hookBridge(getMethodId(2, 9), null , a0, a1); + } + + + //stub of arg size 2, index 10 + public static long stub_hook_10(long a0, long a1) throws Throwable { + return hookBridge(getMethodId(2, 10), null , a0, a1); + } + + + //stub of arg size 2, index 11 + public static long stub_hook_11(long a0, long a1) throws Throwable { + return hookBridge(getMethodId(2, 11), null , a0, a1); + } + + + //stub of arg size 2, index 12 + public static long stub_hook_12(long a0, long a1) throws Throwable { + return hookBridge(getMethodId(2, 12), null , a0, a1); + } + + + //stub of arg size 2, index 13 + public static long stub_hook_13(long a0, long a1) throws Throwable { + return hookBridge(getMethodId(2, 13), null , a0, a1); + } + + + //stub of arg size 2, index 14 + public static long stub_hook_14(long a0, long a1) throws Throwable { + return hookBridge(getMethodId(2, 14), null , a0, a1); + } + + + //stub of arg size 2, index 15 + public static long stub_hook_15(long a0, long a1) throws Throwable { + return hookBridge(getMethodId(2, 15), null , a0, a1); + } + + + //stub of arg size 2, index 16 + public static long stub_hook_16(long a0, long a1) throws Throwable { + return hookBridge(getMethodId(2, 16), null , a0, a1); + } + + + //stub of arg size 2, index 17 + public static long stub_hook_17(long a0, long a1) throws Throwable { + return hookBridge(getMethodId(2, 17), null , a0, a1); + } + + + //stub of arg size 2, index 18 + public static long stub_hook_18(long a0, long a1) throws Throwable { + return hookBridge(getMethodId(2, 18), null , a0, a1); + } + + + //stub of arg size 2, index 19 + public static long stub_hook_19(long a0, long a1) throws Throwable { + return hookBridge(getMethodId(2, 19), null , a0, a1); + } + + + //stub of arg size 2, index 20 + public static long stub_hook_20(long a0, long a1) throws Throwable { + return hookBridge(getMethodId(2, 20), null , a0, a1); + } + + + //stub of arg size 2, index 21 + public static long stub_hook_21(long a0, long a1) throws Throwable { + return hookBridge(getMethodId(2, 21), null , a0, a1); + } + + + //stub of arg size 2, index 22 + public static long stub_hook_22(long a0, long a1) throws Throwable { + return hookBridge(getMethodId(2, 22), null , a0, a1); + } + + + //stub of arg size 2, index 23 + public static long stub_hook_23(long a0, long a1) throws Throwable { + return hookBridge(getMethodId(2, 23), null , a0, a1); + } + + + //stub of arg size 2, index 24 + public static long stub_hook_24(long a0, long a1) throws Throwable { + return hookBridge(getMethodId(2, 24), null , a0, a1); + } + + + //stub of arg size 2, index 25 + public static long stub_hook_25(long a0, long a1) throws Throwable { + return hookBridge(getMethodId(2, 25), null , a0, a1); + } + + + //stub of arg size 2, index 26 + public static long stub_hook_26(long a0, long a1) throws Throwable { + return hookBridge(getMethodId(2, 26), null , a0, a1); + } + + + //stub of arg size 2, index 27 + public static long stub_hook_27(long a0, long a1) throws Throwable { + return hookBridge(getMethodId(2, 27), null , a0, a1); + } + + + //stub of arg size 2, index 28 + public static long stub_hook_28(long a0, long a1) throws Throwable { + return hookBridge(getMethodId(2, 28), null , a0, a1); + } + + + //stub of arg size 2, index 29 + public static long stub_hook_29(long a0, long a1) throws Throwable { + return hookBridge(getMethodId(2, 29), null , a0, a1); + } + + + //stub of arg size 3, index 0 + public static long stub_hook_0(long a0, long a1, long a2) throws Throwable { + return hookBridge(getMethodId(3, 0), null , a0, a1, a2); + } + + + //stub of arg size 3, index 1 + public static long stub_hook_1(long a0, long a1, long a2) throws Throwable { + return hookBridge(getMethodId(3, 1), null , a0, a1, a2); + } + + + //stub of arg size 3, index 2 + public static long stub_hook_2(long a0, long a1, long a2) throws Throwable { + return hookBridge(getMethodId(3, 2), null , a0, a1, a2); + } + + + //stub of arg size 3, index 3 + public static long stub_hook_3(long a0, long a1, long a2) throws Throwable { + return hookBridge(getMethodId(3, 3), null , a0, a1, a2); + } + + + //stub of arg size 3, index 4 + public static long stub_hook_4(long a0, long a1, long a2) throws Throwable { + return hookBridge(getMethodId(3, 4), null , a0, a1, a2); + } + + + //stub of arg size 3, index 5 + public static long stub_hook_5(long a0, long a1, long a2) throws Throwable { + return hookBridge(getMethodId(3, 5), null , a0, a1, a2); + } + + + //stub of arg size 3, index 6 + public static long stub_hook_6(long a0, long a1, long a2) throws Throwable { + return hookBridge(getMethodId(3, 6), null , a0, a1, a2); + } + + + //stub of arg size 3, index 7 + public static long stub_hook_7(long a0, long a1, long a2) throws Throwable { + return hookBridge(getMethodId(3, 7), null , a0, a1, a2); + } + + + //stub of arg size 3, index 8 + public static long stub_hook_8(long a0, long a1, long a2) throws Throwable { + return hookBridge(getMethodId(3, 8), null , a0, a1, a2); + } + + + //stub of arg size 3, index 9 + public static long stub_hook_9(long a0, long a1, long a2) throws Throwable { + return hookBridge(getMethodId(3, 9), null , a0, a1, a2); + } + + + //stub of arg size 3, index 10 + public static long stub_hook_10(long a0, long a1, long a2) throws Throwable { + return hookBridge(getMethodId(3, 10), null , a0, a1, a2); + } + + + //stub of arg size 3, index 11 + public static long stub_hook_11(long a0, long a1, long a2) throws Throwable { + return hookBridge(getMethodId(3, 11), null , a0, a1, a2); + } + + + //stub of arg size 3, index 12 + public static long stub_hook_12(long a0, long a1, long a2) throws Throwable { + return hookBridge(getMethodId(3, 12), null , a0, a1, a2); + } + + + //stub of arg size 3, index 13 + public static long stub_hook_13(long a0, long a1, long a2) throws Throwable { + return hookBridge(getMethodId(3, 13), null , a0, a1, a2); + } + + + //stub of arg size 3, index 14 + public static long stub_hook_14(long a0, long a1, long a2) throws Throwable { + return hookBridge(getMethodId(3, 14), null , a0, a1, a2); + } + + + //stub of arg size 3, index 15 + public static long stub_hook_15(long a0, long a1, long a2) throws Throwable { + return hookBridge(getMethodId(3, 15), null , a0, a1, a2); + } + + + //stub of arg size 3, index 16 + public static long stub_hook_16(long a0, long a1, long a2) throws Throwable { + return hookBridge(getMethodId(3, 16), null , a0, a1, a2); + } + + + //stub of arg size 3, index 17 + public static long stub_hook_17(long a0, long a1, long a2) throws Throwable { + return hookBridge(getMethodId(3, 17), null , a0, a1, a2); + } + + + //stub of arg size 3, index 18 + public static long stub_hook_18(long a0, long a1, long a2) throws Throwable { + return hookBridge(getMethodId(3, 18), null , a0, a1, a2); + } + + + //stub of arg size 3, index 19 + public static long stub_hook_19(long a0, long a1, long a2) throws Throwable { + return hookBridge(getMethodId(3, 19), null , a0, a1, a2); + } + + + //stub of arg size 3, index 20 + public static long stub_hook_20(long a0, long a1, long a2) throws Throwable { + return hookBridge(getMethodId(3, 20), null , a0, a1, a2); + } + + + //stub of arg size 3, index 21 + public static long stub_hook_21(long a0, long a1, long a2) throws Throwable { + return hookBridge(getMethodId(3, 21), null , a0, a1, a2); + } + + + //stub of arg size 3, index 22 + public static long stub_hook_22(long a0, long a1, long a2) throws Throwable { + return hookBridge(getMethodId(3, 22), null , a0, a1, a2); + } + + + //stub of arg size 3, index 23 + public static long stub_hook_23(long a0, long a1, long a2) throws Throwable { + return hookBridge(getMethodId(3, 23), null , a0, a1, a2); + } + + + //stub of arg size 3, index 24 + public static long stub_hook_24(long a0, long a1, long a2) throws Throwable { + return hookBridge(getMethodId(3, 24), null , a0, a1, a2); + } + + + //stub of arg size 3, index 25 + public static long stub_hook_25(long a0, long a1, long a2) throws Throwable { + return hookBridge(getMethodId(3, 25), null , a0, a1, a2); + } + + + //stub of arg size 3, index 26 + public static long stub_hook_26(long a0, long a1, long a2) throws Throwable { + return hookBridge(getMethodId(3, 26), null , a0, a1, a2); + } + + + //stub of arg size 3, index 27 + public static long stub_hook_27(long a0, long a1, long a2) throws Throwable { + return hookBridge(getMethodId(3, 27), null , a0, a1, a2); + } + + + //stub of arg size 3, index 28 + public static long stub_hook_28(long a0, long a1, long a2) throws Throwable { + return hookBridge(getMethodId(3, 28), null , a0, a1, a2); + } + + + //stub of arg size 3, index 29 + public static long stub_hook_29(long a0, long a1, long a2) throws Throwable { + return hookBridge(getMethodId(3, 29), null , a0, a1, a2); + } + + + //stub of arg size 4, index 0 + public static long stub_hook_0(long a0, long a1, long a2, long a3) throws Throwable { + return hookBridge(getMethodId(4, 0), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 1 + public static long stub_hook_1(long a0, long a1, long a2, long a3) throws Throwable { + return hookBridge(getMethodId(4, 1), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 2 + public static long stub_hook_2(long a0, long a1, long a2, long a3) throws Throwable { + return hookBridge(getMethodId(4, 2), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 3 + public static long stub_hook_3(long a0, long a1, long a2, long a3) throws Throwable { + return hookBridge(getMethodId(4, 3), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 4 + public static long stub_hook_4(long a0, long a1, long a2, long a3) throws Throwable { + return hookBridge(getMethodId(4, 4), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 5 + public static long stub_hook_5(long a0, long a1, long a2, long a3) throws Throwable { + return hookBridge(getMethodId(4, 5), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 6 + public static long stub_hook_6(long a0, long a1, long a2, long a3) throws Throwable { + return hookBridge(getMethodId(4, 6), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 7 + public static long stub_hook_7(long a0, long a1, long a2, long a3) throws Throwable { + return hookBridge(getMethodId(4, 7), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 8 + public static long stub_hook_8(long a0, long a1, long a2, long a3) throws Throwable { + return hookBridge(getMethodId(4, 8), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 9 + public static long stub_hook_9(long a0, long a1, long a2, long a3) throws Throwable { + return hookBridge(getMethodId(4, 9), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 10 + public static long stub_hook_10(long a0, long a1, long a2, long a3) throws Throwable { + return hookBridge(getMethodId(4, 10), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 11 + public static long stub_hook_11(long a0, long a1, long a2, long a3) throws Throwable { + return hookBridge(getMethodId(4, 11), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 12 + public static long stub_hook_12(long a0, long a1, long a2, long a3) throws Throwable { + return hookBridge(getMethodId(4, 12), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 13 + public static long stub_hook_13(long a0, long a1, long a2, long a3) throws Throwable { + return hookBridge(getMethodId(4, 13), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 14 + public static long stub_hook_14(long a0, long a1, long a2, long a3) throws Throwable { + return hookBridge(getMethodId(4, 14), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 15 + public static long stub_hook_15(long a0, long a1, long a2, long a3) throws Throwable { + return hookBridge(getMethodId(4, 15), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 16 + public static long stub_hook_16(long a0, long a1, long a2, long a3) throws Throwable { + return hookBridge(getMethodId(4, 16), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 17 + public static long stub_hook_17(long a0, long a1, long a2, long a3) throws Throwable { + return hookBridge(getMethodId(4, 17), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 18 + public static long stub_hook_18(long a0, long a1, long a2, long a3) throws Throwable { + return hookBridge(getMethodId(4, 18), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 19 + public static long stub_hook_19(long a0, long a1, long a2, long a3) throws Throwable { + return hookBridge(getMethodId(4, 19), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 20 + public static long stub_hook_20(long a0, long a1, long a2, long a3) throws Throwable { + return hookBridge(getMethodId(4, 20), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 21 + public static long stub_hook_21(long a0, long a1, long a2, long a3) throws Throwable { + return hookBridge(getMethodId(4, 21), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 22 + public static long stub_hook_22(long a0, long a1, long a2, long a3) throws Throwable { + return hookBridge(getMethodId(4, 22), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 23 + public static long stub_hook_23(long a0, long a1, long a2, long a3) throws Throwable { + return hookBridge(getMethodId(4, 23), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 24 + public static long stub_hook_24(long a0, long a1, long a2, long a3) throws Throwable { + return hookBridge(getMethodId(4, 24), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 25 + public static long stub_hook_25(long a0, long a1, long a2, long a3) throws Throwable { + return hookBridge(getMethodId(4, 25), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 26 + public static long stub_hook_26(long a0, long a1, long a2, long a3) throws Throwable { + return hookBridge(getMethodId(4, 26), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 27 + public static long stub_hook_27(long a0, long a1, long a2, long a3) throws Throwable { + return hookBridge(getMethodId(4, 27), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 28 + public static long stub_hook_28(long a0, long a1, long a2, long a3) throws Throwable { + return hookBridge(getMethodId(4, 28), null , a0, a1, a2, a3); + } + + + //stub of arg size 4, index 29 + public static long stub_hook_29(long a0, long a1, long a2, long a3) throws Throwable { + return hookBridge(getMethodId(4, 29), null , a0, a1, a2, a3); + } + + + //stub of arg size 5, index 0 + public static long stub_hook_0(long a0, long a1, long a2, long a3, long a4) throws Throwable { + return hookBridge(getMethodId(5, 0), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 1 + public static long stub_hook_1(long a0, long a1, long a2, long a3, long a4) throws Throwable { + return hookBridge(getMethodId(5, 1), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 2 + public static long stub_hook_2(long a0, long a1, long a2, long a3, long a4) throws Throwable { + return hookBridge(getMethodId(5, 2), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 3 + public static long stub_hook_3(long a0, long a1, long a2, long a3, long a4) throws Throwable { + return hookBridge(getMethodId(5, 3), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 4 + public static long stub_hook_4(long a0, long a1, long a2, long a3, long a4) throws Throwable { + return hookBridge(getMethodId(5, 4), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 5 + public static long stub_hook_5(long a0, long a1, long a2, long a3, long a4) throws Throwable { + return hookBridge(getMethodId(5, 5), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 6 + public static long stub_hook_6(long a0, long a1, long a2, long a3, long a4) throws Throwable { + return hookBridge(getMethodId(5, 6), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 7 + public static long stub_hook_7(long a0, long a1, long a2, long a3, long a4) throws Throwable { + return hookBridge(getMethodId(5, 7), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 8 + public static long stub_hook_8(long a0, long a1, long a2, long a3, long a4) throws Throwable { + return hookBridge(getMethodId(5, 8), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 9 + public static long stub_hook_9(long a0, long a1, long a2, long a3, long a4) throws Throwable { + return hookBridge(getMethodId(5, 9), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 10 + public static long stub_hook_10(long a0, long a1, long a2, long a3, long a4) throws Throwable { + return hookBridge(getMethodId(5, 10), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 11 + public static long stub_hook_11(long a0, long a1, long a2, long a3, long a4) throws Throwable { + return hookBridge(getMethodId(5, 11), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 12 + public static long stub_hook_12(long a0, long a1, long a2, long a3, long a4) throws Throwable { + return hookBridge(getMethodId(5, 12), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 13 + public static long stub_hook_13(long a0, long a1, long a2, long a3, long a4) throws Throwable { + return hookBridge(getMethodId(5, 13), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 14 + public static long stub_hook_14(long a0, long a1, long a2, long a3, long a4) throws Throwable { + return hookBridge(getMethodId(5, 14), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 15 + public static long stub_hook_15(long a0, long a1, long a2, long a3, long a4) throws Throwable { + return hookBridge(getMethodId(5, 15), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 16 + public static long stub_hook_16(long a0, long a1, long a2, long a3, long a4) throws Throwable { + return hookBridge(getMethodId(5, 16), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 17 + public static long stub_hook_17(long a0, long a1, long a2, long a3, long a4) throws Throwable { + return hookBridge(getMethodId(5, 17), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 18 + public static long stub_hook_18(long a0, long a1, long a2, long a3, long a4) throws Throwable { + return hookBridge(getMethodId(5, 18), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 19 + public static long stub_hook_19(long a0, long a1, long a2, long a3, long a4) throws Throwable { + return hookBridge(getMethodId(5, 19), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 20 + public static long stub_hook_20(long a0, long a1, long a2, long a3, long a4) throws Throwable { + return hookBridge(getMethodId(5, 20), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 21 + public static long stub_hook_21(long a0, long a1, long a2, long a3, long a4) throws Throwable { + return hookBridge(getMethodId(5, 21), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 22 + public static long stub_hook_22(long a0, long a1, long a2, long a3, long a4) throws Throwable { + return hookBridge(getMethodId(5, 22), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 23 + public static long stub_hook_23(long a0, long a1, long a2, long a3, long a4) throws Throwable { + return hookBridge(getMethodId(5, 23), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 24 + public static long stub_hook_24(long a0, long a1, long a2, long a3, long a4) throws Throwable { + return hookBridge(getMethodId(5, 24), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 25 + public static long stub_hook_25(long a0, long a1, long a2, long a3, long a4) throws Throwable { + return hookBridge(getMethodId(5, 25), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 26 + public static long stub_hook_26(long a0, long a1, long a2, long a3, long a4) throws Throwable { + return hookBridge(getMethodId(5, 26), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 27 + public static long stub_hook_27(long a0, long a1, long a2, long a3, long a4) throws Throwable { + return hookBridge(getMethodId(5, 27), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 28 + public static long stub_hook_28(long a0, long a1, long a2, long a3, long a4) throws Throwable { + return hookBridge(getMethodId(5, 28), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 5, index 29 + public static long stub_hook_29(long a0, long a1, long a2, long a3, long a4) throws Throwable { + return hookBridge(getMethodId(5, 29), null , a0, a1, a2, a3, a4); + } + + + //stub of arg size 6, index 0 + public static long stub_hook_0(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { + return hookBridge(getMethodId(6, 0), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 1 + public static long stub_hook_1(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { + return hookBridge(getMethodId(6, 1), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 2 + public static long stub_hook_2(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { + return hookBridge(getMethodId(6, 2), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 3 + public static long stub_hook_3(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { + return hookBridge(getMethodId(6, 3), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 4 + public static long stub_hook_4(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { + return hookBridge(getMethodId(6, 4), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 5 + public static long stub_hook_5(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { + return hookBridge(getMethodId(6, 5), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 6 + public static long stub_hook_6(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { + return hookBridge(getMethodId(6, 6), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 7 + public static long stub_hook_7(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { + return hookBridge(getMethodId(6, 7), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 8 + public static long stub_hook_8(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { + return hookBridge(getMethodId(6, 8), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 9 + public static long stub_hook_9(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { + return hookBridge(getMethodId(6, 9), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 10 + public static long stub_hook_10(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { + return hookBridge(getMethodId(6, 10), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 11 + public static long stub_hook_11(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { + return hookBridge(getMethodId(6, 11), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 12 + public static long stub_hook_12(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { + return hookBridge(getMethodId(6, 12), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 13 + public static long stub_hook_13(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { + return hookBridge(getMethodId(6, 13), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 14 + public static long stub_hook_14(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { + return hookBridge(getMethodId(6, 14), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 15 + public static long stub_hook_15(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { + return hookBridge(getMethodId(6, 15), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 16 + public static long stub_hook_16(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { + return hookBridge(getMethodId(6, 16), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 17 + public static long stub_hook_17(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { + return hookBridge(getMethodId(6, 17), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 18 + public static long stub_hook_18(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { + return hookBridge(getMethodId(6, 18), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 19 + public static long stub_hook_19(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { + return hookBridge(getMethodId(6, 19), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 20 + public static long stub_hook_20(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { + return hookBridge(getMethodId(6, 20), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 21 + public static long stub_hook_21(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { + return hookBridge(getMethodId(6, 21), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 22 + public static long stub_hook_22(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { + return hookBridge(getMethodId(6, 22), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 23 + public static long stub_hook_23(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { + return hookBridge(getMethodId(6, 23), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 24 + public static long stub_hook_24(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { + return hookBridge(getMethodId(6, 24), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 25 + public static long stub_hook_25(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { + return hookBridge(getMethodId(6, 25), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 26 + public static long stub_hook_26(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { + return hookBridge(getMethodId(6, 26), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 27 + public static long stub_hook_27(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { + return hookBridge(getMethodId(6, 27), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 28 + public static long stub_hook_28(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { + return hookBridge(getMethodId(6, 28), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 6, index 29 + public static long stub_hook_29(long a0, long a1, long a2, long a3, long a4, long a5) throws Throwable { + return hookBridge(getMethodId(6, 29), null , a0, a1, a2, a3, a4, a5); + } + + + //stub of arg size 7, index 0 + public static long stub_hook_0(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { + return hookBridge(getMethodId(7, 0), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 1 + public static long stub_hook_1(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { + return hookBridge(getMethodId(7, 1), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 2 + public static long stub_hook_2(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { + return hookBridge(getMethodId(7, 2), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 3 + public static long stub_hook_3(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { + return hookBridge(getMethodId(7, 3), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 4 + public static long stub_hook_4(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { + return hookBridge(getMethodId(7, 4), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 5 + public static long stub_hook_5(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { + return hookBridge(getMethodId(7, 5), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 6 + public static long stub_hook_6(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { + return hookBridge(getMethodId(7, 6), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 7 + public static long stub_hook_7(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { + return hookBridge(getMethodId(7, 7), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 8 + public static long stub_hook_8(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { + return hookBridge(getMethodId(7, 8), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 9 + public static long stub_hook_9(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { + return hookBridge(getMethodId(7, 9), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 10 + public static long stub_hook_10(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { + return hookBridge(getMethodId(7, 10), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 11 + public static long stub_hook_11(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { + return hookBridge(getMethodId(7, 11), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 12 + public static long stub_hook_12(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { + return hookBridge(getMethodId(7, 12), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 13 + public static long stub_hook_13(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { + return hookBridge(getMethodId(7, 13), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 14 + public static long stub_hook_14(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { + return hookBridge(getMethodId(7, 14), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 15 + public static long stub_hook_15(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { + return hookBridge(getMethodId(7, 15), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 16 + public static long stub_hook_16(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { + return hookBridge(getMethodId(7, 16), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 17 + public static long stub_hook_17(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { + return hookBridge(getMethodId(7, 17), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 18 + public static long stub_hook_18(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { + return hookBridge(getMethodId(7, 18), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 7, index 19 + public static long stub_hook_19(long a0, long a1, long a2, long a3, long a4, long a5, long a6) throws Throwable { + return hookBridge(getMethodId(7, 19), null , a0, a1, a2, a3, a4, a5, a6); + } + + + //stub of arg size 8, index 0 + public static long stub_hook_0(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { + return hookBridge(getMethodId(8, 0), null , a0, a1, a2, a3, a4, a5, a6, a7); + } + + + //stub of arg size 8, index 1 + public static long stub_hook_1(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { + return hookBridge(getMethodId(8, 1), null , a0, a1, a2, a3, a4, a5, a6, a7); + } + + + //stub of arg size 8, index 2 + public static long stub_hook_2(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { + return hookBridge(getMethodId(8, 2), null , a0, a1, a2, a3, a4, a5, a6, a7); + } + + + //stub of arg size 8, index 3 + public static long stub_hook_3(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { + return hookBridge(getMethodId(8, 3), null , a0, a1, a2, a3, a4, a5, a6, a7); + } + + + //stub of arg size 8, index 4 + public static long stub_hook_4(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { + return hookBridge(getMethodId(8, 4), null , a0, a1, a2, a3, a4, a5, a6, a7); + } + + + //stub of arg size 8, index 5 + public static long stub_hook_5(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { + return hookBridge(getMethodId(8, 5), null , a0, a1, a2, a3, a4, a5, a6, a7); + } + + + //stub of arg size 8, index 6 + public static long stub_hook_6(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { + return hookBridge(getMethodId(8, 6), null , a0, a1, a2, a3, a4, a5, a6, a7); + } + + + //stub of arg size 8, index 7 + public static long stub_hook_7(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { + return hookBridge(getMethodId(8, 7), null , a0, a1, a2, a3, a4, a5, a6, a7); + } + + + //stub of arg size 8, index 8 + public static long stub_hook_8(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { + return hookBridge(getMethodId(8, 8), null , a0, a1, a2, a3, a4, a5, a6, a7); + } + + + //stub of arg size 8, index 9 + public static long stub_hook_9(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7) throws Throwable { + return hookBridge(getMethodId(8, 9), null , a0, a1, a2, a3, a4, a5, a6, a7); + } + + + //stub of arg size 9, index 0 + public static long stub_hook_0(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { + return hookBridge(getMethodId(9, 0), null , a0, a1, a2, a3, a4, a5, a6, a7, a8); + } + + + //stub of arg size 9, index 1 + public static long stub_hook_1(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { + return hookBridge(getMethodId(9, 1), null , a0, a1, a2, a3, a4, a5, a6, a7, a8); + } + + + //stub of arg size 9, index 2 + public static long stub_hook_2(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { + return hookBridge(getMethodId(9, 2), null , a0, a1, a2, a3, a4, a5, a6, a7, a8); + } + + + //stub of arg size 9, index 3 + public static long stub_hook_3(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { + return hookBridge(getMethodId(9, 3), null , a0, a1, a2, a3, a4, a5, a6, a7, a8); + } + + + //stub of arg size 9, index 4 + public static long stub_hook_4(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { + return hookBridge(getMethodId(9, 4), null , a0, a1, a2, a3, a4, a5, a6, a7, a8); + } + + + //stub of arg size 9, index 5 + public static long stub_hook_5(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { + return hookBridge(getMethodId(9, 5), null , a0, a1, a2, a3, a4, a5, a6, a7, a8); + } + + + //stub of arg size 9, index 6 + public static long stub_hook_6(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { + return hookBridge(getMethodId(9, 6), null , a0, a1, a2, a3, a4, a5, a6, a7, a8); + } + + + //stub of arg size 9, index 7 + public static long stub_hook_7(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { + return hookBridge(getMethodId(9, 7), null , a0, a1, a2, a3, a4, a5, a6, a7, a8); + } + + + //stub of arg size 9, index 8 + public static long stub_hook_8(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { + return hookBridge(getMethodId(9, 8), null , a0, a1, a2, a3, a4, a5, a6, a7, a8); + } + + + //stub of arg size 9, index 9 + public static long stub_hook_9(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) throws Throwable { + return hookBridge(getMethodId(9, 9), null , a0, a1, a2, a3, a4, a5, a6, a7, a8); + } + + + //stub of arg size 10, index 0 + public static long stub_hook_0(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { + return hookBridge(getMethodId(10, 0), null , a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); + } + + + //stub of arg size 10, index 1 + public static long stub_hook_1(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { + return hookBridge(getMethodId(10, 1), null , a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); + } + + + //stub of arg size 10, index 2 + public static long stub_hook_2(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { + return hookBridge(getMethodId(10, 2), null , a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); + } + + + //stub of arg size 10, index 3 + public static long stub_hook_3(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { + return hookBridge(getMethodId(10, 3), null , a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); + } + + + //stub of arg size 10, index 4 + public static long stub_hook_4(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9) throws Throwable { + return hookBridge(getMethodId(10, 4), null , a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); + } + + + //stub of arg size 11, index 0 + public static long stub_hook_0(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9, long a10) throws Throwable { + return hookBridge(getMethodId(11, 0), null , a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); + } + + + //stub of arg size 11, index 1 + public static long stub_hook_1(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9, long a10) throws Throwable { + return hookBridge(getMethodId(11, 1), null , a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); + } + + + //stub of arg size 11, index 2 + public static long stub_hook_2(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9, long a10) throws Throwable { + return hookBridge(getMethodId(11, 2), null , a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); + } + + + //stub of arg size 11, index 3 + public static long stub_hook_3(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9, long a10) throws Throwable { + return hookBridge(getMethodId(11, 3), null , a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); + } + + + //stub of arg size 11, index 4 + public static long stub_hook_4(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9, long a10) throws Throwable { + return hookBridge(getMethodId(11, 4), null , a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); + } + + + //stub of arg size 12, index 0 + public static long stub_hook_0(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9, long a10, long a11) throws Throwable { + return hookBridge(getMethodId(12, 0), null , a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); + } + + + //stub of arg size 12, index 1 + public static long stub_hook_1(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9, long a10, long a11) throws Throwable { + return hookBridge(getMethodId(12, 1), null , a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); + } + + + //stub of arg size 12, index 2 + public static long stub_hook_2(long a0, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8, long a9, long a10, long a11) throws Throwable { + return hookBridge(getMethodId(12, 2), null , a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); + } + +} diff --git a/sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/ErrorCatch.java b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/ErrorCatch.java new file mode 100644 index 000000000..c6a5a82de --- /dev/null +++ b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/ErrorCatch.java @@ -0,0 +1,22 @@ +package com.swift.sandhook.xposedcompat.methodgen; + +import android.util.Log; + +import com.swift.sandhook.SandHook; +import com.swift.sandhook.xposedcompat.XposedCompat; + +import java.lang.reflect.Member; +import java.lang.reflect.Method; + +public class ErrorCatch { + + public static Object callOriginError(Member originMethod, Method backupMethod, Object thiz, Object[] args) throws Throwable { + if (XposedCompat.retryWhenCallOriginError) { + Log.w("SandHook", "method <" + originMethod.toString() + "> use invoke to call origin!"); + return SandHook.callOriginMethod(originMethod, backupMethod, thiz, args); + } else { + return null; + } + } + +} diff --git a/sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/HookMaker.java b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/HookMaker.java new file mode 100644 index 000000000..2afd8828b --- /dev/null +++ b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/HookMaker.java @@ -0,0 +1,14 @@ +package com.swift.sandhook.xposedcompat.methodgen; + +import java.lang.reflect.Member; +import java.lang.reflect.Method; + +import de.robv.android.xposed.XposedBridge; + +public interface HookMaker { + void start(Member member, XposedBridge.AdditionalHookInfo hookInfo, + ClassLoader appClassLoader, String dexDirPath) throws Exception; + Method getHookMethod(); + Method getBackupMethod(); + Method getCallBackupMethod(); +} diff --git a/sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/HookerDexMaker.java b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/HookerDexMaker.java new file mode 100644 index 000000000..19294727d --- /dev/null +++ b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/HookerDexMaker.java @@ -0,0 +1,698 @@ +package com.swift.sandhook.xposedcompat.methodgen; + +import android.text.TextUtils; + +import com.swift.sandhook.SandHook; +import com.swift.sandhook.SandHookMethodResolver; +import com.swift.sandhook.wrapper.HookWrapper; +import com.swift.sandhook.xposedcompat.XposedCompat; +import com.swift.sandhook.xposedcompat.utils.DexLog; + +import java.io.File; +import java.lang.reflect.Constructor; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Map; + +import de.robv.android.xposed.XC_MethodHook; +import de.robv.android.xposed.XposedBridge; +import external.com.android.dx.BinaryOp; +import external.com.android.dx.Code; +import external.com.android.dx.Comparison; +import external.com.android.dx.DexMaker; +import external.com.android.dx.FieldId; +import external.com.android.dx.Label; +import external.com.android.dx.Local; +import external.com.android.dx.MethodId; +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.createResultLocals; +import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.getObjTypeIdIfPrimitive; + +public class HookerDexMaker implements HookMaker { + + public static final String METHOD_NAME_BACKUP = "backup"; + public static final String METHOD_NAME_HOOK = "hook"; + public static final String METHOD_NAME_CALL_BACKUP = "callBackup"; + public static final String METHOD_NAME_SETUP = "setup"; + public static final String METHOD_NAME_LOG = "printMethodHookIn"; + public static final TypeId objArrayTypeId = TypeId.get(Object[].class); + private static final String CLASS_DESC_PREFIX = "L"; + private static final String CLASS_NAME_PREFIX = "SandHooker"; + private static final String FIELD_NAME_HOOK_INFO = "additionalHookInfo"; + private static final String FIELD_NAME_METHOD = "method"; + private static final String FIELD_NAME_BACKUP_METHOD = "backupMethod"; + private static final String PARAMS_FIELD_NAME_METHOD = "method"; + private static final String PARAMS_FIELD_NAME_THIS_OBJECT = "thisObject"; + private static final String PARAMS_FIELD_NAME_ARGS = "args"; + private static final String CALLBACK_METHOD_NAME_BEFORE = "callBeforeHookedMethod"; + private static final String CALLBACK_METHOD_NAME_AFTER = "callAfterHookedMethod"; + private static final TypeId throwableTypeId = TypeId.get(Throwable.class); + private static final TypeId memberTypeId = TypeId.get(Member.class); + private static final TypeId methodTypeId = TypeId.get(Method.class); + private static final TypeId callbackTypeId = TypeId.get(XC_MethodHook.class); + private static final TypeId hookInfoTypeId + = TypeId.get(XposedBridge.AdditionalHookInfo.class); + private static final TypeId callbacksTypeId + = TypeId.get(XposedBridge.CopyOnWriteSortedSet.class); + private static final TypeId paramTypeId + = TypeId.get(XC_MethodHook.MethodHookParam.class); + private static final MethodId setResultMethodId = + paramTypeId.getMethod(TypeId.VOID, "setResult", TypeId.OBJECT); + private static final MethodId setThrowableMethodId = + paramTypeId.getMethod(TypeId.VOID, "setThrowable", throwableTypeId); + private static final MethodId getResultMethodId = + paramTypeId.getMethod(TypeId.OBJECT, "getResult"); + private static final MethodId getThrowableMethodId = + paramTypeId.getMethod(throwableTypeId, "getThrowable"); + private static final MethodId hasThrowableMethodId = + paramTypeId.getMethod(TypeId.BOOLEAN, "hasThrowable"); + private static final MethodId callAfterCallbackMethodId = + callbackTypeId.getMethod(TypeId.VOID, CALLBACK_METHOD_NAME_AFTER, paramTypeId); + private static final MethodId callBeforeCallbackMethodId = + callbackTypeId.getMethod(TypeId.VOID, CALLBACK_METHOD_NAME_BEFORE, paramTypeId); + private static final FieldId returnEarlyFieldId = + paramTypeId.getField(TypeId.BOOLEAN, "returnEarly"); + private static final TypeId xposedBridgeTypeId = TypeId.get(XposedBridge.class); + private static final MethodId logThrowableMethodId = + xposedBridgeTypeId.getMethod(TypeId.VOID, "log", throwableTypeId); + + private FieldId mHookInfoFieldId; + private FieldId mMethodFieldId; + private FieldId mBackupMethodFieldId; + private MethodId mBackupMethodId; + private MethodId mCallBackupMethodId; + private MethodId mHookMethodId; + private MethodId mPrintLogMethodId; + private MethodId mSandHookCallOriginMethodId; + + private TypeId mHookerTypeId; + private TypeId[] mParameterTypeIds; + private Class[] mActualParameterTypes; + private Class mReturnType; + private TypeId mReturnTypeId; + private boolean mIsStatic; + // TODO use this to generate methods + private boolean mHasThrowable; + + private DexMaker mDexMaker; + private Member mMember; + private XposedBridge.AdditionalHookInfo mHookInfo; + private ClassLoader mAppClassLoader; + private Class mHookClass; + private Method mHookMethod; + private Method mBackupMethod; + private Method mCallBackupMethod; + private String mDexDirPath; + + private static TypeId[] getParameterTypeIds(Class[] parameterTypes, boolean isStatic) { + int parameterSize = parameterTypes.length; + int targetParameterSize = isStatic ? parameterSize : parameterSize + 1; + TypeId[] parameterTypeIds = new TypeId[targetParameterSize]; + int offset = 0; + if (!isStatic) { + parameterTypeIds[0] = TypeId.OBJECT; + offset = 1; + } + for (int i = 0; i < parameterTypes.length; i++) { + parameterTypeIds[i + offset] = TypeId.get(parameterTypes[i]); + } + return parameterTypeIds; + } + + private static Class[] getParameterTypes(Class[] parameterTypes, boolean isStatic) { + if (isStatic) { + return parameterTypes; + } + int parameterSize = parameterTypes.length; + int targetParameterSize = parameterSize + 1; + Class[] newParameterTypes = new Class[targetParameterSize]; + int offset = 1; + newParameterTypes[0] = Object.class; + System.arraycopy(parameterTypes, 0, newParameterTypes, offset, parameterTypes.length); + return newParameterTypes; + } + + public void start(Member member, XposedBridge.AdditionalHookInfo hookInfo, + ClassLoader appClassLoader, String dexDirPath) throws Exception { + if (member instanceof Method) { + Method method = (Method) member; + mIsStatic = Modifier.isStatic(method.getModifiers()); + mReturnType = method.getReturnType(); + if (mReturnType.equals(Void.class) || mReturnType.equals(void.class) + || mReturnType.isPrimitive()) { + mReturnTypeId = TypeId.get(mReturnType); + } else { + // all others fallback to plain Object for convenience + mReturnType = Object.class; + mReturnTypeId = TypeId.OBJECT; + } + mParameterTypeIds = getParameterTypeIds(method.getParameterTypes(), mIsStatic); + mActualParameterTypes = getParameterTypes(method.getParameterTypes(), mIsStatic); + mHasThrowable = method.getExceptionTypes().length > 0; + } else if (member instanceof Constructor) { + Constructor constructor = (Constructor) member; + mIsStatic = false; + mReturnType = void.class; + mReturnTypeId = TypeId.VOID; + mParameterTypeIds = getParameterTypeIds(constructor.getParameterTypes(), mIsStatic); + mActualParameterTypes = getParameterTypes(constructor.getParameterTypes(), mIsStatic); + mHasThrowable = constructor.getExceptionTypes().length > 0; + } else if (member.getDeclaringClass().isInterface()) { + throw new IllegalArgumentException("Cannot hook interfaces: " + member.toString()); + } else if (Modifier.isAbstract(member.getModifiers())) { + throw new IllegalArgumentException("Cannot hook abstract methods: " + member.toString()); + } else { + throw new IllegalArgumentException("Only methods and constructors can be hooked: " + member.toString()); + } + mMember = member; + mHookInfo = hookInfo; + mDexDirPath = dexDirPath; + if (appClassLoader == null + || appClassLoader.getClass().getName().equals("java.lang.BootClassLoader")) { + mAppClassLoader = this.getClass().getClassLoader(); + } else { + mAppClassLoader = appClassLoader; + } + + mDexMaker = new DexMaker(); + // Generate a Hooker class. + String className = getClassName(mMember); + String dexName = className + ".jar"; + + HookWrapper.HookEntity hookEntity = null; + //try load cache first + try { + ClassLoader loader = mDexMaker.loadClassDirect(mAppClassLoader, new File(mDexDirPath), dexName); + if (loader != null) { + hookEntity = loadHookerClass(loader, className); + } + } catch (Throwable throwable) {} + + //do generate + if (hookEntity == null) { + hookEntity = doMake(className, dexName); + } + SandHook.hook(hookEntity); + } + + private HookWrapper.HookEntity doMake(String className, String dexName) throws Exception { + mHookerTypeId = TypeId.get(CLASS_DESC_PREFIX + className + ";"); + mDexMaker.declare(mHookerTypeId, className + ".generated", Modifier.PUBLIC, TypeId.OBJECT); + generateFields(); + generateSetupMethod(); + if (XposedCompat.retryWhenCallOriginError) { + generateBackupAndCallOriginCheckMethod(); + } else { + generateBackupMethod(); + } + generateCallBackupMethod(); + generateHookMethod(); + + ClassLoader loader; + if (TextUtils.isEmpty(mDexDirPath)) { + throw new IllegalArgumentException("dexDirPath should not be empty!!!"); + } + // Create the dex file and load it. + loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(mDexDirPath), dexName); + return loadHookerClass(loader, className); + } + + private HookWrapper.HookEntity loadHookerClass(ClassLoader loader, String className) throws Exception { + mHookClass = loader.loadClass(className); + // Execute our newly-generated code in-process. + mHookMethod = mHookClass.getMethod(METHOD_NAME_HOOK, mActualParameterTypes); + mBackupMethod = mHookClass.getMethod(METHOD_NAME_BACKUP, mActualParameterTypes); + mCallBackupMethod = mHookClass.getMethod(METHOD_NAME_CALL_BACKUP, mActualParameterTypes); + SandHook.resolveStaticMethod(mCallBackupMethod); + SandHookMethodResolver.resolveMethod(mCallBackupMethod, mBackupMethod); + SandHook.compileMethod(mCallBackupMethod); + mHookClass.getMethod(METHOD_NAME_SETUP, Member.class, Method.class, XposedBridge.AdditionalHookInfo.class).invoke(null, mMember, mBackupMethod, mHookInfo); + return new HookWrapper.HookEntity(mMember, mHookMethod, mBackupMethod); + } + + private String getClassName(Member originMethod) { + return CLASS_NAME_PREFIX + "_" + MD5(originMethod.toString()); + } + + public Method getHookMethod() { + return mHookMethod; + } + + public Method getBackupMethod() { + return mBackupMethod; + } + + public Method getCallBackupMethod() { + return mCallBackupMethod; + } + + public Class getHookClass() { + return mHookClass; + } + + private void generateFields() { + mHookInfoFieldId = mHookerTypeId.getField(hookInfoTypeId, FIELD_NAME_HOOK_INFO); + mMethodFieldId = mHookerTypeId.getField(memberTypeId, FIELD_NAME_METHOD); + mBackupMethodFieldId = mHookerTypeId.getField(methodTypeId, FIELD_NAME_BACKUP_METHOD); + mDexMaker.declare(mHookInfoFieldId, Modifier.STATIC, null); + mDexMaker.declare(mMethodFieldId, Modifier.STATIC, null); + mDexMaker.declare(mBackupMethodFieldId, Modifier.STATIC, null); + } + + private void generateSetupMethod() { + MethodId setupMethodId = mHookerTypeId.getMethod( + TypeId.VOID, METHOD_NAME_SETUP, memberTypeId, methodTypeId, hookInfoTypeId); + Code code = mDexMaker.declare(setupMethodId, Modifier.PUBLIC | Modifier.STATIC); + // init logic + // get parameters + Local method = code.getParameter(0, memberTypeId); + Local backupMethod = code.getParameter(1, methodTypeId); + Local hookInfo = code.getParameter(2, hookInfoTypeId); + // save params to static + code.sput(mMethodFieldId, method); + code.sput(mBackupMethodFieldId, backupMethod); + code.sput(mHookInfoFieldId, hookInfo); + code.returnVoid(); + } + + private void generateBackupMethod() { + mBackupMethodId = mHookerTypeId.getMethod(mReturnTypeId, METHOD_NAME_BACKUP, mParameterTypeIds); + Code code = mDexMaker.declare(mBackupMethodId, Modifier.PUBLIC | Modifier.STATIC); + + Local method = code.newLocal(memberTypeId); + + Map resultLocals = createResultLocals(code); + MethodId errLogMethod = TypeId.get(DexLog.class).getMethod(TypeId.get(Void.TYPE), "printCallOriginError", memberTypeId); + + + //very very important!!!!!!!!!!! + //add a try cache block avoid inline + Label tryCatchBlock = new Label(); + + code.addCatchClause(throwableTypeId, tryCatchBlock); + code.sget(mMethodFieldId, method); + code.invokeStatic(errLogMethod, null, method); + // start of try + code.mark(tryCatchBlock); + + // do nothing + if (mReturnTypeId.equals(TypeId.VOID)) { + code.returnVoid(); + } else { + // we have limited the returnType to primitives or Object, so this should be safe + code.returnValue(resultLocals.get(mReturnTypeId)); + } + } + + private void generateBackupAndCallOriginCheckMethod() { + mBackupMethodId = mHookerTypeId.getMethod(mReturnTypeId, METHOD_NAME_BACKUP, mParameterTypeIds); + mSandHookCallOriginMethodId = TypeId.get(ErrorCatch.class).getMethod(TypeId.get(Object.class), "callOriginError", memberTypeId, methodTypeId, TypeId.get(Object.class), TypeId.get(Object[].class)); + MethodId errLogMethod = TypeId.get(DexLog.class).getMethod(TypeId.get(Void.TYPE), "printCallOriginError", methodTypeId); + + Code code = mDexMaker.declare(mBackupMethodId, Modifier.PUBLIC | Modifier.STATIC); + + Local method = code.newLocal(memberTypeId); + Local backupMethod = code.newLocal(methodTypeId); + Local thisObject = code.newLocal(TypeId.OBJECT); + Local args = code.newLocal(objArrayTypeId); + Local actualParamSize = code.newLocal(TypeId.INT); + Local argIndex = code.newLocal(TypeId.INT); + Local resultObj = code.newLocal(TypeId.OBJECT); + Label tryCatchBlock = new Label(); + + Local[] allArgsLocals = createParameterLocals(code); + Map resultLocals = createResultLocals(code); + + + + //very very important!!!!!!!!!!! + //add a try cache block avoid inline + + + // start of try + code.addCatchClause(throwableTypeId, tryCatchBlock); + code.sget(mMethodFieldId, method); + code.invokeStatic(errLogMethod, null, method); + //call origin by invoke + code.loadConstant(args, null); + code.loadConstant(argIndex, 0); + code.sget(mBackupMethodFieldId, backupMethod); + int paramsSize = mParameterTypeIds.length; + int offset = 0; + // thisObject + if (mIsStatic) { + // thisObject = null + code.loadConstant(thisObject, null); + } else { + // thisObject = args[0] + offset = 1; + code.move(thisObject, allArgsLocals[0]); + } + +// offset = mIsStatic ? 0 : 1; +// for (int i = offset; i < allArgsLocals.length; i++) { +// code.loadConstant(argIndex, i - offset); +// code.aget(resultObj, args, argIndex); +// autoUnboxIfNecessary(code, allArgsLocals[i], resultObj, resultLocals, true); +// } + + // actual args (exclude thisObject if this is not a static method) + code.loadConstant(actualParamSize, paramsSize - offset); + code.newArray(args, actualParamSize); + for (int i = offset; i < paramsSize; i++) { + Local parameter = allArgsLocals[i]; + // save parameter to resultObj as Object + autoBoxIfNecessary(code, resultObj, parameter); + code.loadConstant(argIndex, i - offset); + // save Object to args + code.aput(args, argIndex, resultObj); + } + + if (mReturnTypeId.equals(TypeId.VOID)) { + code.invokeStatic(mSandHookCallOriginMethodId, null, method, backupMethod, thisObject, args); + code.returnVoid(); + } else { + code.invokeStatic(mSandHookCallOriginMethodId, resultObj, method, backupMethod, thisObject, args); + TypeId objTypeId = getObjTypeIdIfPrimitive(mReturnTypeId); + Local matchObjLocal = resultLocals.get(objTypeId); + code.cast(matchObjLocal, resultObj); + // have to use matching typed Object(Integer, Double ...) to do unboxing + Local toReturn = resultLocals.get(mReturnTypeId); + autoUnboxIfNecessary(code, toReturn, matchObjLocal, resultLocals, true); + code.returnValue(toReturn); + } + + code.mark(tryCatchBlock); + // do nothing + if (mReturnTypeId.equals(TypeId.VOID)) { + code.returnVoid(); + } else { + // we have limited the returnType to primitives or Object, so this should be safe + code.returnValue(resultLocals.get(mReturnTypeId)); + } + } + + private void generateCallBackupMethod() { + mCallBackupMethodId = mHookerTypeId.getMethod(mReturnTypeId, METHOD_NAME_CALL_BACKUP, mParameterTypeIds); + Code code = mDexMaker.declare(mCallBackupMethodId, Modifier.PUBLIC | Modifier.STATIC); + // just call backup and return its result + + Local localOrigin = code.newLocal(memberTypeId); + Local localBackup = code.newLocal(methodTypeId); + Local[] allArgsLocals = createParameterLocals(code); + Map resultLocals = createResultLocals(code); + + + code.sget(mMethodFieldId, localOrigin); + code.sget(mBackupMethodFieldId, localBackup); + + MethodId methodId = TypeId.get(SandHook.class).getMethod(TypeId.get(Void.TYPE), "ensureBackupMethod", memberTypeId, methodTypeId); + code.invokeStatic(methodId, null, localOrigin, localBackup); + + + if (mReturnTypeId.equals(TypeId.VOID)) { + code.invokeStatic(mBackupMethodId, null, allArgsLocals); + code.returnVoid(); + } else { + Local result = resultLocals.get(mReturnTypeId); + code.invokeStatic(mBackupMethodId, result, allArgsLocals); + code.returnValue(result); + } + } + + private void generateHookMethod() { + mHookMethodId = mHookerTypeId.getMethod(mReturnTypeId, METHOD_NAME_HOOK, mParameterTypeIds); + mPrintLogMethodId = TypeId.get(DexLog.class).getMethod(TypeId.get(Void.TYPE), METHOD_NAME_LOG, TypeId.get(Member.class)); + Code code = mDexMaker.declare(mHookMethodId, Modifier.PUBLIC | Modifier.STATIC); + + // code starts + + // prepare common labels + Label noHookReturn = new Label(); + Label incrementAndCheckBefore = new Label(); + Label tryBeforeCatch = new Label(); + Label noExceptionBefore = new Label(); + Label checkAndCallBackup = new Label(); + Label beginCallBefore = new Label(); + Label beginCallAfter = new Label(); + Label tryOrigCatch = new Label(); + Label noExceptionOrig = new Label(); + Label tryAfterCatch = new Label(); + Label decrementAndCheckAfter = new Label(); + Label noBackupThrowable = new Label(); + Label throwThrowable = new Label(); + // prepare locals + Local disableHooks = code.newLocal(TypeId.BOOLEAN); + Local hookInfo = code.newLocal(hookInfoTypeId); + Local callbacks = code.newLocal(callbacksTypeId); + Local snapshot = code.newLocal(objArrayTypeId); + Local snapshotLen = code.newLocal(TypeId.INT); + Local callbackObj = code.newLocal(TypeId.OBJECT); + Local callback = code.newLocal(callbackTypeId); + + Local resultObj = code.newLocal(TypeId.OBJECT); // as a temp Local + Local one = code.newLocal(TypeId.INT); + Local nullObj = code.newLocal(TypeId.OBJECT); + Local throwable = code.newLocal(throwableTypeId); + + Local param = code.newLocal(paramTypeId); + Local method = code.newLocal(memberTypeId); + Local thisObject = code.newLocal(TypeId.OBJECT); + Local args = code.newLocal(objArrayTypeId); + Local returnEarly = code.newLocal(TypeId.BOOLEAN); + + Local actualParamSize = code.newLocal(TypeId.INT); + Local argIndex = code.newLocal(TypeId.INT); + + Local beforeIdx = code.newLocal(TypeId.INT); + Local lastResult = code.newLocal(TypeId.OBJECT); + Local lastThrowable = code.newLocal(throwableTypeId); + Local hasThrowable = code.newLocal(TypeId.BOOLEAN); + + Local[] allArgsLocals = createParameterLocals(code); + + Map resultLocals = createResultLocals(code); + + code.loadConstant(args, null); + code.loadConstant(argIndex, 0); + code.loadConstant(one, 1); + code.loadConstant(snapshotLen, 0); + code.loadConstant(nullObj, null); + + code.sget(mMethodFieldId, method); + //print log + code.invokeStatic(mPrintLogMethodId, null, method); + + // check XposedBridge.disableHooks flag + + FieldId disableHooksField = + xposedBridgeTypeId.getField(TypeId.BOOLEAN, "disableHooks"); + code.sget(disableHooksField, disableHooks); + // disableHooks == true => no hooking + code.compareZ(Comparison.NE, noHookReturn, disableHooks); + + // check callbacks length + code.sget(mHookInfoFieldId, hookInfo); + code.iget(hookInfoTypeId.getField(callbacksTypeId, "callbacks"), callbacks, hookInfo); + code.invokeVirtual(callbacksTypeId.getMethod(objArrayTypeId, "getSnapshot"), snapshot, callbacks); + code.arrayLength(snapshotLen, snapshot); + // snapshotLen == 0 => no hooking + code.compareZ(Comparison.EQ, noHookReturn, snapshotLen); + + // start hooking + + // prepare hooking locals + int paramsSize = mParameterTypeIds.length; + int offset = 0; + // thisObject + if (mIsStatic) { + // thisObject = null + code.loadConstant(thisObject, null); + } else { + // thisObject = args[0] + offset = 1; + code.move(thisObject, allArgsLocals[0]); + } + // actual args (exclude thisObject if this is not a static method) + code.loadConstant(actualParamSize, paramsSize - offset); + code.newArray(args, actualParamSize); + for (int i = offset; i < paramsSize; i++) { + Local parameter = allArgsLocals[i]; + // save parameter to resultObj as Object + autoBoxIfNecessary(code, resultObj, parameter); + code.loadConstant(argIndex, i - offset); + // save Object to args + code.aput(args, argIndex, resultObj); + } + // create param + code.newInstance(param, paramTypeId.getConstructor()); + // set method, thisObject, args + code.iput(paramTypeId.getField(memberTypeId, PARAMS_FIELD_NAME_METHOD), param, method); + code.iput(paramTypeId.getField(TypeId.OBJECT, PARAMS_FIELD_NAME_THIS_OBJECT), param, thisObject); + code.iput(paramTypeId.getField(objArrayTypeId, PARAMS_FIELD_NAME_ARGS), param, args); + + // call beforeCallbacks + code.loadConstant(beforeIdx, 0); + + code.mark(beginCallBefore); + // start of try + code.addCatchClause(throwableTypeId, tryBeforeCatch); + + code.aget(callbackObj, snapshot, beforeIdx); + code.cast(callback, callbackObj); + code.invokeVirtual(callBeforeCallbackMethodId, null, callback, param); + code.jump(noExceptionBefore); + + // end of try + code.removeCatchClause(throwableTypeId); + + // start of catch + code.mark(tryBeforeCatch); + code.moveException(throwable); + code.invokeStatic(logThrowableMethodId, null, throwable); + code.invokeVirtual(setResultMethodId, null, param, nullObj); + code.loadConstant(returnEarly, false); + code.iput(returnEarlyFieldId, param, returnEarly); + code.jump(incrementAndCheckBefore); + + // no exception when calling beforeCallbacks + code.mark(noExceptionBefore); + code.iget(returnEarlyFieldId, returnEarly, param); + // if returnEarly == false, continue + code.compareZ(Comparison.EQ, incrementAndCheckBefore, returnEarly); + // returnEarly == true, break + code.op(BinaryOp.ADD, beforeIdx, beforeIdx, one); + code.jump(checkAndCallBackup); + + // increment and check to continue + code.mark(incrementAndCheckBefore); + code.op(BinaryOp.ADD, beforeIdx, beforeIdx, one); + code.compare(Comparison.LT, beginCallBefore, beforeIdx, snapshotLen); + + // check and call backup + code.mark(checkAndCallBackup); + code.iget(returnEarlyFieldId, returnEarly, param); + // if returnEarly == true, go to call afterCallbacks directly + code.compareZ(Comparison.NE, noExceptionOrig, returnEarly); + // try to call backup + // try start + code.addCatchClause(throwableTypeId, tryOrigCatch); + // we have to load args[] to paramLocals + // because args[] may be changed in beforeHookedMethod + // should consider first param is thisObj if hooked method is not static + offset = mIsStatic ? 0 : 1; + for (int i = offset; i < allArgsLocals.length; i++) { + code.loadConstant(argIndex, i - offset); + code.aget(resultObj, args, argIndex); + autoUnboxIfNecessary(code, allArgsLocals[i], resultObj, resultLocals, true); + } + // get pre-created Local with a matching typeId + if (mReturnTypeId.equals(TypeId.VOID)) { + code.invokeStatic(mBackupMethodId, null, allArgsLocals); + // TODO maybe keep preset result to do some magic? + code.invokeVirtual(setResultMethodId, null, param, nullObj); + } else { + Local returnedResult = resultLocals.get(mReturnTypeId); + code.invokeStatic(mBackupMethodId, returnedResult, allArgsLocals); + // save returnedResult to resultObj as a Object + autoBoxIfNecessary(code, resultObj, returnedResult); + // save resultObj to param + code.invokeVirtual(setResultMethodId, null, param, resultObj); + } + // go to call afterCallbacks + code.jump(noExceptionOrig); + // try end + code.removeCatchClause(throwableTypeId); + // catch + code.mark(tryOrigCatch); + code.moveException(throwable); + // exception occurred when calling backup, save throwable to param + code.invokeVirtual(setThrowableMethodId, null, param, throwable); + + code.mark(noExceptionOrig); + code.op(BinaryOp.SUBTRACT, beforeIdx, beforeIdx, one); + + // call afterCallbacks + code.mark(beginCallAfter); + // save results of backup calling + code.invokeVirtual(getResultMethodId, lastResult, param); + code.invokeVirtual(getThrowableMethodId, lastThrowable, param); + // try start + code.addCatchClause(throwableTypeId, tryAfterCatch); + code.aget(callbackObj, snapshot, beforeIdx); + code.cast(callback, callbackObj); + code.invokeVirtual(callAfterCallbackMethodId, null, callback, param); + // all good, just continue + code.jump(decrementAndCheckAfter); + // try end + code.removeCatchClause(throwableTypeId); + // catch + code.mark(tryAfterCatch); + code.moveException(throwable); + code.invokeStatic(logThrowableMethodId, null, throwable); + // if lastThrowable == null, go to recover lastResult + code.compareZ(Comparison.EQ, noBackupThrowable, lastThrowable); + // lastThrowable != null, recover lastThrowable + code.invokeVirtual(setThrowableMethodId, null, param, lastThrowable); + // continue + code.jump(decrementAndCheckAfter); + code.mark(noBackupThrowable); + // recover lastResult and continue + code.invokeVirtual(setResultMethodId, null, param, lastResult); + // decrement and check continue + code.mark(decrementAndCheckAfter); + code.op(BinaryOp.SUBTRACT, beforeIdx, beforeIdx, one); + code.compareZ(Comparison.GE, beginCallAfter, beforeIdx); + + // callbacks end + // return + code.invokeVirtual(hasThrowableMethodId, hasThrowable, param); + // if hasThrowable, throw the throwable and return + code.compareZ(Comparison.NE, throwThrowable, hasThrowable); + // return getResult + if (mReturnTypeId.equals(TypeId.VOID)) { + code.returnVoid(); + } else { + // getResult always return an Object, so save to resultObj + code.invokeVirtual(getResultMethodId, resultObj, param); + // have to unbox it if returnType is primitive + // casting Object + TypeId objTypeId = getObjTypeIdIfPrimitive(mReturnTypeId); + Local matchObjLocal = resultLocals.get(objTypeId); + code.cast(matchObjLocal, resultObj); + // have to use matching typed Object(Integer, Double ...) to do unboxing + Local toReturn = resultLocals.get(mReturnTypeId); + autoUnboxIfNecessary(code, toReturn, matchObjLocal, resultLocals, true); + // return + code.returnValue(toReturn); + } + // throw throwable + code.mark(throwThrowable); + code.invokeVirtual(getThrowableMethodId, throwable, param); + code.throwValue(throwable); + + // call backup and return + code.mark(noHookReturn); + if (mReturnTypeId.equals(TypeId.VOID)) { + code.invokeStatic(mBackupMethodId, null, allArgsLocals); + code.returnVoid(); + } else { + Local result = resultLocals.get(mReturnTypeId); + code.invokeStatic(mBackupMethodId, result, allArgsLocals); + code.returnValue(result); + } + } + + private Local[] createParameterLocals(Code code) { + Local[] paramLocals = new Local[mParameterTypeIds.length]; + for (int i = 0; i < mParameterTypeIds.length; i++) { + paramLocals[i] = code.getParameter(i, mParameterTypeIds[i]); + } + return paramLocals; + } +} diff --git a/sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/HookerDexMakerNew.java b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/HookerDexMakerNew.java new file mode 100644 index 000000000..1303a3ffa --- /dev/null +++ b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/HookerDexMakerNew.java @@ -0,0 +1,298 @@ +package com.swift.sandhook.xposedcompat.methodgen; + +import android.text.TextUtils; + +import external.com.android.dx.Code; +import external.com.android.dx.DexMaker; +import external.com.android.dx.FieldId; +import external.com.android.dx.Local; +import external.com.android.dx.MethodId; +import external.com.android.dx.TypeId; +import com.swift.sandhook.SandHook; +import com.swift.sandhook.wrapper.HookWrapper; +import com.swift.sandhook.xposedcompat.hookstub.HookStubManager; + +import java.io.File; +import java.lang.reflect.Constructor; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Map; + +import de.robv.android.xposed.XposedBridge; +import de.robv.android.xposed.XposedHelpers; + +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.createResultLocals; +import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.getObjTypeIdIfPrimitive; + +public class HookerDexMakerNew implements HookMaker { + + public static final String METHOD_NAME_BACKUP = "backup"; + public static final String METHOD_NAME_HOOK = "hook"; + public static final TypeId objArrayTypeId = TypeId.get(Object[].class); + private static final String CLASS_DESC_PREFIX = "L"; + private static final String CLASS_NAME_PREFIX = "SandHookerN"; + private static final String FIELD_NAME_HOOK_INFO = "additionalHookInfo"; + private static final String FIELD_NAME_METHOD = "method"; + private static final String FIELD_NAME_BACKUP_METHOD = "backupMethod"; + private static final TypeId memberTypeId = TypeId.get(Member.class); + private static final TypeId methodTypeId = TypeId.get(Method.class); + private static final TypeId hookInfoTypeId + = TypeId.get(XposedBridge.AdditionalHookInfo.class); + + + private FieldId mHookInfoFieldId; + private FieldId mMethodFieldId; + private FieldId mBackupMethodFieldId; + private MethodId mHookMethodId; + private MethodId mBackupMethodId; + private MethodId mSandHookBridgeMethodId; + + private TypeId mHookerTypeId; + private TypeId[] mParameterTypeIds; + private Class[] mActualParameterTypes; + private Class mReturnType; + private TypeId mReturnTypeId; + private boolean mIsStatic; + // TODO use this to generate methods + private boolean mHasThrowable; + + private DexMaker mDexMaker; + private Member mMember; + private XposedBridge.AdditionalHookInfo mHookInfo; + private ClassLoader mAppClassLoader; + private Class mHookClass; + private Method mHookMethod; + private Method mBackupMethod; + private String mDexDirPath; + + private static TypeId[] getParameterTypeIds(Class[] parameterTypes, boolean isStatic) { + int parameterSize = parameterTypes.length; + int targetParameterSize = isStatic ? parameterSize : parameterSize + 1; + TypeId[] parameterTypeIds = new TypeId[targetParameterSize]; + int offset = 0; + if (!isStatic) { + parameterTypeIds[0] = TypeId.OBJECT; + offset = 1; + } + for (int i = 0; i < parameterTypes.length; i++) { + parameterTypeIds[i + offset] = TypeId.get(parameterTypes[i]); + } + return parameterTypeIds; + } + + private static Class[] getParameterTypes(Class[] parameterTypes, boolean isStatic) { + if (isStatic) { + return parameterTypes; + } + int parameterSize = parameterTypes.length; + int targetParameterSize = parameterSize + 1; + Class[] newParameterTypes = new Class[targetParameterSize]; + int offset = 1; + newParameterTypes[0] = Object.class; + System.arraycopy(parameterTypes, 0, newParameterTypes, offset, parameterTypes.length); + return newParameterTypes; + } + + public void start(Member member, XposedBridge.AdditionalHookInfo hookInfo, + ClassLoader appClassLoader, String dexDirPath) throws Exception { + if (member instanceof Method) { + Method method = (Method) member; + mIsStatic = Modifier.isStatic(method.getModifiers()); + mReturnType = method.getReturnType(); + if (mReturnType.equals(Void.class) || mReturnType.equals(void.class) + || mReturnType.isPrimitive()) { + mReturnTypeId = TypeId.get(mReturnType); + } else { + // all others fallback to plain Object for convenience + mReturnType = Object.class; + mReturnTypeId = TypeId.OBJECT; + } + mParameterTypeIds = getParameterTypeIds(method.getParameterTypes(), mIsStatic); + mActualParameterTypes = getParameterTypes(method.getParameterTypes(), mIsStatic); + mHasThrowable = method.getExceptionTypes().length > 0; + } else if (member instanceof Constructor) { + Constructor constructor = (Constructor) member; + mIsStatic = false; + mReturnType = void.class; + mReturnTypeId = TypeId.VOID; + mParameterTypeIds = getParameterTypeIds(constructor.getParameterTypes(), mIsStatic); + mActualParameterTypes = getParameterTypes(constructor.getParameterTypes(), mIsStatic); + mHasThrowable = constructor.getExceptionTypes().length > 0; + } else if (member.getDeclaringClass().isInterface()) { + throw new IllegalArgumentException("Cannot hook interfaces: " + member.toString()); + } else if (Modifier.isAbstract(member.getModifiers())) { + throw new IllegalArgumentException("Cannot hook abstract methods: " + member.toString()); + } else { + throw new IllegalArgumentException("Only methods and constructors can be hooked: " + member.toString()); + } + mMember = member; + mHookInfo = hookInfo; + mDexDirPath = dexDirPath; + if (appClassLoader == null + || appClassLoader.getClass().getName().equals("java.lang.BootClassLoader")) { + mAppClassLoader = this.getClass().getClassLoader(); + } else { + mAppClassLoader = appClassLoader; + } + + mDexMaker = new DexMaker(); + // Generate a Hooker class. + String className = getClassName(mMember); + String dexName = className + ".jar"; + + HookWrapper.HookEntity hookEntity = null; + //try load cache first + try { + ClassLoader loader = mDexMaker.loadClassDirect(mAppClassLoader, new File(mDexDirPath), dexName); + if (loader != null) { + hookEntity = loadHookerClass(loader, className); + } + } catch (Throwable throwable) {} + + //do generate + if (hookEntity == null) { + hookEntity = doMake(className, dexName); + } + SandHook.hook(hookEntity); + } + + private HookWrapper.HookEntity doMake(String className, String dexName) throws Exception { + mHookerTypeId = TypeId.get(CLASS_DESC_PREFIX + className + ";"); + mDexMaker.declare(mHookerTypeId, className + ".generated", Modifier.PUBLIC, TypeId.OBJECT); + generateFields(); + generateHookMethod(); + generateBackupMethod(); + + ClassLoader loader; + if (TextUtils.isEmpty(mDexDirPath)) { + throw new IllegalArgumentException("dexDirPath should not be empty!!!"); + } + // Create the dex file and load it. + loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(mDexDirPath), dexName); + return loadHookerClass(loader, className); + } + + private HookWrapper.HookEntity loadHookerClass(ClassLoader loader, String className) throws Exception { + mHookClass = loader.loadClass(className); + // Execute our newly-generated code in-process. + mHookMethod = mHookClass.getMethod(METHOD_NAME_HOOK, mActualParameterTypes); + mBackupMethod = mHookClass.getMethod(METHOD_NAME_BACKUP); + setup(mHookClass); + return new HookWrapper.HookEntity(mMember, mHookMethod, mBackupMethod, false); + } + + private void setup(Class mHookClass) { + XposedHelpers.setStaticObjectField(mHookClass, FIELD_NAME_METHOD, mMember); + XposedHelpers.setStaticObjectField(mHookClass, FIELD_NAME_BACKUP_METHOD, mBackupMethod); + XposedHelpers.setStaticObjectField(mHookClass, FIELD_NAME_HOOK_INFO, mHookInfo); + } + + private String getClassName(Member originMethod) { + return CLASS_NAME_PREFIX + "_" + MD5(originMethod.toString()); + } + + public Method getHookMethod() { + return mHookMethod; + } + + public Method getBackupMethod() { + return mBackupMethod; + } + + public Method getCallBackupMethod() { + return mBackupMethod; + } + + public Class getHookClass() { + return mHookClass; + } + + private void generateFields() { + mHookInfoFieldId = mHookerTypeId.getField(hookInfoTypeId, FIELD_NAME_HOOK_INFO); + mMethodFieldId = mHookerTypeId.getField(memberTypeId, FIELD_NAME_METHOD); + mBackupMethodFieldId = mHookerTypeId.getField(methodTypeId, FIELD_NAME_BACKUP_METHOD); + mDexMaker.declare(mHookInfoFieldId, Modifier.STATIC, null); + mDexMaker.declare(mMethodFieldId, Modifier.STATIC, null); + mDexMaker.declare(mBackupMethodFieldId, Modifier.STATIC, null); + } + + private void generateBackupMethod() { + mBackupMethodId = mHookerTypeId.getMethod(TypeId.VOID, METHOD_NAME_BACKUP); + Code code = mDexMaker.declare(mBackupMethodId, Modifier.PUBLIC | Modifier.STATIC); + code.returnVoid(); + } + + private void generateHookMethod() { + mHookMethodId = mHookerTypeId.getMethod(mReturnTypeId, METHOD_NAME_HOOK, mParameterTypeIds); + mSandHookBridgeMethodId = TypeId.get(HookStubManager.class).getMethod(TypeId.get(Object.class), "hookBridge", memberTypeId, TypeId.get(Object.class), TypeId.get(Object[].class)); + + Code code = mDexMaker.declare(mHookMethodId, Modifier.PUBLIC | Modifier.STATIC); + + Local method = code.newLocal(memberTypeId); + // Local backupMethod = code.newLocal(methodTypeId); + Local thisObject = code.newLocal(TypeId.OBJECT); + Local args = code.newLocal(objArrayTypeId); + Local actualParamSize = code.newLocal(TypeId.INT); + Local argIndex = code.newLocal(TypeId.INT); + Local resultObj = code.newLocal(TypeId.OBJECT); + + Local[] allArgsLocals = createParameterLocals(code); + Map resultLocals = createResultLocals(code); + + + code.sget(mMethodFieldId, method); + code.loadConstant(args, null); + code.loadConstant(argIndex, 0); +// code.sget(mBackupMethodFieldId, backupMethod); + int paramsSize = mParameterTypeIds.length; + int offset = 0; + // thisObject + if (mIsStatic) { + // thisObject = null + code.loadConstant(thisObject, null); + } else { + // thisObject = args[0] + offset = 1; + code.move(thisObject, allArgsLocals[0]); + } + + // actual args (exclude thisObject if this is not a static method) + code.loadConstant(actualParamSize, paramsSize - offset); + code.newArray(args, actualParamSize); + for (int i = offset; i < paramsSize; i++) { + Local parameter = allArgsLocals[i]; + // save parameter to resultObj as Object + autoBoxIfNecessary(code, resultObj, parameter); + code.loadConstant(argIndex, i - offset); + // save Object to args + code.aput(args, argIndex, resultObj); + } + + if (mReturnTypeId.equals(TypeId.VOID)) { + code.invokeStatic(mSandHookBridgeMethodId, null, method, thisObject, args); + code.returnVoid(); + } else { + code.invokeStatic(mSandHookBridgeMethodId, resultObj, method, thisObject, args); + TypeId objTypeId = getObjTypeIdIfPrimitive(mReturnTypeId); + Local matchObjLocal = resultLocals.get(objTypeId); + code.cast(matchObjLocal, resultObj); + // have to use matching typed Object(Integer, Double ...) to do unboxing + Local toReturn = resultLocals.get(mReturnTypeId); + autoUnboxIfNecessary(code, toReturn, matchObjLocal, resultLocals, true); + code.returnValue(toReturn); + } + + } + + private Local[] createParameterLocals(Code code) { + Local[] paramLocals = new Local[mParameterTypeIds.length]; + for (int i = 0; i < mParameterTypeIds.length; i++) { + paramLocals[i] = code.getParameter(i, mParameterTypeIds[i]); + } + return paramLocals; + } +} diff --git a/sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/SandHookXposedBridge.java b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/SandHookXposedBridge.java new file mode 100644 index 000000000..2d1cac2ee --- /dev/null +++ b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/methodgen/SandHookXposedBridge.java @@ -0,0 +1,138 @@ +package com.swift.sandhook.xposedcompat.methodgen; + +import android.os.Trace; + +import com.swift.sandhook.SandHook; +import com.swift.sandhook.wrapper.HookWrapper; +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; +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.atomic.AtomicBoolean; + +import de.robv.android.xposed.XposedBridge; + +public final class SandHookXposedBridge { + + private static final HashMap hookedInfo = new HashMap<>(); + private static HookMaker hookMaker = XposedCompat.useNewDexMaker ? new HookerDexMakerNew() : new HookerDexMaker(); + private static final AtomicBoolean dexPathInited = new AtomicBoolean(false); + private static File dexDir; + + public static Map entityMap = new HashMap<>(); + + public static void onForkPost() { + dexPathInited.set(false); + } + + public static synchronized void hookMethod(Member hookMethod, XposedBridge.AdditionalHookInfo additionalHookInfo) { + + if (!checkMember(hookMethod)) { + return; + } + + if (hookedInfo.containsKey(hookMethod) || entityMap.containsKey(hookMethod)) { + DexLog.w("already hook method:" + hookMethod.toString()); + return; + } + + try { + if (dexPathInited.compareAndSet(false, true)) { + try { + String fixedAppDataDir = XposedCompat.cacheDir.getAbsolutePath(); + dexDir = new File(fixedAppDataDir, "/sandxposed/"); + if (!dexDir.exists()) + dexDir.mkdirs(); + } catch (Throwable throwable) { + DexLog.e("error when init dex path", throwable); + } + } + Trace.beginSection("SandHook-Xposed"); + long timeStart = System.currentTimeMillis(); + HookMethodEntity stub = null; + if (XposedCompat.useInternalStub) { + stub = HookStubManager.getHookMethodEntity(hookMethod); + } + if (stub != null) { + SandHook.hook(new HookWrapper.HookEntity(hookMethod, stub.hook, stub.backup, false)); + entityMap.put(hookMethod, stub); + } else { + hookMaker.start(hookMethod, additionalHookInfo, + XposedCompat.classLoader, 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")); + Trace.endSection(); + } catch (Exception e) { + DexLog.e("error occur when hook method <" + hookMethod.toString() + ">", e); + } + } + + 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) { + return true; + } else if (member instanceof Constructor) { + return true; + } else if (member.getDeclaringClass().isInterface()) { + DexLog.e("Cannot hook interfaces: " + member.toString()); + return false; + } else if (Modifier.isAbstract(member.getModifiers())) { + DexLog.e("Cannot hook abstract methods: " + member.toString()); + return false; + } else { + DexLog.e("Only methods and constructors can be hooked: " + member.toString()); + return false; + } + } + + 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); + } + } +} + + diff --git a/sandhook/src/main/java/com/swift/sandhook/xposedcompat/utils/ApplicationUtils.java b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/utils/ApplicationUtils.java new file mode 100644 index 000000000..205d7c1f4 --- /dev/null +++ b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/utils/ApplicationUtils.java @@ -0,0 +1,34 @@ +package com.swift.sandhook.xposedcompat.utils; + +import android.app.Application; + +import java.lang.reflect.Method; + +public class ApplicationUtils { + + private static Class classActivityThread; + private static Method currentApplicationMethod; + + static Application application; + + public static Application currentApplication() { + if (application != null) + return application; + if (currentApplicationMethod == null) { + try { + classActivityThread = Class.forName("android.app.ActivityThread"); + currentApplicationMethod = classActivityThread.getDeclaredMethod("currentApplication"); + } catch (Exception e) { + e.printStackTrace(); + } + } + if (currentApplicationMethod == null) + return null; + try { + application = (Application) currentApplicationMethod.invoke(null); + } catch (Exception e) { + } + return application; + } + +} diff --git a/sandhook/src/main/java/com/swift/sandhook/xposedcompat/utils/ClassLoaderUtils.java b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/utils/ClassLoaderUtils.java new file mode 100644 index 000000000..acab279ea --- /dev/null +++ b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/utils/ClassLoaderUtils.java @@ -0,0 +1,106 @@ +package com.swift.sandhook.xposedcompat.utils; + +import android.os.Build; +import android.util.ArrayMap; + +import com.swift.sandhook.xposedcompat.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 getAppClassLoader() { + List 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 mLoaderMap = (ArrayMap) 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 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; + } + +} diff --git a/sandhook/src/main/java/com/swift/sandhook/xposedcompat/utils/DexLog.java b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/utils/DexLog.java new file mode 100644 index 000000000..cda8f1938 --- /dev/null +++ b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/utils/DexLog.java @@ -0,0 +1,51 @@ +package com.swift.sandhook.xposedcompat.utils; + +import android.util.Log; + +import java.lang.reflect.Member; + + +public class DexLog { + + public static final String TAG = "SandXposed-dexmaker"; + + public static boolean DEBUG = true; + + public static int v(String s) { + return Log.v(TAG, s); + } + + public static int i(String s) { + return Log.i(TAG, s); + } + + public static int d(String s) { + return Log.d(TAG, s); + } + + public static void printMethodHookIn(Member member) { + if (DEBUG && member != null) { + Log.d("SandHook-Xposed", "method <" + member.toString() + "> hook in"); + } + } + + public static void printCallOriginError(Member member) { + if (member != null) { + Log.e("SandHook-Xposed", "method <" + member.toString() + "> call origin error!"); + } + } + + public static int w(String s) { + return Log.w(TAG, s); + } + + public static int e(String s) { + return Log.e(TAG, s); + } + + public static int e(String s, Throwable t) { + return Log.e(TAG, s, t); + } + + +} diff --git a/sandhook/src/main/java/com/swift/sandhook/xposedcompat/utils/DexMakerUtils.java b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/utils/DexMakerUtils.java new file mode 100644 index 000000000..909e59acc --- /dev/null +++ b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/utils/DexMakerUtils.java @@ -0,0 +1,270 @@ +package com.swift.sandhook.xposedcompat.utils; +import external.com.android.dx.Code; +import external.com.android.dx.Local; +import external.com.android.dx.TypeId; +import com.android.dx.rop.code.Insn; +import com.android.dx.rop.code.PlainInsn; +import com.android.dx.rop.code.RegisterSpec; +import com.android.dx.rop.code.RegisterSpecList; +import com.android.dx.rop.code.Rops; +import com.android.dx.rop.code.SourcePosition; +import com.android.dx.rop.type.Type; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.HashMap; +import java.util.Map; + +public class DexMakerUtils { + + + private static volatile Method addInstMethod, specMethod; + + public static void autoBoxIfNecessary(Code code, Local target, Local source) { + String boxMethod = "valueOf"; + TypeId boxTypeId; + TypeId typeId = source.getType(); + if (typeId.equals(TypeId.BOOLEAN)) { + boxTypeId = TypeId.get(Boolean.class); + code.invokeStatic(boxTypeId.getMethod(boxTypeId, boxMethod, TypeId.BOOLEAN), target, source); + } else if (typeId.equals(TypeId.BYTE)) { + boxTypeId = TypeId.get(Byte.class); + code.invokeStatic(boxTypeId.getMethod(boxTypeId, boxMethod, TypeId.BYTE), target, source); + } else if (typeId.equals(TypeId.CHAR)) { + boxTypeId = TypeId.get(Character.class); + code.invokeStatic(boxTypeId.getMethod(boxTypeId, boxMethod, TypeId.CHAR), target, source); + } else if (typeId.equals(TypeId.DOUBLE)) { + boxTypeId = TypeId.get(Double.class); + code.invokeStatic(boxTypeId.getMethod(boxTypeId, boxMethod, TypeId.DOUBLE), target, source); + } else if (typeId.equals(TypeId.FLOAT)) { + boxTypeId = TypeId.get(Float.class); + code.invokeStatic(boxTypeId.getMethod(boxTypeId, boxMethod, TypeId.FLOAT), target, source); + } else if (typeId.equals(TypeId.INT)) { + boxTypeId = TypeId.get(Integer.class); + code.invokeStatic(boxTypeId.getMethod(boxTypeId, boxMethod, TypeId.INT), target, source); + } else if (typeId.equals(TypeId.LONG)) { + boxTypeId = TypeId.get(Long.class); + code.invokeStatic(boxTypeId.getMethod(boxTypeId, boxMethod, TypeId.LONG), target, source); + } else if (typeId.equals(TypeId.SHORT)) { + boxTypeId = TypeId.get(Short.class); + code.invokeStatic(boxTypeId.getMethod(boxTypeId, boxMethod, TypeId.SHORT), target, source); + } else if (typeId.equals(TypeId.VOID)) { + code.loadConstant(target, null); + } else { + code.move(target, source); + } + } + + public static void autoUnboxIfNecessary(Code code, Local target, Local source, + Map tmpLocals, boolean castObj) { + String unboxMethod; + TypeId typeId = target.getType(); + TypeId boxTypeId; + if (typeId.equals(TypeId.BOOLEAN)) { + unboxMethod = "booleanValue"; + boxTypeId = TypeId.get("Ljava/lang/Boolean;"); + Local boxTypedLocal = tmpLocals.get(boxTypeId); + code.cast(boxTypedLocal, source); + code.invokeVirtual(boxTypeId.getMethod(TypeId.BOOLEAN, unboxMethod), target, boxTypedLocal); + } else if (typeId.equals(TypeId.BYTE)) { + unboxMethod = "byteValue"; + boxTypeId = TypeId.get("Ljava/lang/Byte;"); + Local boxTypedLocal = tmpLocals.get(boxTypeId); + code.cast(boxTypedLocal, source); + code.invokeVirtual(boxTypeId.getMethod(TypeId.BYTE, unboxMethod), target, boxTypedLocal); + } else if (typeId.equals(TypeId.CHAR)) { + unboxMethod = "charValue"; + boxTypeId = TypeId.get("Ljava/lang/Character;"); + Local boxTypedLocal = tmpLocals.get(boxTypeId); + code.cast(boxTypedLocal, source); + code.invokeVirtual(boxTypeId.getMethod(TypeId.CHAR, unboxMethod), target, boxTypedLocal); + } else if (typeId.equals(TypeId.DOUBLE)) { + unboxMethod = "doubleValue"; + boxTypeId = TypeId.get("Ljava/lang/Double;"); + Local boxTypedLocal = tmpLocals.get(boxTypeId); + code.cast(boxTypedLocal, source); + code.invokeVirtual(boxTypeId.getMethod(TypeId.DOUBLE, unboxMethod), target, boxTypedLocal); + } else if (typeId.equals(TypeId.FLOAT)) { + unboxMethod = "floatValue"; + boxTypeId = TypeId.get("Ljava/lang/Float;"); + Local boxTypedLocal = tmpLocals.get(boxTypeId); + code.cast(boxTypedLocal, source); + code.invokeVirtual(boxTypeId.getMethod(TypeId.FLOAT, unboxMethod), target, boxTypedLocal); + } else if (typeId.equals(TypeId.INT)) { + unboxMethod = "intValue"; + boxTypeId = TypeId.get("Ljava/lang/Integer;"); + Local boxTypedLocal = tmpLocals.get(boxTypeId); + code.cast(boxTypedLocal, source); + code.invokeVirtual(boxTypeId.getMethod(TypeId.INT, unboxMethod), target, boxTypedLocal); + } else if (typeId.equals(TypeId.LONG)) { + unboxMethod = "longValue"; + boxTypeId = TypeId.get("Ljava/lang/Long;"); + Local boxTypedLocal = tmpLocals.get(boxTypeId); + code.cast(boxTypedLocal, source); + code.invokeVirtual(boxTypeId.getMethod(TypeId.LONG, unboxMethod), target, boxTypedLocal); + } else if (typeId.equals(TypeId.SHORT)) { + unboxMethod = "shortValue"; + boxTypeId = TypeId.get("Ljava/lang/Short;"); + Local boxTypedLocal = tmpLocals.get(boxTypeId); + code.cast(boxTypedLocal, source); + code.invokeVirtual(boxTypeId.getMethod(TypeId.SHORT, unboxMethod), target, boxTypedLocal); + } else if (typeId.equals(TypeId.VOID)) { + code.loadConstant(target, null); + } else if (castObj) { + code.cast(target, source); + } else { + code.move(target, source); + } + } + + public static Map createResultLocals(Code code) { + HashMap resultMap = new HashMap<>(); + Local booleanLocal = code.newLocal(TypeId.BOOLEAN); + Local byteLocal = code.newLocal(TypeId.BYTE); + Local charLocal = code.newLocal(TypeId.CHAR); + Local doubleLocal = code.newLocal(TypeId.DOUBLE); + Local floatLocal = code.newLocal(TypeId.FLOAT); + Local intLocal = code.newLocal(TypeId.INT); + Local longLocal = code.newLocal(TypeId.LONG); + Local shortLocal = code.newLocal(TypeId.SHORT); + Local voidLocal = code.newLocal(TypeId.VOID); + Local objectLocal = code.newLocal(TypeId.OBJECT); + + Local booleanObjLocal = code.newLocal(TypeId.get("Ljava/lang/Boolean;")); + Local byteObjLocal = code.newLocal(TypeId.get("Ljava/lang/Byte;")); + Local charObjLocal = code.newLocal(TypeId.get("Ljava/lang/Character;")); + Local doubleObjLocal = code.newLocal(TypeId.get("Ljava/lang/Double;")); + Local floatObjLocal = code.newLocal(TypeId.get("Ljava/lang/Float;")); + Local intObjLocal = code.newLocal(TypeId.get("Ljava/lang/Integer;")); + Local longObjLocal = code.newLocal(TypeId.get("Ljava/lang/Long;")); + Local shortObjLocal = code.newLocal(TypeId.get("Ljava/lang/Short;")); + Local voidObjLocal = code.newLocal(TypeId.get("Ljava/lang/Void;")); + + // backup need initialized locals + code.loadConstant(booleanLocal, false); + code.loadConstant(byteLocal, (byte) 0); + code.loadConstant(charLocal, '\0'); + code.loadConstant(doubleLocal,0.0); + code.loadConstant(floatLocal,0.0f); + code.loadConstant(intLocal, 0); + code.loadConstant(longLocal, 0L); + code.loadConstant(shortLocal, (short) 0); + code.loadConstant(voidLocal, null); + code.loadConstant(objectLocal, null); + // all to null + code.loadConstant(booleanObjLocal, null); + code.loadConstant(byteObjLocal, null); + code.loadConstant(charObjLocal, null); + code.loadConstant(doubleObjLocal, null); + code.loadConstant(floatObjLocal, null); + code.loadConstant(intObjLocal, null); + code.loadConstant(longObjLocal, null); + code.loadConstant(shortObjLocal, null); + code.loadConstant(voidObjLocal, null); + // package all + resultMap.put(TypeId.BOOLEAN, booleanLocal); + resultMap.put(TypeId.BYTE, byteLocal); + resultMap.put(TypeId.CHAR, charLocal); + resultMap.put(TypeId.DOUBLE, doubleLocal); + resultMap.put(TypeId.FLOAT, floatLocal); + resultMap.put(TypeId.INT, intLocal); + resultMap.put(TypeId.LONG, longLocal); + resultMap.put(TypeId.SHORT, shortLocal); + resultMap.put(TypeId.VOID, voidLocal); + resultMap.put(TypeId.OBJECT, objectLocal); + + resultMap.put(TypeId.get("Ljava/lang/Boolean;"), booleanObjLocal); + resultMap.put(TypeId.get("Ljava/lang/Byte;"), byteObjLocal); + resultMap.put(TypeId.get("Ljava/lang/Character;"), charObjLocal); + resultMap.put(TypeId.get("Ljava/lang/Double;"), doubleObjLocal); + resultMap.put(TypeId.get("Ljava/lang/Float;"), floatObjLocal); + resultMap.put(TypeId.get("Ljava/lang/Integer;"), intObjLocal); + resultMap.put(TypeId.get("Ljava/lang/Long;"), longObjLocal); + resultMap.put(TypeId.get("Ljava/lang/Short;"), shortObjLocal); + resultMap.put(TypeId.get("Ljava/lang/Void;"), voidObjLocal); + + return resultMap; + } + + public static TypeId getObjTypeIdIfPrimitive(TypeId typeId) { + if (typeId.equals(TypeId.BOOLEAN)) { + return TypeId.get("Ljava/lang/Boolean;"); + } else if (typeId.equals(TypeId.BYTE)) { + return TypeId.get("Ljava/lang/Byte;"); + } else if (typeId.equals(TypeId.CHAR)) { + return TypeId.get("Ljava/lang/Character;"); + } else if (typeId.equals(TypeId.DOUBLE)) { + return TypeId.get("Ljava/lang/Double;"); + } else if (typeId.equals(TypeId.FLOAT)) { + return TypeId.get("Ljava/lang/Float;"); + } else if (typeId.equals(TypeId.INT)) { + return TypeId.get("Ljava/lang/Integer;"); + } else if (typeId.equals(TypeId.LONG)) { + return TypeId.get("Ljava/lang/Long;"); + } else if (typeId.equals(TypeId.SHORT)) { + return TypeId.get("Ljava/lang/Short;"); + } else if (typeId.equals(TypeId.VOID)) { + return TypeId.get("Ljava/lang/Void;"); + } else { + return typeId; + } + } + + public static void returnRightValue(Code code, Class returnType, Map resultLocals) { + String unboxMethod; + TypeId boxTypeId; + code.returnValue(resultLocals.get(returnType)); + } + + public static void moveException(Code code, Local result) { + addInstruction(code, new PlainInsn(Rops.opMoveException(Type.THROWABLE), + SourcePosition.NO_INFO, spec(result), RegisterSpecList.EMPTY)); + } + + public static void addInstruction(Code code, Insn insn) { + if (addInstMethod == null) { + try { + addInstMethod = Code.class.getDeclaredMethod("addInstruction", Insn.class); + addInstMethod.setAccessible(true); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } + } + try { + addInstMethod.invoke(code, insn); + } catch (IllegalAccessException | InvocationTargetException e) { + e.printStackTrace(); + } + } + + public static RegisterSpec spec(Local result) { + if (specMethod == null) { + try { + specMethod = Local.class.getDeclaredMethod("spec"); + specMethod.setAccessible(true); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } + } + try { + return (RegisterSpec) specMethod.invoke(result); + } catch (IllegalAccessException | InvocationTargetException e) { + e.printStackTrace(); + return null; + } + } + + public static String MD5(String source) { + try { + MessageDigest messageDigest = MessageDigest.getInstance("MD5"); + messageDigest.update(source.getBytes()); + return new BigInteger(1, messageDigest.digest()).toString(32); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + return source; + } +} diff --git a/sandhook/src/main/java/com/swift/sandhook/xposedcompat/utils/DexUtils.java b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/utils/DexUtils.java new file mode 100644 index 000000000..55bd02f48 --- /dev/null +++ b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/utils/DexUtils.java @@ -0,0 +1,66 @@ +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); + } + +} \ No newline at end of file diff --git a/sandhook/src/main/java/com/swift/sandhook/xposedcompat/utils/FileUtils.java b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/utils/FileUtils.java new file mode 100644 index 000000000..c3c7acc17 --- /dev/null +++ b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/utils/FileUtils.java @@ -0,0 +1,77 @@ +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/"; + } +} diff --git a/sandhook/src/main/java/com/swift/sandhook/xposedcompat/utils/ProcessUtils.java b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/utils/ProcessUtils.java new file mode 100644 index 000000000..2adcf4f3c --- /dev/null +++ b/sandhook/src/main/java/com/swift/sandhook/xposedcompat/utils/ProcessUtils.java @@ -0,0 +1,64 @@ +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.text.TextUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by swift_gan on 2017/11/23. + */ + +public class ProcessUtils { + + private static volatile String processName = null; + + public static String getProcessName(Context context) { + if (!TextUtils.isEmpty(processName)) + return processName; + processName = doGetProcessName(context); + return processName; + } + + private static String doGetProcessName(Context context) { + ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + List 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 boolean isMainProcess(Context context) { + String processName = getProcessName(context); + String pkgName = context.getPackageName(); + if (!TextUtils.isEmpty(processName) && !TextUtils.equals(processName, pkgName)) { + return false; + } else { + return true; + } + } + + public static List 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 apps = packageManager.queryIntentActivities(mainIntent, 0); + return apps != null ? apps : new ArrayList(); + } +} diff --git a/sandhook/src/main/res/values/strings.xml b/sandhook/src/main/res/values/strings.xml new file mode 100644 index 000000000..63c2f7396 --- /dev/null +++ b/sandhook/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + xposedcompat + diff --git a/settings.gradle b/settings.gradle index d61f93174..0f7f768a5 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -include ':Core', ':Bridge', ':hiddenapistubs', ':dexmaker', ':dalvikdx' \ No newline at end of file +include ':Core', ':Bridge', ':hiddenapistubs', ':dexmaker', ':dalvikdx', ':sandhook', ':xposedapi' \ No newline at end of file diff --git a/xposedapi/.gitignore b/xposedapi/.gitignore new file mode 100644 index 000000000..796b96d1c --- /dev/null +++ b/xposedapi/.gitignore @@ -0,0 +1 @@ +/build diff --git a/xposedapi/build.gradle b/xposedapi/build.gradle new file mode 100644 index 000000000..dd45e60cd --- /dev/null +++ b/xposedapi/build.gradle @@ -0,0 +1,8 @@ +apply plugin: 'java-library' + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) +} + +sourceCompatibility = "1.7" +targetCompatibility = "1.7" diff --git a/xposedapi/src/main/java/de/robv/android/xposed/XC_MethodHook.java b/xposedapi/src/main/java/de/robv/android/xposed/XC_MethodHook.java new file mode 100644 index 000000000..068616abb --- /dev/null +++ b/xposedapi/src/main/java/de/robv/android/xposed/XC_MethodHook.java @@ -0,0 +1,168 @@ +package de.robv.android.xposed; + +import java.lang.reflect.Member; + +import de.robv.android.xposed.callbacks.IXUnhook; +import de.robv.android.xposed.callbacks.XCallback; + +/** + * Callback class for method hooks. + * + *

Usually, anonymous subclasses of this class are created which override + * {@link #beforeHookedMethod} and/or {@link #afterHookedMethod}. + */ +public abstract class XC_MethodHook extends XCallback { + /** + * Creates a new callback with default priority. + */ + @SuppressWarnings("deprecation") + public XC_MethodHook() { + super(); + } + + /** + * Creates a new callback with a specific priority. + * + *

Note that {@link #afterHookedMethod} will be called in reversed order, i.e. + * the callback with the highest priority will be called last. This way, the callback has the + * final control over the return value. {@link #beforeHookedMethod} is called as usual, i.e. + * highest priority first. + * + * @param priority See {@link XCallback#priority}. + */ + public XC_MethodHook(int priority) { + super(priority); + } + + /** + * Called before the invocation of the method. + * + *

You can use {@link MethodHookParam#setResult} and {@link MethodHookParam#setThrowable} + * to prevent the original method from being called. + * + *

Note that implementations shouldn't call {@code super(param)}, it's not necessary. + * + * @param param Information about the method call. + * @throws Throwable Everything the callback throws is caught and logged. + */ + protected void beforeHookedMethod(MethodHookParam param) throws Throwable {} + + public void callBeforeHookedMethod(MethodHookParam param) throws Throwable { + beforeHookedMethod(param); + } + + /** + * Called after the invocation of the method. + * + *

You can use {@link MethodHookParam#setResult} and {@link MethodHookParam#setThrowable} + * to modify the return value of the original method. + * + *

Note that implementations shouldn't call {@code super(param)}, it's not necessary. + * + * @param param Information about the method call. + * @throws Throwable Everything the callback throws is caught and logged. + */ + protected void afterHookedMethod(MethodHookParam param) throws Throwable {} + + public void callAfterHookedMethod(MethodHookParam param) throws Throwable { + afterHookedMethod(param); + } + + /** + * Wraps information about the method call and allows to influence it. + */ + public static final class MethodHookParam extends XCallback.Param { + /** @hide */ + @SuppressWarnings("deprecation") + public MethodHookParam() { + super(); + } + + /** The hooked method/constructor. */ + public Member method; + + /** The {@code this} reference for an instance method, or {@code null} for static methods. */ + public Object thisObject; + + /** Arguments to the method call. */ + public Object[] args; + + private Object result = null; + private Throwable throwable = null; + public boolean returnEarly = false; + + /** Returns the result of the method call. */ + public Object getResult() { + return result; + } + + /** + * Modify the result of the method call. + * + *

If called from {@link #beforeHookedMethod}, it prevents the call to the original method. + */ + public void setResult(Object result) { + this.result = result; + this.throwable = null; + this.returnEarly = true; + } + + /** Returns the {@link Throwable} thrown by the method, or {@code null}. */ + public Throwable getThrowable() { + return throwable; + } + + /** Returns true if an exception was thrown by the method. */ + public boolean hasThrowable() { + return throwable != null; + } + + /** + * Modify the exception thrown of the method call. + * + *

If called from {@link #beforeHookedMethod}, it prevents the call to the original method. + */ + public void setThrowable(Throwable throwable) { + this.throwable = throwable; + this.result = null; + this.returnEarly = true; + } + + /** Returns the result of the method call, or throws the Throwable caused by it. */ + public Object getResultOrThrowable() throws Throwable { + if (throwable != null) + throw throwable; + return result; + } + } + + /** + * An object with which the method/constructor can be unhooked. + */ + public class Unhook implements IXUnhook { + private final Member hookMethod; + + /*package*/ Unhook(Member hookMethod) { + this.hookMethod = hookMethod; + } + + /** + * Returns the method/constructor that has been hooked. + */ + public Member getHookedMethod() { + return hookMethod; + } + + @Override + public XC_MethodHook getCallback() { + return XC_MethodHook.this; + } + + @SuppressWarnings("deprecation") + @Override + public void unhook() { + XposedBridge.unhookMethod(hookMethod, XC_MethodHook.this); + } + + } +} diff --git a/xposedapi/src/main/java/de/robv/android/xposed/XposedBridge.java b/xposedapi/src/main/java/de/robv/android/xposed/XposedBridge.java new file mode 100644 index 000000000..6f6212cf8 --- /dev/null +++ b/xposedapi/src/main/java/de/robv/android/xposed/XposedBridge.java @@ -0,0 +1,65 @@ +package de.robv.android.xposed; + +import java.lang.reflect.Member; +import java.util.HashMap; +import java.util.Map; + +public class XposedBridge { + + public static boolean disableHooks = false; + + public static final Map> sHookedMethodCallbacks = new HashMap<>(); + + public synchronized static void log(String text) { + } + + /** + * Logs a stack trace to the Xposed error log. + * + *

DON'T FLOOD THE LOG!!! This is only meant for error logging. + * If you want to write information/debug messages, use logcat. + * + * @param t The Throwable object for the stack trace. + */ + public synchronized static void log(Throwable t) { + } + + public static void unhookMethod(Member hookMethod, XC_MethodHook callback) { + } + + public static final class CopyOnWriteSortedSet { + + @SuppressWarnings("UnusedReturnValue") + public synchronized boolean add(E e) { + return true; + } + + @SuppressWarnings("UnusedReturnValue") + public synchronized boolean remove(E e) { + return true; + } + + private int indexOf(Object o) { + return -1; + } + + public Object[] getSnapshot() { + return null; + } + + public synchronized void clear() { + } + } + + public static class AdditionalHookInfo { + public final CopyOnWriteSortedSet callbacks; + public final Class[] parameterTypes; + public final Class returnType; + + private AdditionalHookInfo(CopyOnWriteSortedSet callbacks, Class[] parameterTypes, Class returnType) { + this.callbacks = callbacks; + this.parameterTypes = parameterTypes; + this.returnType = returnType; + } + } +} diff --git a/xposedapi/src/main/java/de/robv/android/xposed/XposedHelpers.java b/xposedapi/src/main/java/de/robv/android/xposed/XposedHelpers.java new file mode 100644 index 000000000..8d31bb04b --- /dev/null +++ b/xposedapi/src/main/java/de/robv/android/xposed/XposedHelpers.java @@ -0,0 +1,11 @@ +package de.robv.android.xposed; + +public class XposedHelpers { + + public static Object getStaticObjectField(Class clazz, String fieldName) { + return null; + } + + public static void setStaticObjectField(Class clazz, String fieldName, Object value) {} + +} diff --git a/xposedapi/src/main/java/de/robv/android/xposed/callbacks/IXUnhook.java b/xposedapi/src/main/java/de/robv/android/xposed/callbacks/IXUnhook.java new file mode 100644 index 000000000..b3b4fd1cc --- /dev/null +++ b/xposedapi/src/main/java/de/robv/android/xposed/callbacks/IXUnhook.java @@ -0,0 +1,13 @@ +package de.robv.android.xposed.callbacks; + +public interface IXUnhook { + /** + * Returns the callback that has been registered. + */ + T getCallback(); + + /** + * Removes the callback. + */ + void unhook(); +} diff --git a/xposedapi/src/main/java/de/robv/android/xposed/callbacks/XCallback.java b/xposedapi/src/main/java/de/robv/android/xposed/callbacks/XCallback.java new file mode 100644 index 000000000..de9a64654 --- /dev/null +++ b/xposedapi/src/main/java/de/robv/android/xposed/callbacks/XCallback.java @@ -0,0 +1,118 @@ +package de.robv.android.xposed.callbacks; + + +import java.io.Serializable; + +import de.robv.android.xposed.XposedBridge.CopyOnWriteSortedSet; + +/** + * Base class for Xposed callbacks. + * + * This class only keeps a priority for ordering multiple callbacks. + * The actual (abstract) callback methods are added by subclasses. + */ +public abstract class XCallback implements Comparable { + /** + * Callback priority, higher number means earlier execution. + * + *

This is usually set to {@link #PRIORITY_DEFAULT}. However, in case a certain callback should + * be executed earlier or later a value between {@link #PRIORITY_HIGHEST} and {@link #PRIORITY_LOWEST} + * can be set instead. The values are just for orientation though, Xposed doesn't enforce any + * boundaries on the priority values. + */ + public final int priority; + + /** @deprecated This constructor can't be hidden for technical reasons. Nevertheless, don't use it! */ + @Deprecated + public XCallback() { + this.priority = PRIORITY_DEFAULT; + } + + /** @hide */ + public XCallback(int priority) { + this.priority = priority; + } + + /** + * Base class for Xposed callback parameters. + */ + public static abstract class Param { + /** @hide */ + public final Object[] callbacks; + private Object extra; + + /** @deprecated This constructor can't be hidden for technical reasons. Nevertheless, don't use it! */ + @Deprecated + protected Param() { + callbacks = null; + } + + /** @hide */ + protected Param(CopyOnWriteSortedSet callbacks) { + this.callbacks = callbacks.getSnapshot(); + } + + /** + * This can be used to store any data for the scope of the callback. + * + *

Use this instead of instance variables, as it has a clear reference to e.g. each + * separate call to a method, even when the same method is called recursively. + * + * @see #setObjectExtra + * @see #getObjectExtra + */ + public synchronized Object getExtra() { + return null; + } + + /** + * Returns an object stored with {@link #setObjectExtra}. + */ + public Object getObjectExtra(String key) { + return null; + } + public void setObjectExtra(String key, Object o) { + } + + private static class SerializeWrapper implements Serializable { + private static final long serialVersionUID = 1L; + private final Object object; + public SerializeWrapper(Object o) { + object = o; + } + } + } + + /** @hide */ + public static void callAll(Param param) { + + } + + /** @hide */ + protected void call(Param param) throws Throwable {} + + /** @hide */ + @Override + public int compareTo(XCallback other) { + if (this == other) + return 0; + + // order descending by priority + if (other.priority != this.priority) + return other.priority - this.priority; + // then randomly + else if (System.identityHashCode(this) < System.identityHashCode(other)) + return -1; + else + return 1; + } + + /** The default priority, see {@link #priority}. */ + public static final int PRIORITY_DEFAULT = 50; + + /** Execute this callback late, see {@link #priority}. */ + public static final int PRIORITY_LOWEST = -10000; + + /** Execute this callback early, see {@link #priority}. */ + public static final int PRIORITY_HIGHEST = 10000; +} diff --git a/xposedapi/src/main/java/de/robv/android/xposed/callbacks/package-info.java b/xposedapi/src/main/java/de/robv/android/xposed/callbacks/package-info.java new file mode 100644 index 000000000..3b00b7f50 --- /dev/null +++ b/xposedapi/src/main/java/de/robv/android/xposed/callbacks/package-info.java @@ -0,0 +1,9 @@ +/** + * Contains the base classes for callbacks. + * + *

For historical reasons, {@link de.robv.android.xposed.XC_MethodHook} and + * {@link de.robv.android.xposed.XC_MethodReplacement} are directly in the + * {@code de.robv.android.xposed} package. + */ +package de.robv.android.xposed.callbacks; +