一、Xposed框架简介

  • Xposed是Android平台上的一个常用的HOOK框架,可以在不改变程序源代码的前提下,影响程序的运行。一个支持Xposed的Android应用程序被称为一个Xposed模块,用户可以在Xposed中安装各种各样的Xposed模块,在启用或关闭Xposed模块之后,需要重新引导系统才能生效。
  • Xposed模块使用Java语言开发,这意味着开发人员可以使用Android Studio开发一个自己的Xposed模块,就像开发一个Android应用程序一样简单。

二、Xposed框架安装

  • 安装Xposed框架的前提是手机要有root权限,或者有第三方Recovery
  • 在Android手机上安装Xposed是一件有风险的事,在尝试之前需要对手机的Recovery、root等知识有一定的了解,否则请不要贸然尝试。同时不建议在日常使用的手机上尝试安装Xposed框架,因为一些应用程序可以检测它,并且以此为理由来封禁您的帐号(例如微信)。
  • Xposed有两种安装方法,第一种是通过Xposed Installer来安装,首先安装上Xposed Installer,它会自动检测手机的Android版本,同时可以下载Xposed来执行安装,安装时候可以直接进行安装(可能需要root权限)也可以通过Recovery来安装。第二种方式就是直接下载Recovery的包来安装,使用Recovery进行刷入。
  • 以上资源在XDA论坛上都有提供,下载地址:[OFFICIAL] Xposed for Lollipop/Marshmallow/Nougat/Oreo [v90-beta3, 2018/01/29]

三、Xposed框架开发环境搭建

  • 上文已经提到,开发一个Xposed模块并不困难,因为Xposed模块也是使用Java语言开发的,这里使用Android Studio来开发一个Xposed模块。关于Android应用开发的基本知识,这里不再赘述,读者如果不了解Android开发,可以参考Android Developers上的入门指南
  • 在创建好工程之后,首先需要配置Gradle,以添加Xposed依赖库,在app文件夹下的build.gradle文件中,将以下语句添加到dependencies中:
  1. compileOnly 'de.robv.android.xposed:api:82'
  2. compileOnly 'de.robv.android.xposed:api:82:sources'
  • 在旧版本的Gradle中,上面的语句应该替换为:
  1. provided 'de.robv.android.xposed:api:82'
  2. provided 'de.robv.android.xposed:api:82:sources'
  • 这样就配置好了Xposed的依赖库,下面我们需要在AndroidManifest.xml中,声明本程序是一个Xposed模块,在<application></application>中添加以下XML语句:
  1. <meta-data
  2. android:name="xposedmodule"
  3. android:value="true"/>
  4. <meta-data
  5. android:name="xposeddescription"
  6. android:value="My Xposed Module"/>
  7. <meta-data
  8. android:name="xposedminversion"
  9. android:value="54"/>
  • 上面三个meta-data指定了Xposed模块标识、Xposed模块描述(显示在Xposed Installer中的模块库中)以及最低Xposed版本。
  • 最后,我们在工程的assets文件夹下新建一个文本文件,命名为xposed_init,这个文件用于配置Xposed的入口类名,在文件中直接写入实现了IXposedHookLoadPackage接口的类名即可,本类中的实例为:
  1. cn.xiaolus.xposed_xiaolu.XposedMain
  • 经过上述配置,Xposed开发环境就已经准备完毕,可以开始编写Xposed模块了。

四、Xposed API使用

  • Xposed最常用的功能就是修改函数的行为,例如返回值,这里也只阐述这部分API的使用。首先我们新建一个Java类,命名为XposedMain,位于包cn.xiaolus.xposed_xiaolu当中,这和xposed_init中的配置一致,该类需要实现IXposedHookLoadPackage接口。在该接口中,提供了一个名为handleLoadPackage的方法,这个方法在Android系统每次加载一个包的时候都会被调用。
  1. public class XposedMain implements IXposedHookLoadPackage {
  2. /**
  3. * 加载每个包时的回调方法
  4. * @param loadPackageParam 加载的Package的参数
  5. * @throws Throwable
  6. */
  7. @Override
  8. public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam loadPackageParam) {
  9. //Do something
  10. }
  11. }
  • 如前所属,因为在每个包加载的时候这个方法都会被调用,所以请勿在此方法中编写耗时的操作,否则整个系统都可能会卡死。一般而言我们只需要关心我们目标程序所在的包即可,通过以下的方法可以取出加载的包名:
  1. @Override
  2. public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam loadPackageParam) {
  3. //判断当前加载的包名
  4. if(loadPackageParam.packageName.equals("cn.xiaolus.syscheck")) {
  5. //Do something
  6. }
  7. }
  • 对于我们关心的包来说,我们还需要找到对应的类和方法,这样才可以修改其运行的行为,通过以下代码可以实现我们的目标:
  1. @Override
  2. public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam loadPackageParam) {
  3. // 判断当前加载的包名
  4. if(loadPackageParam.packageName.equals("cn.xiaolus.syscheck")) {
  5. //
  6. XposedHelpers.findAndHookMethod("cn.xiaolus.syscheck.SecCheck",
  7. loadPackageParam.classLoader,
  8. "checkRoot", new XC_MethodHook() {
  9. /**
  10. * 在Hook指定的方法之前调用此回调方法
  11. * @param param 方法Hook参数
  12. * @throws Throwable
  13. */
  14. @Override
  15. protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
  16. super.beforeHookedMethod(param);
  17. param.setResult(false);
  18. }
  19. /**
  20. * 在Hook指定的方法之后调用此回调方法
  21. * @param param 方法Hook参数
  22. * @throws Throwable
  23. */
  24. @Override
  25. protected void afterHookedMethod(MethodHookParam param) throws Throwable {
  26. super.afterHookedMethod(param);
  27. param.setResult(false);
  28. }
  29. });
  30. }
  31. }
  • 上面的代码使用了XposedHelpersfindAndHookMethod方法,需要四个参数或者五个参数,四个参数的用于HOOK无参数的方法,参数分别为完整类名、ClassLoader对象、方法名以及一个回调接口;五个参数的话在方法名之后需要提供Class[]形式的参数类型表,其他参数相同。
  • XC_MethodHook接口有两个回调方法,一个是beforeHookedMethod,一个是afterHookedMethod,分别是在HOOK指定的函数之前调用和之后调用,具体使用哪个回调方法可以自己尝试。在这两个方法中可以通过MethodHookParam参数获得并修改函数的各种参数,例如通过setResult方法修改函数的返回值,就实现了对函数方法返回值的修改。
  • 运行程序,目标函数无论执行情况如何,返回值都为false,这一般用于一些权限或者框架检测的破解和绕过,也可以用于其他的用途。

五、总结

  • Xposed是一款优秀的Android HOOK框架,优势是模块编写起来相对比较容易,功能强大,缺点也比较明显,每次重新编译框架或者开启、关闭框架,都需要重新引导系统,比较麻烦,同时不能直接HOOK C/C++编写的函数,也比较容易被检测出来(当然了你可以把检测代码也HOOK掉),也是其局限性之一。