xposed 02 - 模块编写与构造函数Hook

本文讨论一下xposed模块编写的步骤,与如何hook构造函数,以及一些需要注意的地方。

Xposed模块编写

跟把大象放冰箱分3步一样,编写xposed模块只需要4步。

第一步

拷贝 XposedBridgeApi.jar 到模块工程的 libs 目录下,放一个 jar 下载链接,其实也可以去作者仓库下载源码自己编译一个jar

https://github.com/bywhat/XposedBridgeApi

https://github.com/rovo89/XposedBridge

第二步

修改 build.gradle 目录,将 libs 下的 jar 添加依赖

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

修改 AndroidManifest.xml,在  application 的标签下添加如下 mate 信息:

<application
    android:allowBackup="true"
    android:dataExtractionRules="@xml/data_extraction_rules"
    android:fullBackupContent="@xml/backup_rules"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/Theme.EdxposedTest"
    tools:targetApi="31" >

    <meta-data
        android:name="xposedmodule"
        android:value="true" />

    <meta-data
        android:name="xposeddescription"
        android:value="edxposed hook learning" />

    <meta-data
        android:name="xposedminversion"
        android:value="54" />

</application>

xposedmodule 表示该apk是不是一个 xposed 模块,肯定要填 true。

xposeddescription 这个描述信息会展示到模块列表的模块信息里面。

xposedminversion 最小的版本,与 libs 下使用的版本一致即可。

第三步

新建一个 hook 类(入口类),入口类必须是 public 的,否则会出现无法访问错误,入口类需要实现 IXposedHookLoadPackage 接口:

public class Xposed01 implements IXposedHookLoadPackage {

    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
        ...
    }

}

第四步

建立 assets 目录,在 assets 目录下新建文件 xposed_init 文件,在里面声明你在第3步写的入口类。可以声明多个,优先级是按照编写顺序,也就是哪个先声明,就先生效。

com.example.edxposedtest.Xposed01

Hook 构造函数

以下面这个例子为演示,演示代码已传递到 p22。

package com.example.hooktarge

class HookTarget1 constructor(private val str: String, val id: Long ) {

    constructor() :this("", 0)

    override fun toString(): String {
        return "HookTarget1(str='$str', id=$id)"
    }

}

这里我们写了两个构造函数。我们针对这2个构造函数进行测试。分为两方面的测试,一个是无参数的构造函数,一个是有参数的构造函数。

hook构造参数有两个 api:

public static XC_MethodHook.Unhook findAndHookConstructor(Class<?> clazz, Object... parameterTypesAndCallback) {
    if (parameterTypesAndCallback.length != 0 && parameterTypesAndCallback[parameterTypesAndCallback.length - 1] instanceof XC_MethodHook) {
        XC_MethodHook callback = (XC_MethodHook)parameterTypesAndCallback[parameterTypesAndCallback.length - 1];
        Constructor<?> m = findConstructorExact(clazz, getParameterClasses(clazz.getClassLoader(), parameterTypesAndCallback));
        return XposedBridge.hookMethod(m, callback);
    } else {
        throw new IllegalArgumentException("no callback defined");
    }
}

public static XC_MethodHook.Unhook findAndHookConstructor(String className, ClassLoader classLoader, Object... parameterTypesAndCallback) {
    return findAndHookConstructor(findClass(className, classLoader), parameterTypesAndCallback);
}

可以看到,实际上第二个 api 也是使用了第一个 api。

所以当我们可以直接获取到 hook 类的 class 时,那么就使用第一个 api 更简单,否则使用第二个 api。对于一些加壳的 apk 或者动态加载的 类,我们需要传递特定的 classloader 才能正确的找到类,此时只能使用第二个 api。

hook无参构造函数

XposedHelpers.findAndHookConstructor("com.example.hooktarge.HookTarget1", loadPackageParam.classLoader, new XC_MethodHook() {
    @Override
    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
        super.beforeHookedMethod(param);
        Log.e("Xposed01", "no params beforeHookedMethod");
    }

    @Override
    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
        super.afterHookedMethod(param);
        Log.e("Xposed01", "no params afterHookedMethod");
    }
});

由于是 hook 构造方法,所以最后一个参数,我们使用 XC_MethodHook。

它有两个接口方法:

  • beforeHookedMethod 在方法调用之前执行

  • afterHookedMethod 在方法调用之后执行

hook 有参构造函数

其实代码也是与上面差不过的,我们可以先看一下 MethodHookParam 这个类的字段:

// 方法
public Member method;
// 方法所属的对象
public Object thisObject;
// 方法的参数
public Object[] args;
// 方法返回值
private Object result = null;

有了这些字段,我们就可以修改构造函数的参数传递。

同时,parameterTypesAndCallback 这个参数的名字也暗示了hook有参数的方法,需要传递参数类型:

XposedHelpers.findAndHookConstructor("com.example.hooktarge.HookTarget1", loadPackageParam.classLoader, String.class, long.class, new XC_MethodHook() {
    @Override
    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
        super.beforeHookedMethod(param);
        Log.e("Xposed01", "params beforeHookedMethod");
        param.args[0] = "abd";
        param.args[1] = 42;
    }

    @Override
    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
        super.afterHookedMethod(param);
        Log.e("Xposed01", "params afterHookedMethod");
        Log.e("Xposed01", "thisObject = " + param.thisObject);
        Log.e("Xposed01", "getResult = " + param.getResult());
    }
});

在 app 里面调用一下这些构造函数:

HookTarget1()
HookTarget1("a5right", 1)

安装 app 与 模块,我们运行一下看看效果:

E  no params beforeHookedMethod
E  params beforeHookedMethod
E  params afterHookedMethod
E  thisObject = HookTarget1(str='abd', id=42)
E  getResult = null
E  no params afterHookedMethod
E  params beforeHookedMethod
E  params afterHookedMethod
E  thisObject = HookTarget1(str='abd', id=42)
E  getResult = null

可以看到,无参构造函数触发了有参构造函数的调用。

我们在hook代码中修改的参数也生效了。

同时还需要注意到,getResult 返回了空,说明了构造函数是没有返回值的。这个应该好理解,之前在写JVM的时候,就学习过了,new 分两步,第一步分配空间,第二步初始化这个对象:

MyObject obj = allocateInstance(MyObjcet.class);
obj.<init>;

所以,如果有需要,请在构造函数的 hook 中使用 thisObject,而不是 getResult。

重新修改代码后,需要在 edposed manager 的module里面的开关,重新关闭再打开后生效,如果未生效,尝试重启。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/269075.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Unity 根据 数字 让 显示游戏总时长的txt直接显示该个 时间时分秒显示方法

Unity 根据 数字 让 显示游戏总时长的txt直接显示该个 时间时分秒显示方法 效果如下&#xff1a; 上代码 void Update(){int timeER int.Parse((txt_gameTimesER - Time.deltaTime).ToString("00"));Set_All_PlayTime_txtLookTime(timeER,bg.txt_LastTime); }/// &…

c 语言学习:输出阶乘的算式

c 语言学习&#xff1a;输出阶乘的算式 代码 #include "stdio.h"int fact(int num){if (num < 1){printf("1 ");return 1;} else {printf("%d x ",num);return num * fact(num-1);} }int main(){int num 10; // printf("plz inpu…

[Latex写作] vscode搭建latex写作环境

个人博客:Sekyoro的博客小屋 个人网站:Proanimer的个人网站 如果是为了方便简洁,实际使用Overleaf完全够了,之前也写过使用Obsidian写文章的教程. 这次主要介绍使用在本地vscode加上插件写论文. 需要工具 vscode 官网即可texlive 通过镜像站即可,比如Index of /CTAN/systems…

类和对象的创建和实例化

1. 类的概述 1.1 具体示例 类是描述一类事物的特征和行为的统称&#xff0c;抽象的不存在的&#xff0c;泛指的概念&#xff0c;例如&#xff1a;描述一个人&#xff0c;从外观上&#xff08;特征&#xff09;和言行举止&#xff08;行为&#xff09;上进行描述外观上&#xff…

智能安全配电装置在临时展会场所中的应用

贾丽丽 安科瑞电气股份有限公司 上海嘉定 201801 【摘要】简述了商场临时展会、展摊等场所中电气装置用电的特性&#xff0c;针对此类场所中隐含的电气安全隐患问题&#xff0c;结合智能安全配电装置的功能&#xff0c;从用电设备的接地、线路的安装与敷设、设备的维护和管理…

LaTex插入图片

一、插入图片 在.tex文件开头导入相应的宏包 \documentclass{article} \usepackage{graphicx} % 导入图像的宏包、单图 \usepackage{subfigure} % 导入图像的宏包、子图 \graphicspath{{./images/}} % 告诉 LaTeX 这篇文档中的图片所存储的位置是主文档所在目录下的 images 文…

【XR806开发板试用】系列之二:出现已经成功编译,但是无法生成镜像文件的问题

本文主要对于编译成功但是烧录出现问题进行解决&#xff0c;用Hello world 和LED点亮代码作为示范 文章仅为参考网络资料和自身理解&#xff0c;如有不正确之处请多指正 首先确定自己根目录在哪&#xff0c;我们都在根目录进行hb set和hb build -f,判断方法是寻找ohos_config.…

为什么要出现并发?并发的三要素

大家好&#xff0c;我是"java继父"伯约&#xff0c;假如这篇对大家有帮助的话求一个赞&#xff0c;另外文章末尾放了我从小白到架构师多年的学习资料。 1.为什么需要多线程 众所周知&#xff0c;CPU、内存、I/O 设备的速度是有极大差异的&#xff0c;为了合理利用 C…

CentOS环境下Nacos2.3集成PostgreSQL

title: CentOS环境下Nacos2.3集成PostgreSQL date: 2023-12-21 19:15:00 categories: Nacos description: CentOS环境下Nacos2.3集成PostgreSQL 1. 目录 1. 目录2. 简介3. 安装部署 3.1. 部署模式3.2. 环境准备3.3. 下载安装文件3.4. PostgreSQL插件 3.4.1. 下载地址3.4.2. 结…

圆中点算法

中心在原点&#xff0c;半径为 R 的圆的隐式函数方程为 F ( x , y ) x 2 y 2 − R 2 0 F(x, y) x^2 y^2 - R^2 0 F(x,y)x2y2−R20 把像素上的点的坐标代入上述隐式方程 八分法画圆算法 利用坐标轴和与坐标轴夹角 45 度的直线 原理 假设圆弧起点 x 0 x0 x0&#xff0…

经典文献阅读之--RenderOcc(使用2D标签训练多视图3D Occupancy模型)

0. 简介 3D占据预测在机器人感知和自动驾驶领域具有重要的潜力&#xff0c;它将3D场景量化为带有语义标签的网格单元。最近的研究主要利用3D体素空间中的完整占据标签进行监督。然而&#xff0c;昂贵的注释过程和有时模糊的标签严重限制了3D占据模型的可用性和可扩展性。为了解…

SQL Server的权限设置

实验环境&#xff08;实验案例一&#xff09; 某公司部署了 SQL Server 2016用来存储网站数据&#xff0c;由系统管理员进行维护.在bdon数据库中 已创建了class表。 需求描述 赋予用户zhangsan在bdqn数据库中创建表的权限和对class表查询和更新数据的权限。

ASP.NET Core 中的应用启动

ASP.NET Core 中的应用启动 | Microsoft Learnhttps://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/startup?viewaspnetcore-8.0 目录 使用 Startup 筛选器扩展 Startup 在启动时从外部程序集添加配置 Startup、ConfigureServices 和 Configure 作者&#xff1a;…

每日一题——LeetCode141.环形链表

个人主页&#xff1a;白日依山璟 专栏&#xff1a;Java|数据结构与算法|每日一题 文章目录 1. 题目描述示例1&#xff1a;示例2&#xff1a;示例3&#xff1a;提示: 2. 思路3. 代码 1. 题目描述 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某…

041、基于CNN的样式迁移

之——基于CNN的滤镜 目录 之——基于CNN的滤镜 杂谈 正文 1.基于CNN的样式迁移 2.实现 杂谈 通过CNN的特征提取&#xff0c;可以实现将一个图片的样式模式特征迁移到另一张图像上。 正文 1.基于CNN的样式迁移 就是在某些层的输出上用其他的图片进行监督。 2.实现 一般来…

国际会议口译,选择同传好还是交传好

在国际会议中&#xff0c;同传与交传是常见的两种翻译方式&#xff0c;它们各自承载着独特的使命与优势&#xff0c;为沟通世界发挥着不可替代的作用。那么&#xff0c;同传好还是交传好&#xff0c;如何选择合适的翻译方式&#xff1f; 首先&#xff0c;从费用角度来看&#x…

苹果怎么调字体大小?详细教程在这,赶快get起来!

在我们使用苹果手机时&#xff0c;可能会遇到需要调整字体大小的情况。合适的字体大小能够提高阅读体验和舒适度&#xff0c;使得手机使用更加便捷。然而&#xff0c;还有很多用户并不知道苹果怎么调字体大小。别着急&#xff01;本文将为您详细介绍操作方法&#xff0c;帮助您…

云计算与大数据之间的羁绊(期末不挂科版):云计算 | 大数据 | Hadoop | HDFS | MapReduce | Hive | Spark

文章目录 前言&#xff1a;一、云计算1.1 云计算的基本思想1.2 云计算概述——什么是云计算&#xff1f;1.3 云计算的基本特征1.4 云计算的部署模式1.5 云服务1.6 云计算的关键技术——虚拟化技术1.6.1 虚拟化的好处1.6.2 虚拟化技术的应用——12306使用阿里云避免了高峰期的崩…

selenium模块有哪些用途?

Selenium模块是一个用于Web应用程序测试的模块&#xff0c;具有多种示例用法。以下是一些示例&#xff1a; 1.打开网页并执行一些基本操作&#xff0c;如点击按钮、输入文本等。 定位网页元素并执行操作&#xff0c;例如使用 find_element 方法查找单个元素&#xff0c;使用 f…

zabbix-邮件告警与钉钉机器人告警

zabbix-邮件告警 在部署邮件告警前需要先将zabbix部署成功 邮件告警需要得到邮箱的授权码&#xff0c;这里将以qq邮箱为例。 1.获取邮箱的授权码 2.编辑Email的相关信息 3.测试Email是否配置成功 测试成功。 4.为用户添加邮箱报警服务 5.创建主机群组、主机、监视项、触…