Commit 5725154d authored by swift_gan's avatar swift_gan

add plugin hooker sample

parent ca8d08d1
...@@ -82,6 +82,8 @@ public class MainActivity extends AppCompatActivity { ...@@ -82,6 +82,8 @@ public class MainActivity extends AppCompatActivity {
}).start(); }).start();
inter.dosth(); inter.dosth();
testPluginHook(str);
} }
public static Field getField(Class topClass, String fieldName) throws NoSuchFieldException { public static Field getField(Class topClass, String fieldName) throws NoSuchFieldException {
...@@ -120,6 +122,11 @@ public class MainActivity extends AppCompatActivity { ...@@ -120,6 +122,11 @@ public class MainActivity extends AppCompatActivity {
return a + b; return a + b;
} }
public int testPluginHook(TestClass testClass) {
Log.e("MainActivity", "call testPluginHook origin");
return testClass.a;
}
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will // Handle action bar item clicks here. The action bar will
......
...@@ -32,7 +32,8 @@ public class MyApp extends Application { ...@@ -32,7 +32,8 @@ public class MyApp extends Application {
DexClassLoader dexClassLoader = new DexClassLoader("/sdcard/hookers-debug.apk", DexClassLoader dexClassLoader = new DexClassLoader("/sdcard/hookers-debug.apk",
getCacheDir().getAbsolutePath(), null, classLoader); getCacheDir().getAbsolutePath(), null, classLoader);
Class absHookerClass = Class.forName("com.swift.sandhook.hookers.AbsHooker", true, dexClassLoader); Class absHookerClass = Class.forName("com.swift.sandhook.hookers.AbsHooker", true, dexClassLoader);
SandHook.addHookClass(absHookerClass); Class pluginHookerClass = Class.forName("com.swift.sandhook.hookers.PluginHooker", true, dexClassLoader);
SandHook.addHookClass(getClassLoader(), absHookerClass, pluginHookerClass);
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
e.printStackTrace(); e.printStackTrace();
} catch (HookErrorException e) { } catch (HookErrorException e) {
......
package com.swift.sandhook.hookers;
import android.util.Log;
import com.swift.sandhook.annotation.HookMethod;
import com.swift.sandhook.annotation.HookMethodBackup;
import com.swift.sandhook.annotation.HookReflectClass;
import com.swift.sandhook.annotation.MethodReflectParams;
import java.lang.reflect.Method;
@HookReflectClass("com.swift.sandhook.MainActivity")
public class PluginHooker {
@HookMethodBackup("testPluginHook")
@MethodReflectParams("com.swift.sandhook.test.TestClass")
static Method backup;
@HookMethod("testPluginHook")
@MethodReflectParams("com.swift.sandhook.test.TestClass")
public static int testPluginHook(Object thiz, Object test) {
Log.e("PluginHooker", "testPluginHook be hooked");
return testPluginHookBackup(thiz, test);
}
@HookMethodBackup("testPluginHook")
@MethodReflectParams("com.swift.sandhook.test.TestClass")
public static int testPluginHookBackup(Object thiz, Object test) {
return testPluginHookBackup(thiz, test);
}
}
...@@ -37,8 +37,8 @@ public class HookWrapper { ...@@ -37,8 +37,8 @@ public class HookWrapper {
Class targetHookClass = getTargetHookClass(classLoader, clazz); Class targetHookClass = getTargetHookClass(classLoader, clazz);
if (targetHookClass == null) if (targetHookClass == null)
throw new HookErrorException("error hook wrapper class :" + clazz.getName()); throw new HookErrorException("error hook wrapper class :" + clazz.getName());
Map<Member,HookEntity> hookEntityMap = getHookMethods(targetHookClass, clazz); Map<Member,HookEntity> hookEntityMap = getHookMethods(classLoader, targetHookClass, clazz);
fillBackupMethod(clazz, hookEntityMap); fillBackupMethod(classLoader, clazz, hookEntityMap);
for (HookEntity entity:hookEntityMap.values()) { for (HookEntity entity:hookEntityMap.values()) {
if (entity.target != null && entity.hook != null) { if (entity.target != null && entity.hook != null) {
SandHook.hook(entity.target, entity.hook, entity.backup); SandHook.hook(entity.target, entity.hook, entity.backup);
...@@ -47,7 +47,7 @@ public class HookWrapper { ...@@ -47,7 +47,7 @@ public class HookWrapper {
} }
} }
private static void fillBackupMethod(Class<?> clazz, Map<Member, HookEntity> hookEntityMap) { private static void fillBackupMethod(ClassLoader classLoader,Class<?> clazz, Map<Member, HookEntity> hookEntityMap) {
Field[] fields = clazz.getDeclaredFields(); Field[] fields = clazz.getDeclaredFields();
if (fields == null || fields.length == 0) if (fields == null || fields.length == 0)
return; return;
...@@ -62,7 +62,7 @@ public class HookWrapper { ...@@ -62,7 +62,7 @@ public class HookWrapper {
if (hookMethodBackup == null) if (hookMethodBackup == null)
continue; continue;
for (HookEntity hookEntity:hookEntityMap.values()) { for (HookEntity hookEntity:hookEntityMap.values()) {
if (TextUtils.equals(hookEntity.target.getName(), hookMethodBackup.value()) && hookEntity.backup != null && samePars(field, hookEntity.pars)) { if (TextUtils.equals(hookEntity.target.getName(), hookMethodBackup.value()) && hookEntity.backup != null && samePars(classLoader, field, hookEntity.pars)) {
field.setAccessible(true); field.setAccessible(true);
try { try {
field.set(null, hookEntity.backup); field.set(null, hookEntity.backup);
...@@ -74,7 +74,7 @@ public class HookWrapper { ...@@ -74,7 +74,7 @@ public class HookWrapper {
} }
} }
private static Map<Member, HookEntity> getHookMethods(Class targetHookClass, Class<?> hookWrapperClass) throws HookErrorException { private static Map<Member, HookEntity> getHookMethods(ClassLoader classLoader, Class targetHookClass, Class<?> hookWrapperClass) throws HookErrorException {
Map<Member,HookEntity> hookEntityMap = new HashMap<>(); Map<Member,HookEntity> hookEntityMap = new HashMap<>();
Method[] methods = hookWrapperClass.getDeclaredMethods(); Method[] methods = hookWrapperClass.getDeclaredMethods();
if (methods == null && methods.length == 0) if (methods == null && methods.length == 0)
...@@ -87,7 +87,7 @@ public class HookWrapper { ...@@ -87,7 +87,7 @@ public class HookWrapper {
Class[] pars; Class[] pars;
if (hookMethodAnno != null) { if (hookMethodAnno != null) {
methodName = hookMethodAnno.value(); methodName = hookMethodAnno.value();
pars = parseMethodPars(method); pars = parseMethodPars(classLoader, method);
try { try {
if (methodName.equals("<init>")) { if (methodName.equals("<init>")) {
foundMethod = targetHookClass.getConstructor(pars); foundMethod = targetHookClass.getConstructor(pars);
...@@ -106,7 +106,7 @@ public class HookWrapper { ...@@ -106,7 +106,7 @@ public class HookWrapper {
entity.hook = method; entity.hook = method;
} else if (hookMethodBackupAnno != null) { } else if (hookMethodBackupAnno != null) {
methodName = hookMethodBackupAnno.value(); methodName = hookMethodBackupAnno.value();
pars = parseMethodPars(method); pars = parseMethodPars(classLoader, method);
try { try {
if (methodName.equals("<init>")) { if (methodName.equals("<init>")) {
foundMethod = targetHookClass.getConstructor(pars); foundMethod = targetHookClass.getConstructor(pars);
...@@ -131,7 +131,7 @@ public class HookWrapper { ...@@ -131,7 +131,7 @@ public class HookWrapper {
return hookEntityMap; return hookEntityMap;
} }
private static Class[] parseMethodPars(Method method) throws HookErrorException { private static Class[] parseMethodPars(ClassLoader classLoader, Method method) throws HookErrorException {
MethodParams methodParams = method.getAnnotation(MethodParams.class); MethodParams methodParams = method.getAnnotation(MethodParams.class);
MethodReflectParams methodReflectParams = method.getAnnotation(MethodReflectParams.class); MethodReflectParams methodReflectParams = method.getAnnotation(MethodReflectParams.class);
if (methodParams != null) { if (methodParams != null) {
...@@ -142,7 +142,11 @@ public class HookWrapper { ...@@ -142,7 +142,11 @@ public class HookWrapper {
Class[] pars = new Class[methodReflectParams.value().length]; Class[] pars = new Class[methodReflectParams.value().length];
for (int i = 0;i < methodReflectParams.value().length; i++) { for (int i = 0;i < methodReflectParams.value().length; i++) {
try { try {
pars[i] = Class.forName(methodReflectParams.value()[i]); if (classLoader == null) {
pars[i] = Class.forName(methodReflectParams.value()[i]);
} else {
pars[i] = Class.forName(methodReflectParams.value()[i], true, classLoader);
}
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
throw new HookErrorException("hook method pars error: " + method.getName(), e); throw new HookErrorException("hook method pars error: " + method.getName(), e);
} }
...@@ -153,7 +157,7 @@ public class HookWrapper { ...@@ -153,7 +157,7 @@ public class HookWrapper {
} }
} }
private static Class[] parseMethodPars(Field field) throws HookErrorException { private static Class[] parseMethodPars(ClassLoader classLoader, Field field) throws HookErrorException {
MethodParams methodParams = field.getAnnotation(MethodParams.class); MethodParams methodParams = field.getAnnotation(MethodParams.class);
MethodReflectParams methodReflectParams = field.getAnnotation(MethodReflectParams.class); MethodReflectParams methodReflectParams = field.getAnnotation(MethodReflectParams.class);
if (methodParams != null) { if (methodParams != null) {
...@@ -164,7 +168,11 @@ public class HookWrapper { ...@@ -164,7 +168,11 @@ public class HookWrapper {
Class[] pars = new Class[methodReflectParams.value().length]; Class[] pars = new Class[methodReflectParams.value().length];
for (int i = 0;i < methodReflectParams.value().length; i++) { for (int i = 0;i < methodReflectParams.value().length; i++) {
try { try {
pars[i] = Class.forName(methodReflectParams.value()[i]); if (classLoader == null) {
pars[i] = Class.forName(methodReflectParams.value()[i]);
} else {
pars[i] = Class.forName(methodReflectParams.value()[i], true, classLoader);
}
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
throw new HookErrorException("hook method pars error: " + field.getName(), e); throw new HookErrorException("hook method pars error: " + field.getName(), e);
} }
...@@ -176,9 +184,9 @@ public class HookWrapper { ...@@ -176,9 +184,9 @@ public class HookWrapper {
} }
private static boolean samePars(Field field, Class[] par) { private static boolean samePars(ClassLoader classLoader, Field field, Class[] par) {
try { try {
Class[] parsOnField = parseMethodPars(field); Class[] parsOnField = parseMethodPars(classLoader, field);
if (par == null) if (par == null)
par = new Class[0]; par = new Class[0];
if (parsOnField == null) if (parsOnField == null)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment