编写 Lposed
插件可以使用 AndroidStudio
也可以使用 Idle
, 前提是你的 Idle
有安装安卓组件,本文使用 Idle
进行讲解,默认你已经安装好了 Lposed
框架,如果没有安装好,可以自行百度进行安装!
创建项目
首先创建一个 Android
项目
需要选择 Android
和 Empty Activity
点击下一步,配置好包名等一些信息后点击创建
创建好之后可以看到项目结构如下:
声明模块
进入到 app/src/main/AndroidManifest.xml
下按照图示位置输入以下代码
<!-- 声明这是一个 Xposed 模块-->
<meta-data
android:name="xposedmodule"
android:value="true"/>
<!-- 这个是 Xposed 模块的显示信息-->
<meta-data
android:name="xposeddescription"
android:value="这是一个Xposed例程"/>
<!-- 这个是 Xposed 小版本-->
<meta-data
android:name="xposedminversion"
android:value="53"/>
安装依赖
进入到 app/libs
目录下, 将 Lsposed
的 jar
包放置进去
进入到 app/build.gradle
文件下声明依赖编译
compileOnly files('libs/LSPosed-api-1.0-SNAPSHOT.jar')
编写案例
打开 app/src/main/res/layout/activity_main.xml
文件, 创建一个按钮
进入到 com/example/xposeddemo/MainActivity.kt
内粘贴以下代码:
package com.example.xposeddemo
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
private var button: Button? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button = findViewById<View>(R.id.button) as Button
button!!.setOnClickListener { Toast.makeText(this@MainActivity, toastMessage(), Toast.LENGTH_SHORT).show() }
}
fun toastMessage(): String {
return "我未被劫持"
}
}
上面的代码表示找到这个 button
, 当点击 button
的时候就调用 toastMessage
方法弹出消息。然后运行 app
看看效果,前提是你要连上你的手机哦
发现 app
已经创建好了,当我们点击这个 button
的时候就会提示:我未被劫持
Hook
现在我们已经有了 app
,所以我们可以编写代码进行劫持
首先创建一个类 com/example/xposeddemo/MyHook.java
, 名字自己定
创建完毕之后我们需要继承 de.robv.android.xposed.IXposedHookLoadPackage
这个类,并且实现 handleLoadPackage
方法
package com.example.xposeddemo;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
public class MyHook implements IXposedHookLoadPackage {
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
}
}
然后我们可以在 handleLoadPackage
这个方法里面进行 hook
, 代码如下:
package com.example.xposeddemo;
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;
import java.util.Objects;
public class MyHook implements IXposedHookLoadPackage {
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
// 先判断包名
if (Objects.equals(loadPackageParam.packageName, "com.example.xposeddemo")) {
XposedBridge.log("找到包名为: " + loadPackageParam.packageName + "应用了!, 准备进行 Hook");
ClassLoader classLoader = loadPackageParam.classLoader;
XposedBridge.log("获取当前 ClassLoader: " + classLoader.toString());
Class<?> clazz = classLoader.loadClass("com.example.xposeddemo.MainActivity");
XposedBridge.log("找到 MainActivity 这个类: " + clazz.toString());
XposedHelpers.findAndHookMethod(clazz, "toastMessage", new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam<?> param) throws Throwable {
XposedBridge.log("成功 Hook MainActivity 的 toastMessage 方法");
super.beforeHookedMethod(param);
}
@Override
protected void afterHookedMethod(MethodHookParam<?> param) throws Throwable {
param.setResult("你已被劫持");
}
});
}
}
}
然后进入 main
目录下创建一个 assets
文件夹
在该文件夹下创建一个 xposed_init
文件,文件内写上你的 hook
类的引用地址
准备完毕,我们再次运行安装 app
到手机上,这个时候会发现提示模块未激活
去启用一下该模块,因为本文中 hook
的是自己,所以我就随便选一个 app
了,自己在开发的时候可以选择响应的应用
可以看到该模块已经被启用了
此时我们重新打开我们的应用,点击按钮,发现输出结果已经变成我们 hook
的结果了:你已被劫持
看一下 Lsposed
里面发现我们打印的日志也输出了
补充
loadPackageParam
里面可以获取包名和 ClassLoader
, 一般都会先用 if
进行过滤
可以使用 classLoader.loadClass
加载类
hook
方法可以使用 XposedHelpers.findAndHookMethod
, 第一个参数是类,第二是是方法名,第三个是回调函数 XC_MethodHook
通过 param.setResult
可以设置方法返回值