​ 为了编写xposed模块,必须了解常用的hook API,所以,接下来我就用一个例子来说明。

hook目标

  1. hook目标类 ​ 代码比较长,所以肯定没有人有耐心看,所以建议直接跟着后面的说明来理解。

/*注意这里是伪代码*/
package cn.bluarry.hookme;

import android.util.Log;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

abstract class Animal{
    int anonymoutInt = 500;
    public abstract void eatFunc(String value);
}
public class HookDemo {
    private String Tag = "HookDemo";
    private static  int staticInt = 100;
    public  int publicInt = 200;
    private int privateInt = 300;

    public HookDemo(){
        this("NOHook");
        Log.d(Tag, "HookDemo() was called|||");
    }

    private HookDemo(String str){
        Log.d(Tag, "HookDemo(String str) was called|||" + str);
    }

    public void hookDemoTest(){
        Log.d(Tag, "staticInt = " + staticInt);
        Log.d(Tag, "PublicInt = " + publicInt);
        Log.d(Tag, "privateInt = " + privateInt);
        publicFunc("NOHook");
        Log.d(Tag, "PublicInt = " + publicInt);
        Log.d(Tag, "privateInt = " + privateInt);
        privateFunc("NOHook");
        staticPrivateFunc("NOHook");

        String[][] str = new String[1][2];
        Map map = new HashMap<String, String>();
        map.put("key", "value");
        ArrayList arrayList = new ArrayList();
        arrayList.add("listValue");
        complexParameterFunc("NOHook", str, map, arrayList);

        repleaceFunc();
        anonymousInner(new Animal() {
            @Override
            public void eatFunc(String value) {
                Log.d(Tag, "eatFunc(String value)  was called|||" + value);
                Log.d(Tag, "anonymoutInt =  " + anonymoutInt);
            }
        }, "NOHook");

        InnerClass innerClass = new InnerClass();
        innerClass.InnerFunc("NOHook");
    }

    public void publicFunc(String value){
        Log.d(Tag, "publicFunc(String value) was called|||" + value);
    }

    private void privateFunc(String value){
        Log.d(Tag, "privateFunc(String value) was called|||" + value);
    }

    static private void staticPrivateFunc(String value){
        Log.d("HookDemo", "staticPrivateFunc(Strin value) was called|||" + value);
    }

    private void complexParameterFunc(String value, String[][] str, Map<String,String> map, ArrayList arrayList)
    {
        Log.d("HookDemo", "complexParameter(Strin value) was called|||" + value);
    }
    private void repleaceFunc(){
        Log.d(Tag, "repleaceFunc will be replace|||");
    }
    public void anonymousInner(Animal dog, String value){
        Log.d(Tag, "anonymousInner was called|||" + value);
        dog.eatFunc("NOHook");
    }

    private void hideFunc(String value){
        Log.d(Tag, "hideFunc was called|||" + value);
    }

    class InnerClass{
        public int innerPublicInt = 10;
        private int innerPrivateInt = 20;
        public InnerClass(){
            Log.d(Tag, "InnerClass constructed func was called");
        }
        public void InnerFunc(String value){
            Log.d(Tag, "InnerFunc(String value) was called|||" + value);
            Log.d(Tag, "innerPublicInt = " + innerPublicInt);
            Log.d(Tag, "innerPrivateInt = " + innerPrivateInt);
        }
    }
}
  1. 对目标类的说明 ​ 使用说明: 用AS来构建一个安卓应用,直接默认一个mainActivity,在Oncreate方法里实例化我们的HookDemo类,然后调用hookDemoTest()方法即可。 ​ 为进行hook前的输出如下图一:


图一

hook API

1. hook 静态变量

​ 对应于上面的例子,实际上是hook变量staticInt,相应的方法如下:

final Class<?> clazz = XposedHelpers.findClass("cn.bluarry.hookme.HookDemo", lpparam.classLoader);
XposedHelpers.setStaticIntField(clazz, "staticInt", 99); 

​ 上面的例子只演示了hook 类型 static int的变量,其他类型的API同上,只需要将Int改为 long,double,object等,结合具体情况拓展即可。

2. hook 无参构造函数

​ hook此构造函数比较简单,具体代码如下:

 XposedHelpers.findAndHookConstructor(clazz, new XC_MethodHook() {
                @Override
        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    XposedBridge.log("Haha, HookDemo constructed was hooked" );
                }
            });

3. Hook公有方法

​ 主要 1.修改参数 2.修改下publicInt和privateInt的值

  XposedHelpers.findAndHookMethod(clazz, "publicFunc", String.class, new XC_MethodHook() {
                @Override
     protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    param.args[0] = "Haha, publicFunc are hooked";
                    XposedHelpers.setIntField(param.thisObject, "publicInt", 199);
                    XposedHelpers.setIntField(param.thisObject, "privateInt", 299);
                }
  });

4. hook方法后/前/时,调用其他方法

    这里主要调用hideFunc,如下
XposedHelpers.findAndHookMethod(clazz, "publicFunc", String.class, new XC_MethodHook() {
                @Override
    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
       // 让hook的对象本身去执行流程
       Method md = clazz.getDeclaredMethod("hideFunc", String.class);
       md.setAccessible(true);
      //方法一:
      //md.invoke(param.thisObject, "Haha, hideFunc was hooked");
      //方法二: 
    XposedHelpers.callMethod(param.thisObject, "hideFunc", "Haha, hideFunc was hooked");
      //方法三: 
      //实例化对象,然后再调用HideFunc方法
      //Constructor constructor = clazz.getConstructor();
      //XposedHelpers.callMethod(constructor.newInstance(), "hideFunc", "Haha, hideFunc was hooked");
                }
            });

5. Hook私有方法

XposedHelpers.findAndHookMethod(clazz, "privateFunc", String.class, new XC_MethodHook() {
                @Override
   protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    param.args[0] = "Haha, privateFunc are hooked";
                }
   });

6. Hook私有静态方法

 XposedHelpers.findAndHookMethod(clazz, "staticPrivateFunc", String.class, new XC_MethodHook() {
       @Override
      protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    param.args[0] = "Haha, staticPrivateFunc are hooked";
   }
  });

7.Hook复杂参数函数

​ 这里说明一下,首先构造了两个复杂参数Map和ArrayList,调用的时候,基本类型如String,直接写String.class, 而对于String数组的写法如代码中所写,注意写法

Class fclass1 = XposedHelpers.findClass("java.util.Map", lpparam.classLoader);
Class fclass2 = XposedHelpers.findClass("java.util.ArrayList", lpparam.classLoader);
XposedHelpers.findAndHookMethod(clazz, "complexParameterFunc", String.class,
    "[[Ljava.lang.String;", fclass1, fclass2, new XC_MethodHook() {
                        @Override
                        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                            param.args[0] = "Haha, complexParameterFunc are hooked";
                        }
                    });

8. Hook私有方法

XposedHelpers.findAndHookMethod(clazz, "repleaceFunc", new XC_MethodReplacement() {
                @Override
    protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
                    Log.d("HookDemo", "Haha, repleaceFunc are replaced");
                    return null;
   }
  });

9. Hook方法, anonymousInner, 参数是抽象类

​ 这也是一种情况,即参数为某抽象类的new出来的匿名类,注意,hook的是该方法,匿名类的方法并未hook!

Class animalClazz  = lpparam.classLoader.loadClass("cn.bluarry.hookme.Animal");
XposedHelpers.findAndHookMethod(clazz, "anonymousInner", animalClazz, String.class, new XC_MethodHook() {
                @Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    XposedBridge.log("HookDemo This is test");
                    param.args[1] = "Haha, anonymousInner are hooked";
                }
});

10.Hook匿名类的方法

XposedHelpers.findAndHookMethod("cn.bluarry.hookme.HookDemo$1", clazz.getClassLoader(),
        "eatFunc", String.class, new XC_MethodHook() {
            @Override
     protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                param.args[0] = "Haha, eatFunc are hooked";
                XposedHelpers.setIntField(param.thisObject, "anonymoutInt", 499);
            }
});

11. Hook内部类的方法,修改参数

  final Class<?> clazz1 = XposedHelpers.findClass("cn.bluarry.hookme.HookDemo$InnerClass", lpparam.classLoader);
            XposedHelpers.findAndHookMethod(clazz1, "InnerFunc", String.class, new XC_MethodHook() {
                @Override
         protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    param.args[0] = "Haha, InnerFunc was hooked";
                    XposedHelpers.setIntField(param.thisObject, "innerPublicInt", 9);
                    XposedHelpers.setIntField(param.thisObject, "innerPrivateInt", 19);
                }
     });

hook结果


图一

本文章的项目地址

hookme

hookDemo

最后更新: 2020年03月02日 20:53

原始链接: /2020/02/28/2020-02-28-xposed模块编写之常用hook函数API/

× 请我吃糖~
打赏二维码