Xposed是一款可以在不修改APK的情况下影响程序运行的框架,基于它可以制作出许多功能强大的模块,且在功能不冲突的情况下同时运作。在这个框架下,我们可以编写并加载自己编写的插件APP,实现对目标apk的注入拦截等。
关于开发环境的配置我就不多说了,别的大佬讲的都很详细,而且我是直接用手机开发测试的,没有配置环境
首先必须继承IXposedHookLoadPackage接口,并重写handleLoadPackage回调方法,像这样:
public class HookInit implements IXposedHookLoadPackage {
@Override
public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
}
}
其中回调方法的LoadPackageParam lpparam参数是Xposed提供的,他可以获取当前应用的信息,他也提供了很多属性,如classLoader(当前类加载器),packageName(包名称)等
Xposed提供了很多封装好的Hook函数,但是本质使用的还是Java反射,下面我将写一个安卓demo作为案例来教大家怎么使用xposed提供的函数
package com.demo;
import android.app.Activity;
import android.os.Bundle;
import android.widget.Button;
import android.widget.EditText;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends Activity {
Button button1;
Button button2;
Button button3;
EditText edit;
static String Name="admin";
static int pass=123456;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button1 = findViewById(R.id.puton);
button2 = findViewById(R.id.statics);
button3 = findViewById(R.id.cons);
edit = findViewById(R.id.activitymainEditText1);
//方法参数测试
button1.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View view) {
String pass=edit.getText().toString();
//传入编辑框内容
check(pass);
}
});
//静态变量测试
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(getApplication(), "name:" + Name + "\n" + "pass:" + pass, Toast.LENGTH_SHORT).show();
}
});
//构造方法测试
button3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
demo2test demo =new demo2test("Anna", 1);
Toast.makeText(getApplication(), "name:" + demo.getName() + "\n" + "id:" + demo.getId(), Toast.LENGTH_SHORT).show();
}
});
}
public void check(String pass) {
// 判断参数内容是否和密码相同
if (pass.equals("123456")) {
Toast.makeText(getApplication(), "密码正确", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplication(), "密码错误", Toast.LENGTH_SHORT).show();
}}
public void test() {
Toast.makeText(getApplication(), "我被调用了?", Toast.LENGTH_SHORT).show();
}
}
package com.demo;
/**
* @Author Moiy
* @Date 2025/04/09 09:20
*/
public class demo2test {
String name;
int id;
public demo2test(String name, int id) {
this.name = name;
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setId(int id) {
this.id = id;
}
public int getId() {
return id;
}}
方法按钮(检测编辑框内容是否正确)
静态按钮(输出静态变量内容)
构造按钮(输出构造函数传入的变量)
关于Xposed hook,一般使用的都是XposedHelpers类下的函数,比如Hook方法使用的就是findAndHookMethod方法,这个函数有两个重载分别是
findAndHookMethod(String className, ClassLoader classLoader, String methodName, Object... parameterTypesAndCallback) {}
findAndHookMethod(Class<?> clazz, String methodName, Object... parameterTypesAndCallback) {}
具体使用:
XposedHelpers.findAndHookMethod(
"com.demo.MainActivity",
lpparam.classLoader,
"check",
String.class,
new XC_MethodHook(){
protected void beforeHookedMethod(MethodHookParam param){
//设置方法参数为123456
param.args[0]="123456";
}
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
//打印日志
XposedBridge.log("方法参数Hook成功: 现参数 = " + param.args[0]);
}
});
第一个参数是类名
第二个是当前应用的类加载器
第三个参数是方法名称
第四个参数是方法的参数类型(空参则不填,如果需要填,参数类型 +.class即可)
最后的参数是一个类,我是用的XC_MethodHook类,他提供了两个方法
分别是beforeHookedMethod(方法调用前)和afterHookedMethod(方法调用后)执行
这两个方法中需要定义一个参数,MethodHookParam param,这个参数可以获取方法的信息,它提供了很多属性,如args(方法参数数组),thisObject(当前实例对象)等,
如果你只想打印出来是否Hook等不需要方法运行状态的信息,那你可以不填参这个参数
下面是Hook成功打印出来的日志(最后一条):

关于Class对象的获取,Xposed提供的有XposedHelpers.findClass()方法
方法提供了有两个重载,正常直接在方法传入类名与当前应用的类加载器,如XposedHelpers.findClass("xxx.xxx.xx",lpparam.classLoader),然后定义一个Class对象接收即可
所需函数:
XposedHelpers.setStaticxxxField(Class<?> clazz, String fieldName, int value)
XposedHelpers.setStaticObjectField(Object obj, String fieldName, Object value)
第一个是基础类型的Hook
第二个是对象类型的Hook
关于基础类型的Hook,XposedHelpers中提供了很多方法,如setStaticIntField(),setStaticByteField(),setStaticCharField()等,
关于对象的就只有setStaticObjectField()方法
具体代码:
//hook变量(更改变量值(对象,字段名,需要修改的值))
Class clas = XposedHelpers.findClass("com.demo.MainActivity", lpparam.classLoader);
XposedHelpers.setStaticObjectField(clas, "Name", "pass");
XposedHelpers.setStaticIntField(clas, "pass", 6666);
XposedBridge.log("变量Hook成功");
下面是Hook成功打印出来的日志(最后一条):
所需函数:
XposedHelpers.findAndHookConstructorClass<?> clazz, Object... parameterTypesAndCallback)
参数传入与Hook方式findAndHookMethod方法基本相同
具体代码:
//hook构造方法
Class claz =XposedHelpers.findClass("com.demo.demo2test", lpparam.classLoader);
XposedHelpers.findAndHookConstructor(claz, String.class, int.class, new XC_MethodHook(){
protected void beforeHookedMethod(XC_MethodHook.MethodHookParam param) {
//设置构造参数
param.args[0] = "Moiy";
param.args[1] = 9999;
}
protected void afterHookedMethod(XC_MethodHook.MethodHookParam param) throws Throwable {
//打印日志
XposedBridge.log("构造方法Hook成功: = " + param.args[0] + " " + param.args[1]);
}
});
这个没什么好讲的,和findAndHookMethod方法基本一样
默认不填构造参数的话,hook的就是空参构造,有的话就是有参构造
日志输出(最后一条):

什么?你问我为什么不讲更高级的用法?
篇幅有限,下次一定
最后给大家看一下Hook全代码:
package con.xposed.demo;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;
import java.lang.reflect.Method;
public class HookInit implements IXposedHookLoadPackage {
@Override
public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
if (!lpparam.packageName.equals("com.demo")) return; //判断包名
final Class<?> claz =XposedHelpers.findClass("com.demo.demo2test", lpparam.classLoader);
//hook构造方法
XposedHelpers.findAndHookConstructor(claz, String.class, int.class, new XC_MethodHook(){
protected void beforeHookedMethod(XC_MethodHook.MethodHookParam param) {
//设置构造参数
param.args[0] = "Moiy";
param.args[1] = 9999;
}
protected void afterHookedMethod(XC_MethodHook.MethodHookParam param) throws Throwable {
//打印日志
XposedBridge.log("构造方法Hook成功: = " + param.args[0] + " " + param.args[1]);
}
});
//hook静态变量(更改静态变量值(对象,字段名,需要修改的值))
Class<?> clas = XposedHelpers.findClass("com.demo.MainActivity", lpparam.classLoader);
XposedHelpers.setStaticObjectField(clas, "Name", "pass");
XposedHelpers.setStaticIntField(clas, "pass", 6666);
XposedBridge.log("静态方法Hook成功");
//hook方法(类名,加载器,方法名,参数,匿名类)
XposedHelpers.findAndHookMethod(
"com.demo.MainActivity",
lpparam.classLoader,
"check",String.class,
new XC_MethodHook(){
protected void beforeHookedMethod(MethodHookParam param){
//设置方法参数为123456
param.args[0]="123456";
}
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
//打印日志
XposedBridge.log("方法参数Hook成功: 现参数 = " + param.args[0]);
}
});
}}
[注意]看雪招聘,专注安全领域的专业人才平台!
最后于 2025-4-15 14:38
被Moly编辑
,原因: 修复显示