LSPosed-Java层Hook

前言

LSPosed项目目前开发者仍在积极维护,在支持了使用Xposed API方式开发模块的同时,也支持不需重启就可让Hook代码生效,极大地提高了开发效率.

其Xposed API官方地址如下:

https://api.xposed.info/reference/packages.html

下面通过一个示例,来展示下LSPosed Java层的Hook流程.

测试Apk

Person.java:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package com.example.luodst;

public class Person {
    private String name = "LuoHun";
    private int age = 18;

    public Person(){
    }

    public Person(String name, int age){
        this.name = name;
        this.age = age;
    }

    // Invoke
    public String publicMethod(){
        return String.format("publicMethod name:%s age:%d", this.name, this.age);
    }

    private String privateMethod(){
        return String.format("privateMethod name:%s age:%d", this.name, this.age);
    }

    public static String publicStaticMethod(){
        return "I'm from publicStaticMethod";
    }

    public String getName(Person person){
        return "Person name is " + person.name;
    }

    public String toString(){
        return String.format("name:%s age:%d", this.name, this.age);
    }

    public String replaceFunc(){
        return String.format("replaceFunc name:%s age:%d", this.name, this.age);
    }

    class Student{
        String course = "Math";
        public String getCourse(){
            return course;
        }
    }

}

MainActivity.java:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package com.example.luodst;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

import com.example.luodst.databinding.ActivityMainBinding;

public class MainActivity extends AppCompatActivity {
    private final String TAG = "[XiaLuoHun]";

    // Used to load the 'luodst' library on application startup.
    static {
        System.loadLibrary("luodst");
    }

    private ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        // Example of a call to a native method
        TextView tv = binding.sampleText;
        tv.setText(stringFromJNI());

        Person person1 = new Person();
        Log.i(TAG, person1.toString());
        Person person2 = new Person("Luo", 50);
        Log.i(TAG, person2.toString());

        String personName = person2.getName(person1);
        Log.i(TAG, personName);

        String strResult = person2.replaceFunc();
        Log.i(TAG, strResult);
    }

    /**
     * A native method that is implemented by the 'luodst' native library,
     * which is packaged with this application.
     */
    public native String stringFromJNI();
}

Hook构造函数

对Java中构造函数的Hook主要借助于Xposed API中XposedHelpers.findAndHookConstructor函数.

1
2
findAndHookConstructor(Class<?> clazz, Object... parameterTypesAndCallback)
findAndHookConstructor(String className, ClassLoader classLoader, Object... parameterTypesAndCallback)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package com.example.luoxposeddemo;

import android.util.Log;

import java.lang.reflect.Field;

import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;

public class LuoHook implements IXposedHookLoadPackage {
    private final String TAG = "[LuoXposed]";

    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
        if (lpparam.packageName.equals("com.example.luodst")) {
            //寻找类 方式一
            //Class personClass = lpparam.classLoader.loadClass("com.example.luodst.Person");
            //寻找类 方式二
            Class personClass = XposedHelpers.findClass("com.example.luodst.Person",lpparam.classLoader);

            //Hook Person()
            XposedHelpers.findAndHookConstructor(personClass, new XC_MethodHook() {
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    super.beforeHookedMethod(param);
                    //输出日志的两种方式
                    Log.i(TAG, "Enter Person()");
                    XposedBridge.log("Enter Person()");
                }

                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    super.afterHookedMethod(param);
                    Log.i(TAG, "Leave Person()");
                    XposedBridge.log("Leave Person()");
                }
            });

            //Hook Person(String name, int age)
            XposedHelpers.findAndHookConstructor(personClass, lpparam.classLoader,String.class, int.class, new XC_MethodHook() {
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    super.beforeHookedMethod(param);
                    Log.i(TAG, "Enter Person(String name, int age)");

                    //获取值 方式一
             /*       String name = (String) param.args[0];
                    Log.i(TAG, name);*/

                    //设置值 方式一
              /*      param.args[0] = "Hun";
                    param.args[1] = 500;*/
                }

                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    super.afterHookedMethod(param);
                    Log.i(TAG, "Enter Person(String name, int age)");

                    //获取值 方式二
                   /* int age = XposedHelpers.getIntField(param.thisObject, "age");
                    Log.i(TAG, Integer.toString(age));*/
                    //获取值 方式三
                    Class clazz = XposedHelpers.findClass("com.example.luodst.Person", lpparam.classLoader);
                    Field age = clazz.getDeclaredField("age");
                    age.setAccessible(true);
                    int age_value = (int) age.get(param.thisObject);
                    Log.i(TAG, Integer.toString(age_value));

                    //设置值 方式二
                 /*   XposedHelpers.setObjectField(param.thisObject, "name", "Hun");
                    XposedHelpers.setIntField(param.thisObject,"age",600);*/
                    //设置值 方式三
         /*           Class personClass = XposedHelpers.findClass("com.example.luodst.Person", lpparam.classLoader);
                    Field age = personClass.getDeclaredField("age");
                    age.setAccessible(true);
                    age.set(param.thisObject, 600);*/
                }
            });
        }
    }
}

Hook普通函数

对Java中普通函数的Hook主要借助于Xposed API中XposedHelpers.findAndHookMethod函数.

1
2
findAndHookMethod(Class<?> clazz, String methodName, Object... parameterTypesAndCallback)
findAndHookMethod(String className, ClassLoader classLoader, String methodName, Object... parameterTypesAndCallback)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package com.example.luoxposeddemo;

import android.util.Log;

import java.lang.reflect.Field;

import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;

public class LuoHook implements IXposedHookLoadPackage {
    private final String TAG = "[LuoXposed]";

    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
        if (lpparam.packageName.equals("com.example.luodst")) {
            //寻找类 方式一
            //Class personClass = lpparam.classLoader.loadClass("com.example.luodst.Person");
            //寻找类 方式二
            Class personClass = XposedHelpers.findClass("com.example.luodst.Person",lpparam.classLoader);

            //Hook com.example.luodst.Person.toString()
            XposedHelpers.findAndHookMethod(personClass, "toString", new XC_MethodHook() {
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    super.beforeHookedMethod(param);
                    Log.i(TAG, "Enter com.example.luodst.Person.toString()");
                }

                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    super.afterHookedMethod(param);
                    Log.i(TAG, "Leave com.example.luodst.Person.toString()");
                }
            });

            //Hook com.example.luodst.MainActivity.stringFromJNI()
            XposedHelpers.findAndHookMethod("com.example.luodst.MainActivity", lpparam.classLoader, "stringFromJNI", new XC_MethodHook() {
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    super.beforeHookedMethod(param);
                    Log.i(TAG, "Enter com.example.luodst.MainActivity.stringFromJNI");
                }

                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    super.afterHookedMethod(param);
                    param.setResult("Hello XiaLuoHun");
                }
            });
        }
    }
}

主动调用

主动调用分为静态函数和实例函数.

Xposed 提供了关于主动调用的API,其相应函数签名分别为:

1
2
callMethod(Object obj, String methodName, Class[]<?> parameterTypes, Object... args)
callMethod(Object obj, String methodName, Object... args)

下面主要展示下主动调用的几种形式.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package com.example.luoxposeddemo;

import android.util.Log;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;

public class LuoHook implements IXposedHookLoadPackage {
    private final String TAG = "[LuoXposed]";

    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
        if (lpparam.packageName.equals("com.example.luodst")) {
            //寻找类 方式一
            //Class personClass = lpparam.classLoader.loadClass("com.example.luodst.Person");
            //寻找类 方式二
            Class personClass = XposedHelpers.findClass("com.example.luodst.Person", lpparam.classLoader);

            //Invoke静态函数
            //①反射
            Method publicStaticMethod = personClass.getDeclaredMethod("publicStaticMethod");
            String strResult1 = (String) publicStaticMethod.invoke(null);
            Log.i(TAG, strResult1);
            //②Xposed API
            String strResult2 = (String) XposedHelpers.callStaticMethod(personClass, "publicStaticMethod");
            Log.i(TAG, strResult2);

            //Invoke实例函数
            //①类原生方式
            Object personObj1 = personClass.newInstance();
            String result1 = (String) XposedHelpers.callMethod(personObj1, "publicMethod");
            Log.i(TAG, result1);
            //②通过构造函数进行调用
            Constructor personConstructor = personClass.getConstructor(String.class, int.class);
            Object personObj2 = personConstructor.newInstance("Luo", 1000);
            String result2 = (String) XposedHelpers.callMethod(personObj2, "toString");
            Log.i(TAG, result2);
            //③Xposed API
            //public method
            Object personObj3 = XposedHelpers.newInstance(personClass, "Hun", 2000);
            String result3 = (String) XposedHelpers.callMethod(personObj3, "publicMethod");
            Log.i(TAG, result3);
            //private method
            Object personObj4 = XposedHelpers.newInstance(personClass, "Hun", 3000);
            String result4 = (String) XposedHelpers.callMethod(personObj4, "privateMethod");
            Log.i(TAG, result4);
            //④反射
            Object personObj5 = XposedHelpers.newInstance(personClass, "Hun", 4000);
            Method privateMethod = personClass.getDeclaredMethod("privateMethod");
            privateMethod.setAccessible(true);
            String resutlt5 = (String) privateMethod.invoke(personObj5);
            Log.i(TAG, resutlt5);
            //⑤Hook构造函数
            XposedHelpers.findAndHookConstructor(personClass, String.class, int.class, new XC_MethodHook() {
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    super.beforeHookedMethod(param);
                }

                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    super.afterHookedMethod(param);
                    //publicMethod
                    String result = (String) XposedHelpers.callMethod(param.thisObject, "publicMethod");
                    Log.i(TAG, result);
                }
            });
            //⑥Hook参数
            Class selfClass = XposedHelpers.findClass("com.example.luodst.Person", lpparam.classLoader);
            XposedHelpers.findAndHookMethod("com.example.luodst.Person", lpparam.classLoader, "getName", selfClass, new XC_MethodHook() {
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    super.beforeHookedMethod(param);
                    Log.i(TAG, "Enter Invoke com.example.luodst.Person.privateMethod");
                    //privateMethod
                    String result = (String) XposedHelpers.callMethod(param.args[0], "privateMethod");
                    Log.i(TAG, result);
                }

                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    super.afterHookedMethod(param);
                }
            });
        }
    }
}

函数替换

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.example.luoxposeddemo;

import android.util.Log;

import java.lang.reflect.Field;

import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XC_MethodReplacement;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;

public class LuoHook implements IXposedHookLoadPackage {
    private final String TAG = "[LuoXposed]";

    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
        if (lpparam.packageName.equals("com.example.luodst")) {
            //寻找类 方式一
            //Class personClass = lpparam.classLoader.loadClass("com.example.luodst.Person");
            //寻找类 方式二
            Class personClass = XposedHelpers.findClass("com.example.luodst.Person",lpparam.classLoader);

            //进行函数替换
            XposedHelpers.findAndHookMethod(personClass, "replaceFunc", new XC_MethodReplacement() {
                @Override
                protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
                    Log.i(TAG, "replaceFunc");
                    return "LuoReplaceFunc";
                }
            });
        }
    }
}

相关内容

0%