Xposed 插件开发之二: Xposed的一些知识
上一篇《Xposed 插件开发之一: Xposed入门》
一、 Api说明
IXposedHookLoadPackage
加载回调接口,在xposed入口类继承,实现handleLoadPackage(XC_LoadPackage.LoadPackageParam)
,这个方法用于在打开app的时候回调,参数LoadPackageParam
包含了加载的应用程序的一些基本信息。
IXposedHookInitPackageResources
加载回调接口,用于修改app的资源文件,在xposed入口类继承,实现handleInitPackageResources(InitPackageResourcesParam)
方法,用于在加载应用程序的包的时候执行用户的操作 ,参数InitPackageResourcesParam
包含了加载的应用程序的一些资源基本信息。
IXposedHookZygoteInit
加载回调接口,在xposed入口类继承,实现initZygote(IXposedHookZygoteInit.StartupParam)
,这个方法用于在开始hookApp的时候回调,参数StartupParam
包含了模块app的路径。
XposedHelpers.java
Xposed功能辅助类,里面提供了一些辅助方法,简化连接和调用方法/构造函数,获取和设置字段,这里直说重要的方法
findAndHookMethod: hook类中的某个方法
参数:
className: 要hook的方法的所在类
classloader: 要hook的包的classLoader,一般都写loadPackageParam.classLoader
methodName: 要hook的方法
parameterTypesAndCallback: 方法的参数和监听器。callMethod: 在目标app中调用方法
参数:
Object: 要调用方法的所在类
methodName: 要调用的方法名称
args: 方法的参数findClass: 获取class类实例
参数:
className: 类名
classLoader: 类加载器
XposedBridge.java
- log:在Xposed的app的日志功能里输出日志和/data/xposed/debug.log 这个文件中
参数
text: 要输出的内容
二、 Hook过程
Xposed 框架中真正起作用的是对方法的hook,hook到之后,在方法之前之后进行修改添加或者替换,那么寻找正确的目标方法名和所在的类名就很关键了。一般寻找目标方法有两种方法:
- 开源的直接查看源码,主要是系统应用
- 反编译查看源码,常见的有apkTool,jadx,jeb
1. Find
通过特定的类加载器加载要hook的类,通过反射找到被hook的成员。工具类XposedHelpers提供了一些工具方法来简化find过程;XposedBridge的hook*方法用于处理hook并执行回调。
XposedHelpers静态方法 | 描述 |
---|---|
findClass | 使用classLoader加载class |
findField | 通过反射查找类的数据成员并设置可访问性(setAccessible(true)) |
findMethod | 通过反射查找类的成员函数并设置可访问性 |
findConstructor | 通过反射查找类的构造函数并设置可访问性 |
setStatic | 通过反射设置类静态变量的值 |
set | 通过反射设置对象数据成员的值 |
findAndHook | 查找并hook |
2. Hook
XC_MethodHook中定义了回调方法:
- beforeHookedMethod(MethodHookParam param):被hook方法调用前执行,调用param.setResult可以跳过被hook的方法。
- afterHookedMethod(MethodHookParam param): 被hook方法调用后执行,调用param.setResult更改被hook方法的执行结果。
- replaceHookedMethod: 继承自XC_MethodReplacement,能替换Hook的方法
- XC_MethodReplacement: 继承自XC_MethodHook,通过在beforeHookedMethod中调用param.setResult实现了方法的替换。
@Override
protected final void beforeHookedMethod(MethodHookParam param) throws Throwable {try {Object result = replaceHookedMethod(param);param.setResult(result);} catch (Throwable t) {param.setThrowable(t);}
}
三、部分注意点和技巧
1. Hook内部类
通过美元符号 $ 连接内部类, 例如:
//获取ItemDecoration的类路径
String clsName = "androidx.recyclerview.widget.RecyclerView$ItemDecoration"
2. hook的方法
只能hook正常的方法,或者实现的方法或者构造方法,不能hook接口和抽象方法
3. context上下文获取
拿到之后可以用静态变量存放起来
try {Class<?> ContextClass = findClass("android.content.ContextWrapper", loadPackageParam.classLoader);findAndHookMethod(ContextClass, "getApplicationContext", new XC_MethodHook() {@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {super.afterHookedMethod(param);Context applicationContext = (Context) param.getResult();XposedBridge.log("得到上下文");}});
} catch (Throwable t) {XposedBridge.log("获取上下文出错"+t);
}
4. 获取控件
例如获取一个EditText,上一篇文章的例子,获取TextView,修改字符。。打开被hook的app就会发现文本变成了"我是被Xposed修改的啦"
public class Main implements IXposedHookLoadPackage {@Overridepublic void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {findAndHookMethod("com.tpnet.companycalc.MainActivity",loadPackageParam.classLoader,"onCreate",Bundle.class,new XC_MethodHook() {@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {//获取到当前hook的类,这里是MainActivityClass clazz = param.thisObject.getClass();XposedBridge.log("class name:" + clazz.getName());// 输入框不为私有private 可通过以下方式获取//Field field = clazz.getField("tvText");// 密码输入框对象变量名称// 通过反射获取控件,无论parivate或者publicField field = clazz.getDeclaredField("tvText");// 设置访问权限field.setAccessible(true);TextView textView = (TextView) field.get(param.thisObject);String string = textView.getText().toString();XposedBridge.log("原来的字符 : " + string);// 设置属性textView.setText("我是被Xposed修改的啦");}});}
}
5. 参数中有自定义类
通过反射获得得到自定义类
Class<?> hookMessageListenerClass = null;hookMessageListenerClass = lpparam.classLoader.loadClass("org.jivesoftware.smack.MessageListener");findAndHookMethod("org.jivesoftware.smack.ChatManager", lpparam.classLoader, "createChat", String.class , hookMessageListenerClass ,new XC_MethodHook() {@Overrideprotected void beforeHookedMethod(MethodHookParam param) throws Throwable {String sendTo = (String) param.args[0];}@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {super.afterHookedMethod(param);}
});
6. hook 构造方法
XposedBridge类里面的findAndHookConstructor方法
7.打开Activity
Activity activity = (Activity) param.thisObject;
Intent intent = new Intent();
intent.setClassName(activity,"com.ushaqi.zhuishushenqi.ui.home.HomeActivity");
activity.startActivity(intent);
8. 自定义接口的处理
当你想调用宿主app里面的一个方法,方法的参数是一个接口,接口不能new的,这时候应该怎么办? 使用Proxy.newProxyInstance
/**
* 生成接口实例
* @param loader 类加载器
* @param interface 接口的Class实例
* @param h 接口回调
* /
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
Xposed 插件开发之二: Xposed的一些知识相关推荐
- [Android开发] Xposed 插件开发之三: 编写广告去除插件
上一篇<Xposed 插件开发之二: Xposed的一些知识> 一. 准备 要去广告的app: 追杀神器3.75 反编译工具: AndroidKiller1.3.1 查看布局工具: UIA ...
- Xposed Xposed插件开发
Xposed插件开发 简单介绍 Xposed,大名鼎鼎得Xposed,是Android平台上最负盛名的一个框架.在这个框架下,我们可以加载很多插件App,这些插件App可以直接或间接操纵系统层面的东西 ...
- [免费专栏] Android安全之Android Xposed插件开发,小白都能看得懂的教程
也许每个人出生的时候都以为这世界都是为他一个人而存在的,当他发现自己错的时候,他便开始长大 少走了弯路,也就错过了风景,无论如何,感谢经历 Android安全付费专栏长期更新,本篇最新内容请前往: [ ...
- Xposed插件开发
Xposed插件开发(一)简单demo xposed下载地址:http://repo.xposed.info/module/de.robv.android.xposed.installer xpose ...
- Xposed插件开发手册(1): Xposed框架的安装
前言 之前我写了一篇文章<定制ROM采坑之路(2):魔趣OS刷入小米5A手机过程详解>,在进行成功刷机后,我尝试将Xposed框架安装到我新刷的系统中了.因为我这里的操作是基于魔趣OS的, ...
- Xposed插件开发手册(2):Xposed插件开发入门
前言 在上一篇文章<Xposed插件开发手册(1): Xposed框架的安装>,我们学习到了Xposed的安装,这篇文章我们就来做一个简单的Xposed模块,劫持我们写的App,整篇文章我 ...
- Idea插件开发(二)——插件的创建打包及发布
Idea插件开发(一)--插件的分类及基础认识 Idea插件开发(二)--插件的创建打包及发布 Idea插件开发(三)--插件JSL的完整开发过程 上一篇简单介绍了插件的基本知识,接下来直接上手开发, ...
- android8 检测xposed,Xposed检测与自定义Xposed
Xposed检测与自定义Xposed 前言: Xposed检测 1.遍历App安装列表检测 2.自造异常检测堆栈信息. 3.检查关键Java方法是否变为native方法 4.反射XposedHelpe ...
- Xposed源码剖析——Xposed初始化
承接上文 http://blog.csdn.net/yzzst/article/details/47829657 之前我们看过了app_main.cpp源码,知道了在其中,启动了XposedBridg ...
最新文章
- 揭秘@爱可可:“寂寞呆子”成长记
- java有不过_不过而而
- 省内转学出错的解决办法
- SpringBoot随笔
- python实现基于八方向判断的断裂连接
- Vue多个组件映射到同一个组件,页面不刷新?
- git status清空_本地删除文件后,git status会显示红色的那个文件。
- es6 Reflect对象的静态方法
- cortex a7 a53_西昊人体工学椅A7开箱测评
- C#.NET验证码智能识别学习笔记---03#.Net中@符号的意思
- JQuery------jQuery.parseHTML()的使用方法
- SpringHttpInvoker解析3-客户端实现
- CMMI认证是什么,级别分类有哪些?
- 通俗易懂物联网(11):物联网解决方案设计
- java 获取剪切板文件_如何在Java程序中读写系统剪切板的数据
- ai杀手级_设计师的10个杀手级Adobe Photoshop技巧
- html 灯箱效果样式,jQuery灯箱效果插件-Swipebox
- MATLAB clc clear
- 12C新特性--Application Continuity
- PTA习题【python】 6-8 jmu-python-发牌
热门文章
- 这10句诗,满满都是“江湖气”!
- AI产业链的划分,主要可分为基础层、技术层和应用层
- Python之——获取电脑连接过的所有wifi名称和密码
- 突然就看懂了《大话西游》
- 有人说“星座对自己的运势预测和性格描述很准”。请谈读你的看法。 “星座热”的社会学解读
- 2022苏州市人力资源服务业四项评比结果公布,盖雅榜上有名
- Parabola 抛物线-简单公式实现
- 【电脑自动关机】开机后Mysql再也启动不起来了。问题解决
- 总结:阿里云学生服务器地址/条件/续费等问题及解答FAQ
- 拼多多销售数据分析主要包含哪些方面的数据?