avatar

目录
Xposed学习笔记(1)

通过jadx-gui 打开 demo APP,查看代码,进行xposed Hook Api 实验


Xposed Hook Api 笔记

Api说明

1.IXposedHookLoadPackage.java

加载回调接口,在xposed入口类继承,实现handleLoadPackage方法

  • handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam)
    这个方法用于在加载应用程序的包的时候执行用户的操作
    参数:
    LoadPackageParam loadPackageParam: 这个参数包含了加载的应用程序的一些基本信息

2.IXposedHookInitPackageResources.java

加载回调接口,用于修改app的资源文件,在xposed入口类继承,实现handleInitPackageResources(InitPackageResourcesParam resparam)方法

  • handleInitPackageResources(InitPackageResourcesParam resparam)
    这个方法用于在加载应用程序的包的时候执行用户的操作
    参数:
    InitPackageResourcesParam resparam: 这个参数包含了加载的应用程序的一些资源基本信息

3.XposedHelpers.java

一些辅助方法,简化连接和调用方法/构造函数,获取和设置字段,这里直说重要的方法

  • findAndHookMethod(String className, ClassLoader classLoader, String methodName, Object… parameterTypesAndCallback)
    hook一个类中的方法
    参数:
    className: 要hook的方法的所在类
    classloader: 要hook的包的classLoader,一般都写loadPackageParam.classLoader
    methodName: 要hook的方法
    parameterTypesAndCallback: 方法的参数和监听器。

  • callMethod(Object obj, String methodName, Object… args)
    在目标app中调用方法
    参数:
    Object: 要调用方法的所在类
    methodName: 要调用的方法名称
    args: 方法的参数

  • findClass(String className, ClassLoader classLoader)
    获取class类实例
    参数:
    className: 类名
    classLoader: 类加载器

4.XposedBridge.java

  • log(String text)
    在Xposed的app的日志功能里输出日志和/data/xposed/debug.log 这个文件中
    参数:
    text: 要输出的内容

导入库

java
1
2
3
4
5
6
7
8
9
10
11
12
13
package com.example.testxp;


import android.util.Log;

import java.security.PublicKey;
import java.util.Map;

import de.robv.android.xposed.IXposedHookLoadPackage;//在包加载时刻hook,此时可以hook用户app的函数
import de.robv.android.xposed.XC_MethodHook;//为插件提供hook接口(java层实现)
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;//提供反射能力
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;//暴力列举Package下所有的方法

构造函数

通过特定的类加载器加载要hook的类,通过反射找到被hook的成员。工具类XposedHelpers提供了一些工具方法来简化find过程;XposedBridge的hook*方法用于处理hook并执行回调。

XposedHelpers静态方法 描述
findClass 使用classLoader加载class
findField* 通过反射查找类的数据成员并设置可访问性(setAccessible(true))
findMethod* 通过反射查找类的成员函数并设置可访问性
findConstructor* 通过反射查找类的构造函数并设置可访问性
setStatic* 通过反射设置类静态变量的值
set* 通过反射设置对象数据成员的值
findAndHook* 查找并hook
java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class Hello implements IXposedHookLoadPackage {
public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {

Log.d("KeyboArd", "hook...");

if(lpparam.packageName.equals("com.xiaojianbang.xposeddemo")){
final Class clazz = XposedHelpers.findClass("com.xiaojianbang.xposeddemo.Demo",lpparam.classLoader);
XposedHelpers.setStaticIntField(clazz,"staticInt",10000);
XposedHelpers.setStaticObjectField(clazz,"Tag","KeyboArd");

XposedHelpers.findAndHookConstructor(clazz,new XC_MethodHook(){
public void beforeHookedMethod(MethodHookParam param) throws Throwable{
Log.d("KeyboArd","无参构造函数前");
}

public void afterHookedMethod(MethodHookParam param)throws Throwable{
Log.d("KeyboArd","无参构造函数后");
}
});
XposedHelpers.findAndHookConstructor(clazz, String.class, new XC_MethodHook() {
public void beforeHookedMethod(MethodHookParam param) throws Throwable{
param.args[0]= "Wrpzkb";
}

public void afterHookedMethod(MethodHookParam param) throws Throwable{
Log.d("KeyboArd","有参构造函数后");
}
});

Throwable基本方法

getMessage()

•获取异常信息,返回字符串。

toString()

•获取异常类名和异常信息,返回字符串。

printStackTrace()

•获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void。

printStackTrace(PrintStream s)

•通常用该方法将异常内容保存在日志文件中,以便查阅。

throws和throw

throws

•用在方法声明后面,跟的是异常类名

•可以跟多个异常类名,用逗号隔开

•表示抛出异常,由该方法的调用者来处理

•throws表示出现异常的一种可能性,并不一定会发生这些异常

java 中字符串也算对象,所以要用equals来比较字符串。

这里首先判断包名是否等于com.xiaojianbang.xposeddemo,findclass搜索类,通过classLoader加载class,通过反射设置修改staticint的值和Tag的字符串。

java
1
2
3
4
if(lpparam.packageName.equals("com.xiaojianbang.xposeddemo")){
final Class clazz = XposedHelpers.findClass("com.xiaojianbang.xposeddemo.Demo",lpparam.classLoader);//返回一个类的字节码
XposedHelpers.setStaticIntField(clazz,"staticInt",10000);
XposedHelpers.setStaticObjectField(clazz,"Tag","KeyboArd");


XC_MethodHook回调方法:

beforeHookedMethod(MethodHookParam param):被hook方法调用前执行,调用param.setResult可以跳过被hook的方法。
afterHookedMethod(MethodHookParam param): 被hook方法调用后执行,调用param.setResult更改被hook方法的执行结果。
replaceHookedMethod 继承自XC_MethodReplacement,能替换Hook的方法

MethodHookParam param回调参数:

对于回调过来的参数MethodHookParam param一般有以下2种用处:
1.param.args[0]:得到被拦截方法的第一个参数,返回值是Object
2.param.getResult():得到被拦截方法的执行结果,返回值是Object

Constructor构造的意思

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
XposedHelpers.findAndHookConstructor(clazz,new XC_MethodHook(){
public void beforeHookedMethod(MethodHookParam param) throws Throwable{
Log.d("KeyboArd","无参构造函数前");
}

public void afterHookedMethod(MethodHookParam param)throws Throwable{
Log.d("KeyboArd","无参构造函数后");
}
});
XposedHelpers.findAndHookConstructor(clazz, String.class, new XC_MethodHook() {
public void beforeHookedMethod(MethodHookParam param) throws Throwable{
param.args[0]= "Wrpzkb";
}

public void afterHookedMethod(MethodHookParam param) throws Throwable{
Log.d("KeyboArd","有参构造函数后");
}
});

生成软件,看下输出的值。


Hook 函数

findAndHookMethod 有两种,一种是传入类的字节码,要HOOK的方法名,和方法列表和一个回调函数,有三个… 说明是可变参数。

java
1
2
3
public static Unhook findAndHookMethod(Class<?> clazz, String methodName, Object... parameterTypesAndCallback) {
throw new RuntimeException("Stub!");
}

一种是传入类名字符串,类加载器,方法名和方法列表和一个回调函数

java
1
2
3
public static Unhook findAndHookMethod(String className, ClassLoader classLoader, String methodName, Object... parameterTypesAndCallback) {
throw new RuntimeException("Stub!");
}

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
XposedHelpers.findAndHookMethod(clazz,//类的字节码
"publicFunc",//要Hook的方法名
String.class,//不能直接给类型,给参数类型的字节码
new XC_MethodHook(){//回调函数
public void beforeHookedMethod(MethodHookParam param) throws Throwable{
Log.d("KeyboArd",""+param.args[0]);

Log.d("KeyboArd","publicFunc is hooked before");
}

public void afterHookedMethod(MethodHookParam param) throws Throwable{
Log.d("KeyboArd",""+param.getResult());
Log.d("KeyboArd","public is hooked after");
}
});

要被Hook的函数:


多参数函数Hook

Class.forName要求JVM查找并加载指定的类,也就是说JVM会执行该类的静态代码段。并返回与该类相关的Class对象。

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
XposedHelpers.findAndHookMethod(clazz,//类的字节码
"complexParameterFunc",//要Hook的函数
"java.lang.String",//参数1 把类的完整路径写进去,通过api通过路径寻找字节码
"[[Ljava.land.String;",//参数2 [[ 表示二维数组,L表示他是一个对象,不是一个基本类型
Map.class,//参数3
Class.forName("java.util.ArrayList"),//参数4
new XC_MethodHook() {//回调函数

public void beforeHookedMethod(MethodHookParam param) throws Throwable{
Log.d("KeyboArd","complexParameterFunc is hooked before1");
}

public void afterHookedMethod(MethodHookParam param) throws Throwable{
Log.d("KeyboArd","complexParamterFunc is hooked after1");
}
});

另一种写法

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//String str, String[][] strArr, Map<String, String> map, ArrayList arrayList
XposedHelpers.findAndHookMethod(clazz,//类的字节码
"complexParameterFunc",//要Hook的函数
String.class,//参数1
String[][].class,//参数2
Map.class,//参数3
ArrayList.class,//参数4
new XC_MethodHook() {//回调函数

public void beforeHookedMethod(MethodHookParam param) throws Throwable{
Log.d("KeyboArd","complexParameterFunc is hooked before1");
}

public void afterHookedMethod(MethodHookParam param) throws Throwable{
Log.d("KeyboArd","complexParamterFunc is hooked after1");
}
});

其他类Hook

java
1
2
3
4
5
6
7
8
9
10
Class cls = Class.forName("com.xiaojianbang.xposeddemo.Animal",true,lpparam.classLoader);
XposedHelpers.findAndHookMethod(clazz,
"Inner",
cls,
String.class,
new XC_MethodHook() {
public void beforeHookedMethod(MethodHookParam param) throws Throwable{
Log.d("KeyboArd","这是自定义类参数的Hook Class.forName1");
}
});

另一种写法

java
1
2
3
4
5
6
7
8
9
10
final Class cls = XposedHelpers.findClass("com.xiaojianbang.xposeddemo.Animal",lpparam.classLoader);
XposedHelpers.findAndHookMethod(clazz,
"Inner",
cls,
String.class,
new XC_MethodHook() {
public void beforeHookedMethod(MethodHookParam param) throws Throwable{
Log.d("KeyboArd","这是自定义类参数的Hook Class.forName1");
}
});

替换

java
1
2
3
4
5
6
XposedHelpers.findAndHookMethod(clazz, "replaceFunc", new XC_MethodReplacement() {
public Object replaceHookedMethod(MethodHookParam methodHookParam)throws Throwable{
Log.d("KeyboArd","这是替换之后的输出");
return null;
}
});


内部类

getIntField获取字段

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
XposedHelpers.findAndHookMethod(
XposedHelpers.findClass("com.xiaojianbang.xposeddemo.Demo$InnerClass", lpparam.classLoader),
"innerFunc",
String.class,
new XC_MethodHook(){
public void beforeHookedMethod(MethodHookParam param) throws Throwable{
Log.d("KeyboArd","qian");
XposedHelpers.callMethod(clazz.newInstance(),"refl");//主动调用
Log.d("KeyboArd","hou");

int aa = XposedHelpers.getIntField(param.thisObject,"innerPublicInt");//内部类
StringBuilder sb = new StringBuilder();
Log.d("KeyboArd",""+aa);
}
});


结尾

Xposed 的API学习到此结束🔚

准备上班,做检疫人员,唉,又要去面对jiangxi人了,看见就烦,每天都十万个为什么。

为什么给你看身份证

为什么给你看出入证

为什么要戴口罩

为什么要给你看车尾箱

真是牛逼。

想知道这么多为什么,就多读点书。garbage人

文章作者: KeyboArd
文章链接: https://www.wrpzkb.cn/xposed/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 KeyboArd's Blog
打赏
  • 微信
    微信
  • 支付寶
    支付寶

评论