Xposed 也算是有名的框架了,微信抢红包、qq抢红包等工具都是使用 Xposed 框架实现的
目前一些黑产也可以通过 Xposed hook 程序,修改数据或直接调用某些方法,来达到破解软件的目的
下面是一篇简单的使用教程
来说明如何 hook 一个程序
创建一个普通的主项目
此项目什么操作都不做,仅仅有一个按钮及文字显示控件
包名是: com.zhou.hooktest
注意:在 hook 的过程中,包名很重要,插件是通过包名匹配来决定hook的
xml 和 java 文件内容如下:
xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/testBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/clickBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="点击改变"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
</android.support.constraint.ConstraintLayout>
java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setNewText("来自 Activity");
findViewById(R.id.clickBtn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setNewText("来自点击");
}
});
AlertDialog alertDialog=new AlertDialog(this);
alertDialog.show();
alertDialog.setCancelable();
EditText editText;
editText.getText("");
}
public void setNewText(String text) {
TextView textView = findViewById(R.id.testBtn);
textView.setText(text);
}
}
这个工程仅仅显示一段文字内容
创建一个 Xposed 插件工程
创建插件工程的初始步骤和创建普通工程没有区别
首先使用 AS 创建一个普通项目
假设我目前创建的工程包名为: com.zhou.hook
添加 Xposed 插件工程所必须的步骤
AndroidManifest.xml 修改
在 Application 节点中添加:
<!-- 是否是xposed模块,xposed根据这个来判断是否是模块 -->
<meta-data
android:name="xposedmodule"
android:value="true" />
<!-- 模块描述,显示在xposed模块列表那里第二行 -->
<meta-data
android:name="xposeddescription"
android:value="测试Xposed模块" />
<!-- 最低xposed版本号(lib文件名可知) -->
<meta-data
android:name="xposedminversion"
android:value="30" />
app 的 build.gradle 修改
在 app 的build.gradle 添加依赖
注意使用 provided 而不是 implementation
provided 'de.robv.android.xposed:api:82'
创建一个 java 入口文件
创建一个 xposed 框架插件入口,这个入口继承自:IXposedHookLoadPackage
下面是我创建的示例:
这个示例的java文件路径是: com.zhou.hook.Main
public class Main implements IXposedHookLoadPackage {
public static final String TAG = "HookXposed";
@Override
public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
try {
hookTest(lpparam);
} catch (Exception e) {
Log.i(TAG, " load exception:" + Log.getStackTraceString(e));
}
}
/**
* 这是测试 xposed 框架是否能运行的方法
*
* @param lpparam
*/
private void hookTest(final XC_LoadPackage.LoadPackageParam lpparam) {
if (lpparam.packageName.equals("com.zhou.hooktest")) {
Log.i(TAG, " load success");
XposedBridge.log("load test apk");
Log.i(TAG, " load success findAndHookMethod");
XposedHelpers.findAndHookMethod("com.zhou.hooktest.MainActivity"
, lpparam.classLoader, "setNewText", String.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
Log.i(TAG, " load success beforeHookedMethod:" + param.args[0]);
XposedBridge.log("test apk param:" + param.args[0]);
param.args[0] = "来自 xposed";
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
Log.i(TAG, " load success afterHookedMethod");
super.afterHookedMethod(param);
}
});
Log.i(TAG, "hook over");
}
}
}
assets 添加文件
在 app/src/main/assets
文件夹(也就是资源文件夹)内添加一个文件:xposed_init
注意文件名必须是 xposed_init
在这个文件中添加一行内容,这行内容告诉 xposed 框架,插件的入口类的路径
com.zhou.hook.Main
运行
分别将两个程序安装在有 Xposed 框架且成功激活框架的模拟器或手机上
在 Xposed 框架中,勾选模块并重启,此插件即可运行
正常情况下,打开主程序,应该显示 来自 Activity
而点击按钮,应该显示 来自点击
在 Xposed 框架启用插件后,此程序无论是打开,还是点击按钮,都只显示: 来自 Xposed
在上面的 Xposed 插件程序中,劫持了 setNewText
方法,使用 log 输出了参数,并将该方法参数修改成了: 来自 Xposed
说明
通过 if (lpparam.packageName.equals("com.zhou.hooktest"))
,此插件只会 hook 用来测试的主程序
XposedHelpers.findAndHookMethod
的最后一个参数即回调,
beforeHookedMethod
是方法执行前的调用, 可以在这里获取 方法入参
afterHookedMethod
是方法执行后的调用, 可以获取方法出参
Xposed 插件具有更强大的功能,不只是 hook method ,对象同样可以被反射获取,并且可以更改对象的值
例如: XposedHelpers.findField()
将会返回一个 Field
对象,通过 Field ,可以修改对象的值