环境搭建

  1. 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修改静态变量

  1. public class Hook implements IXposedHookLoadPackage {
  2. @Override
  3. public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
  4. Log.d("lyf","hook开始");
  5. // 过滤要hook的app包名
  6. if(loadPackageParam.packageName.equals("com.example.demo1")){
  7. // 找到要hook的类
  8. Class<?> clazz=XposedHelpers.findClass("com.example.demo1.MainActivity",loadPackageParam.classLoader);
  9. // 修改静态int值,把变量名为int1值改为999
  10. XposedHelpers.setStaticIntField(clazz,"int1",999);
  11. // 修改静态string值,把变量名为str1值改成
  12. XposedHelpers.setStaticObjectField(clazz,"str1","kkkkkkkkkkkkk");
  13. }
  14. Log.d("lyf","hook结束");
  15. }
  16. }

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”)
  1. Class<?> clazz2=XposedHelpers.findClass("com.example.demo1.C1",loadPackageParam.classLoader);
  2. // hook构造函数,原函数参数类型是String对应String.class
  3. XposedHelpers.findAndHookConstructor(clazz2, String.class, new XC_MethodHook() {
  4. // 构造函数执行前
  5. @Override
  6. protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
  7. Log.d("lyf","hook构造函数开始");
  8. // 修改参数
  9. param.args[0]="修改后的构造函数参数";
  10. }
  11. // 构造函数执行后
  12. @Override
  13. protected void afterHookedMethod(MethodHookParam param) throws Throwable {
  14. Log.d("lyf","hook构造函数结束");
  15. }
  16. });
  17. // hook普通方法,静态、私有、普通hook方法一致,getS2:方法名
  18. XposedHelpers.findAndHookMethod(clazz2, "getS2", new XC_MethodHook() {
  19. @Override
  20. protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
  21. Log.d("lyf","hook普通方法开始");
  22. }
  23. @Override
  24. protected void afterHookedMethod(MethodHookParam param) throws Throwable {
  25. // 修改返回值
  26. param.setResult("修改普通方法返回值");
  27. Log.d("lyf","hook普通方法结束结束");
  28. }
  29. });

自定义类参数hook

  1. // 自定义类参数hook方法1,com.example.demo1.C2:外部app的类
  2. Class clazz3=loadPackageParam.classLoader.loadClass("com.example.demo1.C2");
  3. // 方法2,底层调用方法1
  4. Class clazz4=XposedHelpers.findClass("com.example.demo1.C2",loadPackageParam.classLoader);
  5. // 方法3,底层调用方法1,必须指定classloader否则hook不成功
  6. Class clazz5=Class.forName("com.example.demo1.C2",false,loadPackageParam.classLoader);
  7. // 方法4,直接写全限定类名:com.example.demo1.C2

Hook替换函数

  1. // hook替换函数
  2. XposedHelpers.findAndHookMethod(clazz2, "getS3", new XC_MethodReplacement() {
  3. // 替换后的函数
  4. @Override
  5. protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
  6. Log.d("lyf","替换后函数输出");
  7. return "替换后函数输出";
  8. }
  9. });

Hook内部类

内部类:$连接,com.lyf.a类里有b类,com.lyf.a$b
匿名内部类:反编译看smali代码匿名内部类名字会成1、2之类的,com.lyf.a$1、com.lyf.a$2

主动调用

  1. Class<?> clazz2=XposedHelpers.findClass("com.example.demo1.C1",loadPackageParam.classLoader);
  2. // 主动调用,实例方法
  3. // 根据clazz2创建对象,调用getS4方法
  4. String res= (String) XposedHelpers.callMethod(clazz2.newInstance(),"getS4");
  5. Log.d("lyf","主动调用"+res);
  6. // 静态方法用callStaticMethod

打印调用栈

Log.e(“lyf”,”调用栈”,new Throwable(“打印调用栈”));

Java反射

https://blog.csdn.net/qq_44715943/article/details/120587716
一般步骤:找到类-》找到字段或方法,设定访问权限-》修改字段或调用方法

  1. 获取方法

    1. Class clazz6=Class.forName("com.example.demo1.C1",false,loadPackageParam.classLoader);
    2. // 根据名字找到方法,后面接参数
    3. Method refmethod=clazz6.getDeclaredMethod("getS5",String.class);
    4. // 设定访问权限
    5. refmethod.setAccessible(true);
    6. // 调用方法
    7. String res1= (String) refmethod.invoke(clazz6.newInstance(),"反射调用方法getS5");
    8. System.out.println("反射调用方法getS5返回值:"+res1);
  2. 获取属性

    1. Class clazz6=Class.forName("com.example.demo1.C1",false,loadPackageParam.classLoader);
    2. // 根据名字获取属性
    3. Field reffield=clazz6.getDeclaredField("s2");
    4. Object obj=clazz6.newInstance();
    5. reffield.setAccessible(true);
    6. reffield.set(obj,"s233");
    7. System.out.println((String) reffield.get(obj));

    遍历所有方法、属性、内部类、类

    1. Class clazz6=Class.forName("com.example.demo1.C1",false,loadPackageParam.classLoader);
    2. // 遍历所有方法和字段
    3. System.out.println("###遍历所有方法开始###");
    4. // 获取所有方法
    5. Method[] me=clazz6.getDeclaredMethods();
    6. for (Method method : me) {
    7. System.out.println(method.getName());
    8. }
    9. System.out.println("###遍历所有方法结束###");
    10. System.out.println("###遍历所有字段开始###");
    11. // 获取所有属性
    12. Field[] fi=clazz6.getDeclaredFields();
    13. for (Field field : fi) {
    14. System.out.println(field.getName());
    15. }
    16. System.out.println("###遍历所有字段结束###");
    17. // 获取所有内部类
    18. Class[] cla=clazz6.getDeclaredClasses();
    19. // 遍历所有类
    20. XposedHelpers.findAndHookMethod(ClassLoader.class, "loadClass",String.class, new XC_MethodHook() {
    21. @Override
    22. protected void afterHookedMethod(MethodHookParam param) throws Throwable {
    23. // 获取返回值,得到类名
    24. Class clazz = (Class) param.getResult();
    25. Log.d("获取类:",clazz.getName());
    26. }
    27. });

    hook类所有方法

    构造函数不会被hook

    1. Class clazz=loadPackageParam.classLoader.loadClass("com.example.demo1.C1");
    2. Method[] met=clazz.getDeclaredMethods();
    3. for (Method method : met) {
    4. // 根据方法对象hook类,不需要传参数
    5. XposedBridge.hookMethod(method, new XC_MethodHook() {
    6. @Override
    7. protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
    8. // 遍历打印参数类型
    9. if(param.args!=null){
    10. for (Object arg : param.args) {
    11. Log.d("打印参数:",arg.getClass().getName());
    12. }
    13. }
    14. // 打印方法名,打印越靠后执行越晚
    15. Log.d("打印方法名:",method.toString());
    16. }
    17. });
    18. }

    Hook多dex

    如果app有多个dex,默认的classloader可能会找不到类,需要切换dex

    1. XposedHelpers.findAndHookMethod(Application.class, "attach", Context.class, new XC_MethodHook() {
    2. @Override
    3. protected void afterHookedMethod(MethodHookParam param) throws Throwable {
    4. ClassLoader c1=((Context)param.args[0]).getClassLoader();
    5. Class hookClass=null;
    6. try{
    7. // 根据类加载器寻找类
    8. hookClass=c1.loadClass("com.example.demo1.C1");
    9. }catch (Exception e){
    10. Log.e("lyf","寻找com.example.demo1.C1错误",e);
    11. }
    12. Log.i("lyf","寻找com.example.demo1.C1成功");
    13. XposedHelpers.findAndHookMethod(hookClass, "getS2", new XC_MethodHook() {
    14. @Override
    15. protected void afterHookedMethod(MethodHookParam param) throws Throwable {
    16. Log.d("lyf","hook getS2得到返回值:"+param.getResult().toString());
    17. }
    18. });
    19. }
    20. });