Xposed——hook方法学习
Xposed是基于java层的hook框架,在不修改apk源码的情况下,编写自己的模块来改变apk的行为。以下总结了常见的Xposed的hook方法:
hook普通方法
创建一个类继承IXposedHookLoadPackage,修改 handleLoadPackage方法,首先要判断是否为特定的包。
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam Param) throws Throwable {
if(Param.packageName.equals("com.example.xposed_new3")){......}
}
hook普通方法调用的函数都是XposedHelpers.findAndHookMethod
XposedHelpers.findAndHookMethod(
className(包名+类名),
Param.classLoader(固定参数),
methodName(被hook的函数名)
**.class(函数的参数),
new XC_MethodHook(){}
)
XC_MethodHook方法详解
hook普通方法的主要作用是打印各种参数信息,或者修改某些参数使其直接通过程序。
hook匿名内部类
匿名内部类一般为普通方法,所以仍然用findAndHookMethod的hook方法。
注:匿名内部类辨别方法:在smali代码中一个类为一个文件,且匿名内部类后缀会加上”$”符号,在工程管理器中直接找出相关类。
Lcom/example/xposed_new4/MainActivity$1
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
if(loadPackageParam.packageName.equals("com.example.xposed_new4")){
XposedHelpers.findAndHookMethod(
"com.example.xposed_new4.MainActivity$1",
loadPackageParam.classLoader,
"onClick",
View.class,
new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
View v=(View)param.args[0];
XposedBridge.log("view:"+v.getId());
}
});
}
}
在findAndHookMethod方法中的包名类名参数使用smali代码中的包名加类名,其余操作与普通方法hook相同。
Xposed—java 反射
java反射主要作用为突破修饰符的限制,如获取私有方法和私有字段。
以hook某一私有控件为例
//获取类
Class<?> clazz=param.thisObject.getClass();
//获取字段
Field field=clazz.getDeclaredField("Text");
//设置可见
field.setAccessible(true);
EditText ed_sn= (EditText) field.get(param.thisObject);//把类中的控件参数传给ed_sn
XposedBridge.log("输入结果为:"+ed_sn.getText().toString().trim());
//修改编辑框
ed_sn.setText("L61q4_cheng");
hook某一私有方法
//获取方法
Method method=clazz.getDeclaredMethod("MethodName",new Class[]{.class,.class...});
//显示可见
method.setAccessible(true);
//调用方法
返回值=method.invoke(param.thisObject,new Object(){...});//调用函数的参数
hook主动调用
主动调用,直接调用apk中的函数来实现hook操作,方便对数据进行直接操作。主动调用函数为XposedHelpers。该方法一般用于获取某一数据来通过某一入口,而不是直接修改方法的返回值。Xposed通过主动调用可以直接使用Android项目中某些方法,使其可以有更强大的功能。
XposedHelpers方法详解
XposedHelpers.callMethod();//调用普通方法
XposedHelpers.callStaticMethod();//调用静态方法
XposedHelpers.callMethod(
param.getClass(),//固定句式
"methodName"//需要主动调用的方法名
new Object[]{...,...},//大括号中为调用函数中的参数,
)
在调用方法之前,可将程序中对参数的操作直接复制过来,例如加密操作,格式操作。
如果该方法有返回值且需要获取,可将该方法直接用在某一变量上,例如:
String str=(String)XposedHelpers.callMethod(
param.getClass(),
"methodName"
new Object[]{...,...},
)
param.args[1]=str.toString();
Xposed—hook静态变量
实例变量在每一份实例出来的类中都有不同的值,先有对象才有实例变量,因此在没有对象之前是不能hook修改实例变量。在内存中静态变量不会改变。因此可以在对象之前hook。
故hook静态变量不需要获取类对象,直接修改类中私有静态变量。hook的方法有XposedHelpers,以变量类型Int为例。
final Class<?> clazz= XposedHelpers.findClass(
"com.example.xposed_new5.MainActivity",
loadPackageParam.classLoader);//方便起见提前赋给clazz
XposedHelper.setStaticIntField(clazz,"变量名",value(修改的值));
XposedHelpers.setStaticObjectField();//修改字符串
注:不同变量类型使用不同方法。
final Class<?>clazz=XposedHelpers.findClass(
"com.example.xposed_new5.MainActivity",
loadPackageParam.classLoader);
XposedHelpers.setStaticIntField(clazz,"staticInt",99);
Xposed—hook构造方法
Java构造方法
与类同名,通过关键字new调用,每个类至少有一个或一个以上的构造方法(如果没有定义构造方法,系统会自动定义一个无参数的构造方法)。构造方法可以无参、一个或多个参数,且构造方法没有返回值。例如:
MainActivity(){
}
MainActivity(int a,int b){
}
MainActivity(String str){
}
hook构造方法
hook构造方法不需要添加方法名,采用的hook方法为XposedHelpers.findAndHookConstructor。
此时不能hook实例变量,因为对象还没有产生。
findAndHookConstructor详解
final Class<?> clazz=XposedHelpers.findClass(
"com.example.xposed_new6.MainActivity",//包名加类名
loadPackageParam.classLoader);//固定格式
XposedHelpers.findAndHookConstructor(
clazz,//可以提前定义,也可以直接在这里写出来
int.class,//构造方法的参数
String.class,//无参数也可以不写
new XC_MethodHook(){
//和普通方法写法一样
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
XposedBridge.log("Haha, HookDemo constructed was hooked" );
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
}
});
Xposed—hook所有函数遍历所有类
对于动态dex文件可以采用这种方法来hook。
XposedHelpers.findAndHookMethod(
ClassLoader.class,
"isok",
String.class,
new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
Class<?> clazz=(Class<?>) loadPackageParam.getResult();
XposedBridge.log("Clazz:"+clazz.getName());
}
}
});
通过hook主动调用获取相关数据
获取类
Class<?> clazz=param.thisObject.getClass();
对类进行操作(获取字段)
Field[] fields=clazz.getDeclaredFields();
for(Field field:fields){
XposedBridge.log("字段名称:"+field.getName());
}
获取类中的所有方法
Method[] methods=clazz.getDeclaredMethods();
for(Method method:methods)
{
XposedBridge.log("方法名称:"+method.getName());
}
通过主动调用获取普通方法
XposedHelpers.callMethod(loadPackageParam.getClass(),"methodName",new Object(){...});
通过主动调用获取静态方法
Class<?> clazz1=XposedHelpers.findClass(
"com.example.xposed_new7.MainActivity",
loadPackageParam.classLoader);
XposedHelpers.callStaticMethod(clazz1,"methodName",new Object(){...});
通过主动调用获取普通字段(不是方法中的特定字段)
XposedHelpers.getBooleanField(loadPackageParam.getClass(),"fieldName");
获取静态字段
Class<?> clazz2=XposedHelpers.findClass(
"com.example.xposed_new7.MainActivity",
loadPackageParam.classLoader);
XposedHelpers.getStaticBooleanField(clazz2,"fieldName");
Xposed—hook替换函数
if(loadPackageParam.packageName.equals("com.example.xposed_new8")){
Class<?>clazz=XposedHelpers.findClass(
"com.example.xposed_new8.MainActivity",
loadPackageParam.classLoader);
XposedHelpers.findAndHookMethod(
"com.example.xposed_new8.MainActivity",
loadPackageParam.classLoader,
"ButtonTest1",
new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
XposedBridge.log("方法替换成功");
XposedHelpers.callMethod(clazz,"ButtonTest2");//主动调用ButtonTest2
return null;
}
}
);
}
*Xposed—hook多DEX
在一个apk中有多个dex文件时,在apk打包的时候优先加载主dex文件,会优先有些类hook不到,采用attach方法来解决。
XposedHelpers.findAndHookMethod(
Application.class,
"attach",
Context.class,
new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
Context context= (Context) param.args[0];
ClassLoader loader=context.getClassLoader();
XposedHelpers.findAndHookMethod(
"com.example.xposed_new8.MainActivity",
loader,
"ButtonTest1",
new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
}
}
);
}
}
);