环境搭建
- xposed环境
https://www.freebuf.com/articles/terminal/189021.html
XposedBridgeApi-82.jar:https://wws.lanzoui.com/b0263ugle 密码:God
帮助文档:https://github.com/rovo89/XposedBridge/wiki/Development-tutorial
如果是下载jar导入compileOnly ‘de.robv.android.xposed:api:82’、
compileOnly ‘de.robv.android.xposed:api:82:sources’要改成compileOnly files(‘lib/XposedBridgeApi-82.jar’)
Hook修改静态变量
public class Hook implements IXposedHookLoadPackage {@Overridepublic void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {Log.d("lyf","hook开始");// 过滤要hook的app包名if(loadPackageParam.packageName.equals("com.example.demo1")){// 找到要hook的类Class<?> clazz=XposedHelpers.findClass("com.example.demo1.MainActivity",loadPackageParam.classLoader);// 修改静态int值,把变量名为int1值改为999XposedHelpers.setStaticIntField(clazz,"int1",999);// 修改静态string值,把变量名为str1值改成XposedHelpers.setStaticObjectField(clazz,"str1","kkkkkkkkkkkkk");}Log.d("lyf","hook结束");}}
Hook函数
参数对应hook写法
| Java参数 | Hook写法 |
|---|---|
| String | String.class、”java.lang.String” |
| String[] | String[].class、”[[Ljava.lang.String;” |
| Map | Map.class、”java.util.Map” |
| ArrayList | Claa.forName(“java.util.ArrayList”) |
Class<?> clazz2=XposedHelpers.findClass("com.example.demo1.C1",loadPackageParam.classLoader);// hook构造函数,原函数参数类型是String对应String.classXposedHelpers.findAndHookConstructor(clazz2, String.class, new XC_MethodHook() {// 构造函数执行前@Overrideprotected void beforeHookedMethod(MethodHookParam param) throws Throwable {Log.d("lyf","hook构造函数开始");// 修改参数param.args[0]="修改后的构造函数参数";}// 构造函数执行后@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {Log.d("lyf","hook构造函数结束");}});// hook普通方法,静态、私有、普通hook方法一致,getS2:方法名XposedHelpers.findAndHookMethod(clazz2, "getS2", new XC_MethodHook() {@Overrideprotected void beforeHookedMethod(MethodHookParam param) throws Throwable {Log.d("lyf","hook普通方法开始");}@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {// 修改返回值param.setResult("修改普通方法返回值");Log.d("lyf","hook普通方法结束结束");}});
自定义类参数hook
// 自定义类参数hook方法1,com.example.demo1.C2:外部app的类Class clazz3=loadPackageParam.classLoader.loadClass("com.example.demo1.C2");// 方法2,底层调用方法1Class clazz4=XposedHelpers.findClass("com.example.demo1.C2",loadPackageParam.classLoader);// 方法3,底层调用方法1,必须指定classloader否则hook不成功Class clazz5=Class.forName("com.example.demo1.C2",false,loadPackageParam.classLoader);// 方法4,直接写全限定类名:com.example.demo1.C2
Hook替换函数
// hook替换函数XposedHelpers.findAndHookMethod(clazz2, "getS3", new XC_MethodReplacement() {// 替换后的函数@Overrideprotected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {Log.d("lyf","替换后函数输出");return "替换后函数输出";}});
Hook内部类
内部类:$连接,com.lyf.a类里有b类,com.lyf.a$b
匿名内部类:反编译看smali代码匿名内部类名字会成1、2之类的,com.lyf.a$1、com.lyf.a$2
主动调用
Class<?> clazz2=XposedHelpers.findClass("com.example.demo1.C1",loadPackageParam.classLoader);// 主动调用,实例方法// 根据clazz2创建对象,调用getS4方法String res= (String) XposedHelpers.callMethod(clazz2.newInstance(),"getS4");Log.d("lyf","主动调用"+res);// 静态方法用callStaticMethod
打印调用栈
Log.e(“lyf”,”调用栈”,new Throwable(“打印调用栈”));
Java反射
https://blog.csdn.net/qq_44715943/article/details/120587716
一般步骤:找到类-》找到字段或方法,设定访问权限-》修改字段或调用方法
获取方法
Class clazz6=Class.forName("com.example.demo1.C1",false,loadPackageParam.classLoader);// 根据名字找到方法,后面接参数Method refmethod=clazz6.getDeclaredMethod("getS5",String.class);// 设定访问权限refmethod.setAccessible(true);// 调用方法String res1= (String) refmethod.invoke(clazz6.newInstance(),"反射调用方法getS5");System.out.println("反射调用方法getS5返回值:"+res1);
获取属性
Class clazz6=Class.forName("com.example.demo1.C1",false,loadPackageParam.classLoader);// 根据名字获取属性Field reffield=clazz6.getDeclaredField("s2");Object obj=clazz6.newInstance();reffield.setAccessible(true);reffield.set(obj,"s233");System.out.println((String) reffield.get(obj));
遍历所有方法、属性、内部类、类
Class clazz6=Class.forName("com.example.demo1.C1",false,loadPackageParam.classLoader);// 遍历所有方法和字段System.out.println("###遍历所有方法开始###");// 获取所有方法Method[] me=clazz6.getDeclaredMethods();for (Method method : me) {System.out.println(method.getName());}System.out.println("###遍历所有方法结束###");System.out.println("###遍历所有字段开始###");// 获取所有属性Field[] fi=clazz6.getDeclaredFields();for (Field field : fi) {System.out.println(field.getName());}System.out.println("###遍历所有字段结束###");// 获取所有内部类Class[] cla=clazz6.getDeclaredClasses();// 遍历所有类XposedHelpers.findAndHookMethod(ClassLoader.class, "loadClass",String.class, new XC_MethodHook() {@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {// 获取返回值,得到类名Class clazz = (Class) param.getResult();Log.d("获取类:",clazz.getName());}});
hook类所有方法
构造函数不会被hook
Class clazz=loadPackageParam.classLoader.loadClass("com.example.demo1.C1");Method[] met=clazz.getDeclaredMethods();for (Method method : met) {// 根据方法对象hook类,不需要传参数XposedBridge.hookMethod(method, new XC_MethodHook() {@Overrideprotected void beforeHookedMethod(MethodHookParam param) throws Throwable {// 遍历打印参数类型if(param.args!=null){for (Object arg : param.args) {Log.d("打印参数:",arg.getClass().getName());}}// 打印方法名,打印越靠后执行越晚Log.d("打印方法名:",method.toString());}});}
Hook多dex
如果app有多个dex,默认的classloader可能会找不到类,需要切换dex
XposedHelpers.findAndHookMethod(Application.class, "attach", Context.class, new XC_MethodHook() {@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {ClassLoader c1=((Context)param.args[0]).getClassLoader();Class hookClass=null;try{// 根据类加载器寻找类hookClass=c1.loadClass("com.example.demo1.C1");}catch (Exception e){Log.e("lyf","寻找com.example.demo1.C1错误",e);}Log.i("lyf","寻找com.example.demo1.C1成功");XposedHelpers.findAndHookMethod(hookClass, "getS2", new XC_MethodHook() {@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {Log.d("lyf","hook getS2得到返回值:"+param.getResult().toString());}});}});
