LSposed hook(学习分享)
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.gradle
的dependencies
下添加即可
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);
}
});