Xposed模块编写

参考:

https://www.52pojie.cn/thread-1740944-1-1.html

https://www.52pojie.cn/thread-1748081-1-1.html

环境配置

电脑端准备

1.官网下载相关jar包

https://github.com/bywhat/XposedBridgeApi/blob/main/XposedBridgeAPI-82.jar

2.将jar包导入到android工程中

  • 项目下创建libs目录,将jar包导入
  • 配置gradle,直接在build.gradledependencies下添加即可
compileOnly(files("libs/XposedBridgeAPI-82.jar"))

3.配置项目

  • AndroidManifest.xml下的application添加下面元数据
<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/Theme.Test" >
<meta-data android:name="xposedmodule"
android:value="true" />
<meta-data android:name="xposeddescription"
android:value="My test xposed" />
<meta-data android:name="xposedminversion"
android:value="82" />
<!-- 根据版本号 -->
</application>
  • main目录下添加assets/xposed_init文件,文件中写入口类名
com.example.xposed.MyXposed

4.在配置好的类中愉快的hook

public class MyXposed implements IXposedHookLoadPackage {  

    @Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
XposedBridge.log("MytagIs:" + loadPackageParam.packageName);
}
}
手机端

1.用Magisk Root手机并在设置中开启zygisk

2.下载Lsposed

https://github.com/LSPosed/LSPosed

3.在Magisk 模块安装Lsposed zygisk版的发行压缩包

Xposed

类的路径
外部类:com.zj.wuaipojie.Demo
内部类:com.zj.wuaipojie.Demo$inner
hook函数

用回调函数XC_MethodHook来修改传入参数和返回值

常规函数

XposedHelpers.findAndHookMethod("com.zj.wuaipojie.Demo", loadPackageParam.classLoader, "a", "java.lang.String", new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
//获取参数
Log.d("zj2595", param.args[0].toString());
//设置传入参数
param.args[0] = "hook普通参数";
Log.d("zj2595", param.args[0].toString());
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
//获取返回值
Log.d("zj2595", param.getResult().toString());
//设置返回值
param.setResult("我hook普通返回");
}
});

hook复杂/自定义方法

Class<?> clazz = loadPackageParam.classLoader.loadClass("com.zj.wuaipojie.Demo");
XposedBridge.hookAllMethods(clazz, "complexParameterFunc", new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
Log.d("zj2595", param.args[0].toString());
param.args[0] = "hook复杂参数";
Log.d("zj2595", param.args[0].toString());
} @Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
Log.d("zj2595", param.getResult().toString());
param.setResult("我hook复杂返回");
}
});

用回调函数XC_MethodReplacement来替换该函数

替换函数

Class<?> clazz = loadPackageParam.classLoader.loadClass("com.zj.wuaipojie.Demo");
XposedBridge.hookAllMethods(clazz, "repleaceFunc", new XC_MethodReplacement() { @Override
protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
Log.d("zj2595", "我将函数替换了");
return null;
}
});

加固后函数


构造函数

通过签名区分

XposedBridge.hookAllConstructors(clazz, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
Constructor<?> constructor = (Constructor<?>) param.method;
Class<?>[] parameterTypes = constructor.getParameterTypes();
Log.d("zj2595", "构造" + Arrays.toString(parameterTypes));
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param); } });

直接hook特定函数

XposedHelpers.findAndHookConstructor("com.zj.wuaipojie.Demo", loadPackageParam.classLoader, "java.lang.String", new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
Log.d("zj2595", "hook str构造函数");
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
}
}); XposedHelpers.findAndHookConstructor("com.zj.wuaipojie.Demo", loadPackageParam.classLoader, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
Log.d("zj2595", "hook 空参构造函数");
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
}
});

Dex


hook变量

静态成员变量

final Class<?> clazz = loadPackageParam.classLoader.loadClass("com.zj.wuaipojie.Demo");
//获取静态成员变量
Log.i("zj2595", (String) XposedHelpers.getStaticObjectField(clazz, "staticField"));
//设置静态成员变量
XposedHelpers.setStaticObjectField(clazz, "staticField", "hook_static");

普通成员变量

要在构造函数运行后获取修改

final Class<?> clazz = loadPackageParam.classLoader.loadClass("com.zj.wuaipojie.Demo");
XposedBridge.hookAllConstructors(clazz, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
//获取成员变量
Log.d("zj2595", String.valueOf(XposedHelpers.getIntField(param.thisObject, "publicInt")));
//设置成员变量
XposedHelpers.setIntField(param.thisObject,"publicInt", 999);
}
});
方法调用

成员方法

final Class<?> clazz = loadPackageParam.classLoader.loadClass("com.zj.wuaipojie.Demo");
XposedHelpers.callMethod(clazz.newInstance(), "refl");

静态方法

final Class<?> clazz = loadPackageParam.classLoader.loadClass("com.zj.wuaipojie.Demo");
XposedHelpers.callStaticMethod(clazz.newInstance(), "staticrefl");
Xposed应用

遍历类下的所有方法

XposedHelpers.findAndHookMethod(ClassLoader.class, "loadClass", String.class, new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
Class<?> clazz = (Class<?>) param.getResult();
if(clazz.getName().contains("com.zj.wuaipojie")){
Method[] methods = clazz.getDeclaredMethods();
for(Method method : methods){
//排除抽象,本地,接口方法
if(!Modifier.isAbstract(method.getModifiers()) &&
!Modifier.isNative(method.getModifiers()) &&
!Modifier.isInterface(method.getModifiers())){
XposedBridge.hookMethod(method, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
Log.d("zj2595", method.toString());
}
});
}
}
}
}
});

字符串赋值定位

XposedBridge.hookAllMethods(TextView.class, "setText", new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
PrintStack();
}
});
//打印堆栈
private void PrintStack(){
Throwable ex = new Throwable();
StackTraceElement[] stacktrace = ex.getStackTrace();
for(StackTraceElement stack : stacktrace){
Log.d("zj2595", "line:" + stack.getLineNumber() + " class:" + stack.getClassName() + " method:" + stack.getMethodName() + " file:" + stack.getFileName() );
}
}

点击事件监听

XposedHelpers.findAndHookMethod(View.class, "setOnClickListener", View.OnClickListener.class,new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
Class<?> clazz = param.args[0].getClass();
if(clazz != null){
XposedHelpers.findAndHookMethod(clazz, "onClick", View.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
View view = (View)param.args[0];
Log.i("zj2595", String.format("Buttonid:0x%x",view.getId()));
}
});
}
}
});

修改布局

XposedHelpers.findAndHookMethod("com.zj.wuaipojie.ui.ChallengeSixth", loadPackageParam.classLoader, "onCreate", "android.os.Bundle", 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);
View view = (View)XposedHelpers.callMethod(param.thisObject, "findViewById", 0x7f0800de);
view.setVisibility(View.GONE);
}
});

LSposed hook(学习分享)的更多相关文章

  1. ElasticSearch 5学习(7)——分布式集群学习分享2

    前面主要学习了ElasticSearch分布式集群的存储过程中集群.节点和分片的知识(ElasticSearch 5学习(6)--分布式集群学习分享1),下面主要分享应对故障的一些实践. 应对故障 前 ...

  2. ElasticSearch 5学习(6)——分布式集群学习分享1

    在使用中我们把文档存入ElasticSearch,但是如果能够了解ElasticSearch内部是如何存储的,将会对我们学习ElasticSearch有很清晰的认识.本文中的所使用的ElasticSe ...

  3. MySQL学习分享--Thread pool实现

    基于<MySQL学习分享--Thread pool>对Thread pool架构设计的详细了解,本文主要对Thread pool的实现进行分析,并根据Mariadb和Percona提供的开 ...

  4. JavaScript Shell学习分享

    目录 JavaScript Shell学习分享 简介 安装 使用原因 小结 JavaScript Shell学习分享 简介 JavaScript Shell是由Mozilla提供的综合JavaScri ...

  5. python 学习分享-paramiko模块

    paramiko模块学习分享 paramiko是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接.paramiko支持Linux, Solaris, BS ...

  6. 有关JSOUP学习分享(一)

    其实现在用JSOUP爬虫的也不多了,但是由于最近换公司,做数据爬虫需要用到,就看了下,感觉还是挺好用的,原理什么的感觉和weblogic也差不到哪里去,废话少说,这里就简单的分享下最近接触的干货. J ...

  7. Swagger框架学习分享

    Swagger框架学习分享 转至元数据结尾 Created and last modified by 刘新宇 大约1分钟曾经 pageId=162045803#page-metadata-start& ...

  8. Flink 从0到1学习—— 分享四本 Flink 国外的书和二十多篇 Paper 论文

    前言 之前也分享了不少自己的文章,但是对于 Flink 来说,还是有不少新入门的朋友,这里给大家分享点 Flink 相关的资料(国外数据 pdf 和流处理相关的 Paper),期望可以帮你更好的理解 ...

  9. [torch] pytorch hook学习

    pytorch hook学习 register_hook import torch x = torch.Tensor([0,1,2,3]).requires_grad_() y = torch.Ten ...

  10. python paramiko模块学习分享

    python paramiko模块学习分享 paramiko是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接.paramiko支持Linux, Sola ...

随机推荐

  1. Q:CRON表达式,Linux和Java的不同写法

    CRON表达式是一个字符串,包含五个到七个由空格分隔的字段(每种软件不一样),表示一组时间,通常作为执行某个程序的时间表. 调度精度: Linux的cron调度精度为分钟级别,最小粒度为分钟,而Jav ...

  2. Linux mint的hadoop安装方法

    参考网址http://www.powerxing.com/install-hadoop/ 1.创建hadoop账户 这条命令创建了可以登陆的 hadoop 用户,并使用 /bin/bash 作为 sh ...

  3. 源码方式本地化部署deepseek和量化

    前置条件 1.python环境,安装教程:https://www.python.org/downloads/2.wsl环境(Windows系统),安装教程:https://learn.microsof ...

  4. kubsphere应用系列(三)-创建手动流水线

    准备工作 1.1 创建凭证 1.2 添加代码仓库 第一步创建流水线   第二步配置流水线 1.1选择CI/CD模板 1.2删除多余阶段 1.3 配置git仓库信息     1.4配置docker仓库信 ...

  5. Spark - [03] RDD概述

    RDD,分布式数据集,是Spark中最基本的数据抽象. 一.什么是RDD RDD(Resilient Distributed Dataset)叫做分布式数据集,是 Spark 中最基本的数据抽象. 代 ...

  6. ES - 概述

    前言 Q1:ElasticSearch 是什么? 为什么要学习? ElasticSearch 是一个分布式.可扩展.实时的搜索和分析引擎,基于 Lucene 构建.它可以用于全文搜索.结构化搜索.分析 ...

  7. Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!

    在众多开源项目中,高颜值.功能强大且部署简单的项目往往更能俘获开发者的心.然而,实际部署 Web 应用时,面对数据库.缓存.消息队列等复杂的依赖关系,常常令人头疼.Docker 的开源为我们普及了容器 ...

  8. ADO.NET中SQL绑定变量方式总结

    最近在项目上遇到几个问题,关于ADO.NET中SQL绑定变量 总结一下,分享给大家. 1. 使用 SqlParameter(推荐方式,防止 SQL 注入) ADO.NET 提供 SqlParamete ...

  9. mongodb查询某个字段数据

    如下 db.集合名.find( {}, {需要查询的字段:1, _id:0} ) 例如 db.userInfo.find({}, {'created_at':1, _id: 0}) 默认会显示 _id ...

  10. docker搭建本地仓库

    环境准备: 服务器:9.134.130.35 私有仓库服务器,运行registry容器 客户端:9.208.244.175 测试客户端,用于上传.下载镜像文件 测试搭建本地仓库 mkdir /dock ...