Xposed_Hook构造函数

编写准备

1.拷贝XposedBridgeApi.jar到新建工程的libs目录

2.修改App目录下的build.gradle文件,在androidmanifest.xml中新增Xposed相关内容

3.新建Hook类,编写Hook代码

4.新建assets文件夹,然后在assets目录下新建路径Xposed_init,在里面写上Hook类的完整路径

不想怎么麻烦可以使用如下(可以自动化创建Xposed模块Hook)

https://github.com/monkeylord/XposedTemplateForAS (新手推荐,但本文未使用)

Tips:AS版本3.6.2以上废掉了模板功能

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.xposed01">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <meta-data
            android:name="xposedmodule"
            android:value="true" /> //是否配置为Xposed插件,需要设置为true
        <meta-data
            android:name="xposedminversion"
            android:value="54" />   //最低版本号
        <meta-data
            android:name="xposeddescription"  //模块名字
            android:value="Xposed第一个" /> //描述

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Xposed插件编写

1.新建Hook类,命名为XMdodule,并实现IXPosedHookLoadPackage即可,并实现里面的关键方法handleLoadPackage(XC_LoadPackage.LoadPackageParam Ipparam),该方法会在每个软件被启动的时候回调,所以一般需要通过目标包名过滤。如下

Xposed01.java

public class Xposed01 implements IXposedHookLoadPackage{
    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable{
        Log.i("Xposed01", loadPackageParam.packageName);
        XposedBridge.log("App packagename" + loadPackageParam.packageName);
        if (loadPackageParam.packageName.equals("com.example.test")){
            XposedBridge.log("Xposed01" + loadPackageParam.packageName);
        }
    }
}

loadPackageParam.packageName 可以获取Xposed插件运行在哪个App进程空间当中

这里的日志输出Log.i会输出在安卓的日志中,XposedBridge.log会输出在Xposed程序日志中

59076-6ok83nif5xv.png

31612-vv4pb22puzo.png

多模块

如果有多个模块Xposed01,Xposed02,Xposed03...可以在assets/xposed_init中调整,按照先后顺序执行

com.example.xposed01.Xposed01
com.example.xposed01.Xposed02
com.example.xposed01.Xposed03
....

Tips:xposed_init是入口

在新建一个Xposed插件

这里我们需要自己写一个带有构造函数的App

Student.java

package com.example.xposedhook01;

public class Student {
    String name=null;
    String id=null;
    int age=0;
    public Student(){
        name="default";
        id="default";
        age=100;
    }
    public Student(String name){
        this.name=name;
        id="default";
    }
    public Student(String name,String id){
        this.name=name;
        this.id=id;
    }
    public Student(String name,String id,int age){
        this.name=name;
        this.id=id;
        this.age=age;
    }
}

MainActivity.java

package com.example.xposedhook01;

import androidx.appcompat.app.AppCompatActivity;

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

public class MainActivity extends AppCompatActivity {

    public void printStudent(Student stu){
        //打印学生信息
        Log.i("Xposed",stu.name+"- -"+stu.name+"- -"+stu.name+"- -"+stu.name);
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //调用四个构造函数
        Student astudent = new Student();
        Student bstudent = new Student("xiaoming");
        Student cstudent = new Student("xiaoming","2022");
        Student dstudent = new Student("xiaoming","2022",20);

        printStudent(astudent);
        printStudent(bstudent);
        printStudent(cstudent);
        printStudent(dstudent);

    }
}

Xposed Hook修改参数信息或者修改返回对象

运行情况

54349-xo2cm7veyv.png

Hook构造函数就需要用到XposedHelpers.findAndHookConstructor,AS中有两个

public static XC_MethodHook.Unhook findAndHookConstructor(Class<?> clazz, Object... parameterTypesAndCallback)
public static XC_MethodHook.Unhook findAndHookConstructor(String className, ClassLoader classLoader, Object... parameterTypesAndCallback)

第一个是java.lang.Class类型 可以通过反射获取Class进行加载

第二个是java.lang.String 需要传入类名和ClassLoader(就是当前的类被加载到哪个ClassLoader当中)后面就是构造函数的参数信息,最后就是一个回调。已知可以拿到的classloader和类名的

10047-ocv0797lfo.png

这里可以通过两种方式

首先需要获取Classloader,首先我们写的App并没有加壳,所以直接使用如下直接获取

ClassLoader classLoader=loadPackageParam.classLoader;

loadPackageParam类有当前包名/当前进程名/classLoader

92677-a63si5qetsi.png

1.无参构造函数Hook(使用第一个API)

package com.example.xposed01;

import android.util.Log;

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 Xposed01 implements IXposedHookLoadPackage{
    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable{
        Log.i("Xposed01", loadPackageParam.packageName);
        XposedBridge.log("App packagename" + loadPackageParam.packageName);
        if (loadPackageParam.packageName.equals("com.example.xposedhook01")){
            XposedBridge.log("Xposed01" + loadPackageParam.packageName);

            ClassLoader classLoader=loadPackageParam.classLoader;
            Class StudentClass=classLoader.loadClass(" com.example.xposedhook01.Student");//反射调用相关的api,得到StudentClass
            
        //public Student(){
        //name="default";
        //id="default";
        //age=100;
        //}
            XposedHelpers.findAndHookConstructor(StudentClass, new XC_MethodHook() {
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    super.beforeHookedMethod(param); //调用前,用于参数修改等
                    XposedBridge.log("com.example.xposedhook01.Student() is Classed!!beforeHookedMethod");
                }

                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    super.afterHookedMethod(param);//调用后,用于返回值修改或获取等
                    XposedBridge.log("com.example.xposedhook01.Student() is Classed!!afterHookedMethod");
                }
            });
        }
    }
}

2.有参构造函数Hook(使用第一个API)

不管是beforeHookedMethod还是afterHookedMethod都有一个参数叫MethodHookParam

有当前对象thisObject,参数args,可以看到是一个数组,同时还有一个result(函数执行后),一般用着三个

11908-5s1s44dxejc.png

//            public Student(String name){
//                this.name=name;
//                id="default";
            XposedHelpers.findAndHookConstructor(StudentClass, String.class, new XC_MethodHook() { //需要传入参数类型,这样就可以获取到参数信息了
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    super.beforeHookedMethod(param);
                    java.lang.Object[] argsobjarray=param.args;
                    String name=(String) argsobjarray[0];   //强制转换

                    XposedBridge.log("com.example.xposedhook01.Student(String) is Classed!!beforeHookedMethod- -"+name);
                }

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

//            public Student(String name,String id){
//                this.name=name;
//                this.id=id;
//            }
            //在参数传入中多加一个String.class
            XposedHelpers.findAndHookConstructor(StudentClass, String.class, String.class, new XC_MethodHook() {
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    super.beforeHookedMethod(param);
                    java.lang.Object[] argsobjarray=param.args;
                    String name=(String) argsobjarray[0];   //强制转换
                    String id=(String) argsobjarray[1];

                    XposedBridge.log("com.example.xposedhook01.Student(String,String) is Classed!!beforeHookedMethod- -"+name+"---"+id);
                }

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

//public Student(String name,String id,int age){
//                this.name=name;
//                this.id=id;
//                this.age=age;
//            }
            XposedHelpers.findAndHookConstructor(StudentClass, String.class, String.class, int.class, new XC_MethodHook() {
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    super.beforeHookedMethod(param);
                    java.lang.Object[] argsobjarray=param.args;
                    String name=(String) argsobjarray[0];   //强制转换
                    String id=(String) argsobjarray[1];
                    int age=(int) argsobjarray[2];
                    
                     //修改参数
                    argsobjarray[1]="2050";
                    argsobjarray[2]=1000;

                    XposedBridge.log("com.example.xposedhook01.Student(String,String,int) is Classed!!beforeHookedMethod- -"+name+"---"+id+"- -"+age);
                }

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

38148-rolhp1w1obm.png

(使用第二个API)

//第二种方式需要知道准确的Classloader,其他内容和上面的差不多
            XposedHelpers.findAndHookConstructor("com.example.xposedhook01.Student", loadPackageParam.classLoader, 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);
                }
            });

本文链接:

https://www.linqi.net.cn/index.php/archives/345/