Xposed学习笔记

Xposed学习记录.

https://github.com/rovo89/XposedBridge
交流微信: cjh-18888

1. Xposed 与EdXposed的安装

https://dl-xda.xposed.info/framework/

为什么我2个版本?
官方的xposed正式版支持到sdk25(android 7.1)后,就没继续发布正式版的xposed了。sdk26,27都是beta版。
因此我们在给系统刷入xposed的时候,要分版本对待。

  • android系统 <= 7.1 使用官方原本xposed
  • android系统 > 7.1 使用EdXposed

由于我这里只想刷高版本的,低版本的就不演示。
我选择了android9的版本,使用的设备是pixel一代.

  1. 刷机:sailfish-ppr1.180610.009-factory-a945cab8 我选择了这个版本的镜像,解压运行flash_all.bat就可以了
  2. 下载Magisk,Edxposed.riru.twrp 介绍:Magisk是root,EdXposed就是Xposed的民间版,twrp就是定制的recovery

!!! 都使用ZIP包 !!! github都可以找到,我也传了一份到网盘上
网盘地址: https://drive.weixin.qq.com/s?k=AJEAIQdfAAonAvscTZAHIAKgYiACo
EdXposed 有 sendhook 和YAHFA版, 下载sendhook,当然,yahfa也可以。
magisk-riru-v21.1
Magisk下载的是Magisk-v20.4.zip

  1. 推入sdcard.
adb push EdXposed-SandHook-v0.4.6.2.4529.-release.zip /sdcard/
adb push magisk-riru-v21.1.zip /sdcard/
adb push Magisk-v20.4.zip /sdcard/
  1. 刷入临时twrp且安装magisk,magisk-riru,edxposed,
// 进入bootloader模式
adb reboot bootloader

// 刷入临时twrp
fastboot boot twrp-3.3.0-0-sailfish.img

// 安装 Magisk -> Magisk riru -> Edxposed
// 进到漂亮的recovery界面以后 点击 Install ,找到 sdcard, 然后依次安装,然后do not install 就安装完毕了。

  1. 安装JustTrustMe 测试是否成功
adb install JustTrustMe.apk
// 然后激活模块,重启设备.
adb logcat 
// 不出意外是可以顺利找到 Xposed的.

2. 第一个Xposed模块

基本步骤:

  1. 拷贝XposedBridgeApi.jar 到新建工程的libs目录
  2. 修改app目录下的build.gradle文件,在AndroidManifest.xml新增Xposed相关的内容
  3. 新建hook类,编写hook代码
  4. 新建assets文件夹,然后在assets目录下新建xposed_init,在里面写上hook类的完整路径

1. 在libs导入XposedBridgeApi-54.jar

文件也打包了,复制粘贴就好。

2. 修改AndroidManifest.xml

             // 是否配置为Xposed插件 设置为true
        <meta-data
            android:name="xposedmodule" 
            android:value="true" />

            // 模块名称
        <meta-data android:name="xposeddescription"
            android:value="hook 构造函数"/>

            // 最低版本号
        <meta-data android:name="xposedminversion"
            android:value="54" />

3. 修改build.gradle

dependencies加入

compileOnly fileTree(dir: 'libs',include:['*.jar'])

4. 创建一个hook类

基本Hook代码

package com.xiaopang.xposed01;

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

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

我们可以打印一下包名,代码如下.


    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
        Log.i("Xposed01", loadPackageParam.packageName);
        // XposedBridge.log 在xposedinstall的log信息中是可以看到这部分的log
        XposedBridge.log("Xposed01 ->app packagename" + loadPackageParam.packageName);
        if (loadPackageParam.packageName.equals("com.example.test")) {
            XposedBridge.log("weixin:cjh-18888 " + loadPackageParam.packageName);
        };
    }

5.创建main/assets目录,新建文本xposed_init

xposed_init里面内容为实现了IXposedHookLoadPackage接口的hook类的完整类名,它可以有多个,每一个hook实现类占一行。
xposed_init的内容

com.xiaopang.xposed01.Xposed01

6. 编译APK,看logcat

编译apk,重启,看logcat, 过滤下

2021-03-23 13:33:55.878 4440-4440/? I/EdXposed-Bridge: Xposed01 ->app packagenamecom.qualcomm.fastdormancy
2021-03-23 13:33:56.030 4496-4496/? I/EdXposed-Bridge: Xposed01 ->app packagenamecom.qualcomm.embms
2021-03-23 13:33:56.124 4514-4514/? I/EdXposed-Bridge: Xposed01 ->app packagenameorg.codeaurora.ims
2021-03-23 13:33:56.401 4537-4537/? I/EdXposed-Bridge: Xposed01 ->app packagenamecom.topjohnwu.magisk
2021-03-23 13:33:56.849 4569-4569/? I/EdXposed-Bridge: Xposed01 ->app packagenamecom.android.settings
2021-03-23 13:33:57.024 4584-4584/? I/EdXposed-Bridge: Xposed01 ->app packagenamecom.google.android.carriersetup
2021-03-23 13:33:58.283 4609-4609/? I/EdXposed-Bridge: Xposed01 ->app packagenamecom.android.cellbroadcastreceiver
2021-03-23 13:33:58.473 4627-4627/? I/EdXposed-Bridge: Xposed01 ->app packagenamecom.google.android.apps.messaging
2021-03-23 13:33:59.244 4661-4661/? I/EdXposed-Bridge: Xposed01 ->app packagenamecom.google.android.dialer
2021-03-23 13:34:00.028 4701-4701/? I/EdXposed-Bridge: Xposed01 ->app packagenamecom.google.android.gms
2021-03-23 13:34:00.314 4718-4718/? I/EdXposed-Bridge: Xposed01 ->app packagenamecom.google.android.apps.maps
2021-03-23 13:34:03.260 4797-4797/? I/EdXposed-Bridge: Xposed01 ->app packagenamecom.google.android.apps.messaging
2021-03-23 13:34:03.694 4821-4821/? I/EdXposed-Bridge: Xposed01 ->app packagenamecom.google.android.gm

3. Hook构造函数

1. 编写目标APP

  1. 创建Student类
package com.xiaopang.xposedhook01;

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

    public Student(String name){
        this.name = name;
        this.id = "dafault";
        this.age = 100;
    }


    public Student(String name, String id){
        this.name = name;
        this.id = id;
        this.age = 100;
    }

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


  1. 完善MainActivaty
package com.xiaopang.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.id + "--" + stu.age);

    }

    @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("xiaohua","2020");
        Student dstudent = new Student("xiaohong","2020",20);
        printStudent(astudent);
        printStudent(bstudent);
        printStudent(cstudent);
        printStudent(dstudent);

    }
}

运行一下可以在日志看到

2021-03-23 13:45:18.094 8422-8422/com.xiaopang.xposedhook01 I/Xposed: dafault--dafault--100
2021-03-23 13:45:18.094 8422-8422/com.xiaopang.xposedhook01 I/Xposed: xiaoming--dafault--100
2021-03-23 13:45:18.094 8422-8422/com.xiaopang.xposedhook01 I/Xposed: xiaohua--2020--100
2021-03-23 13:45:18.094 8422-8422/com.xiaopang.xposedhook01 I/Xposed: xiaohong--2020--20

2. 无参构造函数

  1. 创建HookConstructors类

// 无参构造函数Hook
XposedHelpers.findAndHookConstructor(StudentClass, new XC_MethodHook() {
    @Override // 执行前  可以对参数进行修改
    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
        super.beforeHookedMethod(param);
        XposedBridge.log("com.xiaopang.xposedhook01.Student() is called [beforeHookedMethod]");
    }

    @Override // 调用后  可以对返回值进行修改
    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
        super.afterHookedMethod(param);
        XposedBridge.log("com.xiaopang.xposedhook01.Student is called [afterHookedMethod]");
    }
});

3. 有参构造函数


// 有参构造函数Hook
//     public Student(String name){
//        this.name = name;
//        this.id = "dafault";
//        this.age = 100;
//    }
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.xiaopang.xposedhook01.Student(String) is called [beforeHookedMethod]--" + name);
    }
    @Override // 调用后  可以对返回值进行修改
    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
        super.afterHookedMethod(param);
        XposedBridge.log("com.xiaopang.xposedhook01.Student is called [afterHookedMethod]");
    }
});

// 有参构造函数Hook
//     public Student(String name, String id){
//        this.name = name;
//        this.id = id;
//        this.age = 100;
//    }
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.xiaopang.xposedhook01.Student(String,String) is called [beforeHookedMethod]--" + name + "--" + id);
    }
    @Override // 调用后  可以对返回值进行修改
    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
        super.afterHookedMethod(param);
        XposedBridge.log("com.xiaopang.xposedhook01.Student is called [afterHookedMethod]");
    }
});

// 有参构造函数Hook
//     public Student(String name, String id){
//    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];
        String age = (String) argsObjarray[2];
        XposedBridge.log("com.xiaopang.xposedhook01.Student(String,String,int) is called [beforeHookedMethod]--" + name + "--" + id + "--" + age);
    }
    @Override // 调用后  可以对返回值进行修改
    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
        super.afterHookedMethod(param);
        XposedBridge.log("com.xiaopang.xposedhook01.Student is called [afterHookedMethod]");
    }
});

3. 修改参数

// 有参构造函数Hook
//     public Student(String name, String id){
//    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];
        String age = (String) argsObjarray[2];

        argsObjarray[0] = "weixin:cjh-18888"  // 修改参数

        XposedBridge.log("com.xiaopang.xposedhook01.Student(String,String,int) is called [beforeHookedMethod]--" + name + "--" + id + "--" + age);
    }
    @Override // 调用后  可以对返回值进行修改
    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
        super.afterHookedMethod(param);
        XposedBridge.log("com.xiaopang.xposedhook01.Student is called [afterHookedMethod]");
    }
});

4. 修改返回值。

// 有参构造函数Hook
//     public Student(String name, String id){
//    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];
        String age = (String) argsObjarray[2];

        argsObjarray[0] = "weixin:cjh-18888"  // 修改参数

        XposedBridge.log("com.xiaopang.xposedhook01.Student(String,String,int) is called [beforeHookedMethod]--" + name + "--" + id + "--" + age);
    }
    @Override // 调用后  可以对返回值进行修改
    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
        super.afterHookedMethod(param);
        Object
        XposedBridge.log("com.xiaopang.xposedhook01.Student is called [afterHookedMethod]");
    }
});

3. 修改属性.

如若一个类中拥有这些属性


public class Student {
    String name = null;
    String id = null;
    int age = 0;
    private String nikename = null;
    public static String teacherName = null;


    .......
}

1. 利用反射来修改属性

    XposedHelpers.findAndHookConstructor(StudentClass,String.class,String.class,int.class,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];
            String age = (String) argsObjarray[2];
            argsObjarray[0] = "weixin:cjh-18888";  // 修改参数
            argsObjarray[1] = "10000";

            String teacher = (String) argsObjarray[3];
            String nikename = (String) argsObjarray[4];
            XposedBridge.log("com.xiaopang.xposedhook01.Student(String,String,int) is called [beforeHookedMethod]--" + name + "--" + id + "--" + age + "--" + teacher + "--" + nikename);
        }
        @Override // 调用后  可以对返回值进行修改
        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
            super.afterHookedMethod(param);
            Object thisobj = param.thisObject;
            Object returnobj = param.getResult();
            XposedBridge.log(thisobj + "---" + returnobj);
            XposedBridge.log("com.xiaopang.xposedhook01.Student is called [afterHookedMethod]");
        }
    });
    ClassLoader pathClassLoader = loadPackageParam.classLoader;
    Class stuClass = pathClassLoader.loadClass("com.xiaopang.xposedhook01.Student");
    Field teacherField = stuClass.getDeclaredField("teacher");

    teacherField.setAccessible(true);
    teacherField.set(null,"teacher666");
    
    String teachername = (String) teacherField.get(null);
    Log.d("weixin:cjh-18888", "teacherField->" + teachername);

2. 利用Xposed API修改

 // 通过Xposed API来修改属性
String teachername2 = (String) XposedHelpers.getStaticObjectField(stuClass,"teacher");
XposedHelpers.setStaticObjectField(stuClass,"teacher","xiaopang66666");

// 修改对象属性
// XposedHelpers.setObjectField();

它其实也是通过反射的.

    public static Object getStaticObjectField(Class<?> clazz, String fieldName) {
        try {
            return findField(clazz, fieldName).get((Object)null);
        } catch (IllegalAccessException var3) {
            XposedBridge.log(var3);
            throw new IllegalAccessError(var3.getMessage());
        } catch (IllegalArgumentException var4) {
            throw var4;
        }
    }

看看findField , 继续深究其实一样是利用了反射的原理

    public static Field findField(Class<?> clazz, String fieldName) {
        StringBuilder sb = new StringBuilder(clazz.getName());
        sb.append('#');
        sb.append(fieldName);
        String fullFieldName = sb.toString();
        Field field;
        if (fieldCache.containsKey(fullFieldName)) {
            field = (Field)fieldCache.get(fullFieldName);
            if (field == null) {
                throw new NoSuchFieldError(fullFieldName);
            } else {
                return field;
            }
        } else {
            try {
                field = findFieldRecursiveImpl(clazz, fieldName);
                field.setAccessible(true);
                fieldCache.put(fullFieldName, field);
                return field;
            } catch (NoSuchFieldException var5) {
                fieldCache.put(fullFieldName, (Object)null);
                throw new NoSuchFieldError(fullFieldName);
            }
        }
    }


3. 使用Xposed进行“破解”

apk已传到网盘

反编译后,看到关键代码在这里. content内容长度 = 16 且 Flag2.check(content)为真的时候,返回true;

package com.kanxue.xposedflag;

public class Flag1 {
    public static int length = 16;

    public static boolean check(String content) {
        if (content.length() != length || !new Flag2().check(content)) {
            return false;
        }
        return true;
    }
}

这里看到是在判断,content等于this.flag就返回真. 那么通过上面的学习,其实很容易就编写出xposed代码.


public class Flag2 {
    public String flag = "aiyaobucuo";

    public boolean check(String content) {
        if (content.equals(this.flag)) {
            return true;
        }
        return false;
    }
}

Xposed代码,

package com.xiaopang.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 hookFlag  implements IXposedHookLoadPackage {
    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
        // com.kanxue.xposedflag
        Log.d("weixin:cjh-18888", "packageNmae ->" + loadPackageParam.packageName);
//        XposedBridge.log("packageNmae ->" + loadPackageParam.packageName);
        if (loadPackageParam.packageName.equals("com.kanxue.xposedflag")) {
            Log.d("weixin:cjh-18888", "packageNmae ->" + loadPackageParam.packageName);
//            XposedBridge.log("packageNmae ->" + loadPackageParam.packageName);
            ClassLoader classLoader = loadPackageParam.classLoader;

            // flag 1
            Class flag1clazz = classLoader.loadClass("com.kanxue.xposedflag.Flag1");

            XposedHelpers.setStaticIntField(flag1clazz,"length",6);

            // flag 2
            XposedHelpers.findAndHookConstructor("com.kanxue.xposedflag.Flag2", classLoader, new XC_MethodHook() {
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    super.beforeHookedMethod(param);
                    Log.d("weixin:cjh-18888", "into flag 2");
//                    XposedBridge.log("into flag 2");

                }
                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    super.afterHookedMethod(param);
//                    XposedBridge.log("leave flag2 ");
                    Log.d("weixin:cjh-18888", "leave flag2 ");
                    Object flag2obj = param.thisObject;
                    XposedHelpers.setObjectField(flag2obj,"flag","urlsec");
                }
            });
        };
    }
}

4. Hook 一般函数

1. 一般Java函数的hook

无论是public,还是private,还是static都可以用findAndHookMethod

ClassLoader classLoader = loadPackageParam.classLoader;
Class clazz = XposedHelpers.findClass("com.xiaopang.xposedhook01.Student",classLoader);
XposedHelpers.findAndHookMethod(clazz, "publicstaticfunc", String.class, int.class, new XC_MethodHook() {
    @Override
    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
        super.beforeHookedMethod(param);
        Object[] objectarray = param.args;
        String arg0 = (String) objectarray[0];
        int arg1 = (int)objectarray[1];
        XposedBridge.log("beforeHookedMethod publicstaticfunc ->arg0:" + arg0 + "--arg1:" + arg1);
        // 修改
        // objectarray[0] = "weixin:cjh-18888";

    }

    @Override
    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
        super.afterHookedMethod(param);
        String result = (String) param.getResult();
        // 修改返回值
        // param.setResult("weixin:cjh-18888");
        XposedBridge.log("afterHookedMethod publicstaticfunc->result:" + result );

    }
});

2. 内部类中的函数hook

使用美元符连接内部类


Class personClass = XposedHelpers.findClass("com.xiaopang.xposedhook01.Student$person", loadPackageParam.classLoader);
            XposedHelpers.findAndHookMethod(personClass, "getpersonname", String.class, new XC_MethodHook() {
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    super.beforeHookedMethod(param);
                    XposedBridge.log("beforeHookedMethod getpersonname->" + param.args[0]);
                }

                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    super.afterHookedMethod(param);
                    XposedBridge.log("afterHookedMethod getpersonname->" + param.getResult());
                }
            });

3. 匿名内部类函数的hook

匿名内部类其实主要还是找到classname. 匿名内部类一般都是

clssname$1,classname$2

然后就比较常规了

写累了,不想写了/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值