0. Xposed框架简介

关于Xposed框架相信大家应该不陌生了,他是Android中Hook技术的一个著名的框架,而Xposed框架是免费的而且还是开源的,本文主要介绍如何通过这个框架来进行系统方法的拦截功能,比如我们开发过程中,对于一些测试环境很难模拟,特别是测试同学有时候像随机改变设备的imei,mcc等信息用来模拟不同测试场景,这时候如果可以去修改系统的这个值的话对于测试来说就非常方便了,其实这些在网上已经有很多类似的小工具了,下面就来详细的讲解如何使用这个框架。

1. 编写模块功能

环境搭建好了,下面就开始操作了,上面安装的那个工具其实是一个模块管理器,我们如果想做一些hook操作还得自己编写模块也就是应用程序,然后把这个模块安装到设备中,这个工具就可以检测出来了,会提示你加载这模块然后在重启设备,模块功能就有效果了。那么下面来看一下如何编写一个Xposed模块呢?

第一步:新建一个Android项目,导入Xposed工具包

这里一定要注意,不能使用libs文件夹而是lib文件夹,如果这里使用了libs文件夹的话,在安装成功模块之后重启会发现Hook是失败的,通过打印tag为xposed的日志信息会发现这样的错误:java.lang.IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation

注意:在Eclipse中,如果把工具包放到libs文件中,默认是加入到编译路径中的,同时在编译出来的程序中也是包含了这个工具包中的所有类,而对于其他非libs文件夹,我们添加工具包之后在add buildpath之后只是做到了工程引用工具包的功能,而最终并不会把这个工具包包含到程序中的。

第二步:编写模块代码

模块代码编写还是比较简单的,我们只要新建一个实现IXposedHookLoadPackage接口的类,然后在handleLoadPackage回调方法中进行拦截操作即可,而具体的拦截操作是借助XposedHelpers.findAndHookMethod方法和XposedBridge.hookMethod方法实现的,这两个方法也是比较简单的,从参数含义可以看到,主要是Hook的类名和方法名,然后还有一个就是拦截的回调方法,一般是拦截之前做什么的一个beforeHookedMethod方法和拦截之后做什么的一个afterHookedMethod方法。

  1. public class Main implements IXposedHookLoadPackage {
  2. //hook 一个具体的函数
  3. private void hook_method(String className, ClassLoader classLoader, String methodName,
  4. Object... parameterTypesAndCallback){
  5. try {
  6. XposedHelpers.findAndHookMethod(className, classLoader, methodName, parameterTypesAndCallback);
  7. } catch (Exception e) {
  8. XposedBridge.log(e);
  9. }
  10. }
  11. //hook 相同函数名的函数
  12. private void hook_methods(String className, String methodName, XC_MethodHook xmh){
  13. try {
  14. Class<?> clazz = Class.forName(className);
  15. for (Method method : clazz.getDeclaredMethods())
  16. if (method.getName().equals(methodName)
  17. && !Modifier.isAbstract(method.getModifiers())
  18. && Modifier.isPublic(method.getModifiers())) {
  19. XposedBridge.hookMethod(method, xmh);
  20. }
  21. } catch (Exception e) {
  22. XposedBridge.log(e);
  23. }
  24. }
  25. @Override
  26. public void handleLoadPackage(final LoadPackageParam lpp) throws Throwable{
  27. Log.i("jw", "pkg:"+lpp.packageName);
  28. //hook 系统函数getDeviceId 函数,并将返回值设置为jiangwei
  29. hook_method("android.telephony.TelephonyManager", lpp.classLoader, "getDeviceId", new XC_MethodHook() {
  30. @Override
  31. protected void afterHookedMethod(MethodHookParam param) throws Throwable {
  32. Log.i("jw", "hook getDeviceId...");
  33. Object obj = param.getResult();
  34. Log.i("jw", "imei args:"+obj);
  35. param.setResult("jiangwei");
  36. }
  37. });
  38. //定位
  39. hook_methods("android.location.LocationManager", "getLastKnownLocation", new XC_MethodHook(){
  40. @Override
  41. protected void afterHookedMethod(MethodHookParam param) throws Throwable {
  42. Log.i("jw", "hook getLastKnownLocation...");
  43. Location l = new Location(LocationManager.PASSIVE_PROVIDER);
  44. double lo = -10000d; //经度
  45. double la = -10000d; //纬度
  46. l.setLatitude(la);
  47. l.setLongitude(lo);
  48. param.setResult(l);
  49. }
  50. });
  51. hook_methods("android.location.LocationManager", "requestLocationUpdates", new XC_MethodHook() {
  52. @Override
  53. protected void afterHookedMethod(MethodHookParam param) throws Throwable {
  54. Log.i("jw", "hook requestLocationUpdates...");
  55. if (param.args.length == 4 && (param.args[0] instanceof String)) {
  56. LocationListener ll = (LocationListener)param.args[3];
  57. Class<?> clazz = LocationListener.class;
  58. Method m = null;
  59. for (Method method : clazz.getDeclaredMethods()) {
  60. if (method.getName().equals("onLocationChanged")) {
  61. m = method;
  62. break;
  63. }
  64. }
  65. try {
  66. if (m != null) {
  67. Object[] args = new Object[1];
  68. Location l = new Location(LocationManager.PASSIVE_PROVIDER);
  69. double lo = -10000d; //经度
  70. double la = -10000d; //纬度
  71. l.setLatitude(la);
  72. l.setLongitude(lo);
  73. args[0] = l;
  74. m.invoke(ll, args);
  75. }
  76. } catch (Exception e) {
  77. XposedBridge.log(e);
  78. }
  79. }
  80. }
  81. });
  82. }
  83. }

对于IXposedHookLoadPackage这个接口和回调方法,我们可以知道,应该是拦截系统中所有应用的运行信息,这里传递回来的一个LoadPackageParam参数类型就是包括了Hook应用的具体信息,我们可以打印应用的包名就可以看到效果了。

注意:如果你想Hook一个类的具体方法,那么就必须要清楚的了解到这个方法的相信信息:参数类型和个数,返回类型等。因为在拦截的过程中必须要对这个方法进行分析,比如得到方法参数来进行具体参数修改,返回值信息来进行返回值修改,这里看到了获取imei值的方法是一个无参数的返回字符串类型的方法,那么如果要拦截他的返回值,就需要修改他的返回值使用setResult方法即可。所以从这里可以看到不管是你hook系统的方法,还是日后去hook第三方应用的具体类方法,第一步都得了解到你hook对象的具体信息,关于系统方法咋们可以通过查看源码来得到信息,而对于第三方应用的话那么只能借助反编译技术了,比如修改游戏金币功能,你必须先反编译游戏知道修改金币的类和具体方法才可行。

这里我不仅Hook了系统的imei信息,也简单的Hook了系统的地理位置信息,在Android中获取经纬度信息有三种方式,这里为了演示简单,用了GPS定位功能,一般获取经纬度信息的代码主要是两处:

一处是初始化的时候调用getLastKnowLocation方法获取最后一次系统中的地理位置信息

  • //获取地理位置管理器
    1. LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    2. //获取Location
    3. Location location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
    4. if(location!=null){//不为空,显示地理位置经纬度  
         showLocation(location);  

    还有一处就是监听地理位置变化的回调接口中的onLocationChanged回调方法:

    1. /**
    2. * LocationListern监听器
    3. * 参数:地理位置提供器、监听位置变化的时间间隔、位置变化的距离间隔、LocationListener监听器
    4. */
    5. LocationListener locationListener = new LocationListener() {
    6. @Override
    7. public void onStatusChanged(String provider, int status, Bundle arg2) {
    8. }
    9. @Override
    10. public void onProviderEnabled(String provider) {
    11. }
    12. @Override
    13. public void onProviderDisabled(String provider) {
    14. }
    15. @Override
    16. public void onLocationChanged(Location location) {
    17. //如果位置发生变化,重新显示
    18. showLocation(location);
    19. }
    20. };

    所以如果想Hook系统的地理位置信息进行拦截,那么就需要操作这两处代码了,而他们有一个区别就是,第一处是通过返回值得到的,第二处是通过回调方法中的参数得到的。下面来看一下具体的Hook代码:

    Hook第一处代码比较简单,直接构造一个假的Location对象然后设置返回值即可。

    1. //定位
    2. hook_methods("android.location.LocationManager", "getLastKnownLocation", new XC_MethodHook(){
    3. @Override
    4. protected void afterHookedMethod(MethodHookParam param) throws Throwable {
    5. Log.i("jw", "hook getLastKnownLocation...");
    6. Location l = new Location(LocationManager.PASSIVE_PROVIDER);
    7. double lo = -10000d; //经度
    8. double la = -10000d; //纬度
    9. l.setLatitude(la);
    10. l.setLongitude(lo);
    11. param.setResult(l);
    12. }
    13. });

    Hook第二处代码有点复杂,需要先找到添加位置监听的方法requestLocationUpdates,然后通过反射得到这个回调对象,找到具体的回调方法,然后在进行操作,因为回调方法是通过参数把Location对象传递回来的,所以这里需要修改参数值。

    1. hook_methods("android.location.LocationManager", "requestLocationUpdates", new XC_MethodHook() {
    2. @Override
    3. protected void afterHookedMethod(MethodHookParam param) throws Throwable {
    4. Log.i("jw", "hook requestLocationUpdates...");
    5. if (param.args.length == 4 && (param.args[0] instanceof String)) {
    6. LocationListener ll = (LocationListener)param.args[3];
    7. Class<?> clazz = LocationListener.class;
    8. Method m = null;
    9. for (Method method : clazz.getDeclaredMethods()) {
    10. if (method.getName().equals("onLocationChanged")) {
    11. m = method;
    12. break;
    13. }
    14. }
    15. try {
    16. if (m != null) {
    17. Object[] args = new Object[1];
    18. Location l = new Location(LocationManager.PASSIVE_PROVIDER);
    19. double lo = -10000d; //经度
    20. double la = -10000d; //纬度
    21. l.setLatitude(la);
    22. l.setLongitude(lo);
    23. args[0] = l;
    24. m.invoke(ll, args);
    25. }
    26. } catch (Exception e) {
    27. XposedBridge.log(e);
    28. }
    29. }
    30. }
    31. });

    好了,到这里我们就编写好了Hook系统的imei值和地理位置信息的模块了。

    第三步:添加模块入口

    这一步是非常重要的,也是最容易忘记的,就是要告诉Xposed框架一个模块中Hook的入口,这里可以看到模块的入口是Main类,所以需要在模块的assets中添加一个xposed_init文件:

     

    这里的内容很简单,就是模块入口类的全称名称即可:


    第四步:添加模块的额外信息

    最后一步就是需要在模块的AndroidManifest.xml文件添加额外信息,具体包括模块的描述信息,版本号等:

    1. <meta-data
    2. android:name="xposedmodule"
    3. android:value="true" />
    4. <meta-data
    5. android:name="xposeddescription"
    6. android:value="Hook系统信息" />
    7. <meta-data
    8. android:name="xposedminversion"
    9. android:value="30" />
    xposedmodule:代表的是Android程序作为Xposed中的一个模块,所以值为true;
    xposeddescription:代表的是对本模块的功能的描述,可以自己简单叙述下就可以了;
    xposedminversion:代表的是本模块开发时用到的xposed的jar包的最低版本号,这里是30,而我所用的xposed的jar包版本是54;

    经过上面四步之后咋们就完成了模块的定义了,最后咋们为了验证我们Hook的结果,在新建一个Activity类,在内部调用一下系统的获取imei方法以及位置信息方法,并且显示在屏幕中:

    1. public void onCreate(Bundle savedInstanceState) {
    2. super.onCreate(savedInstanceState);
    3. setContentView(R.layout.activity_demo);
    4. locationTxt = (TextView)findViewById(R.id.location);
    5. imeiTxt = (TextView)findViewById(R.id.imei);
    6. //获取地理位置管理器
    7. locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    8. //获取Location
    9. Location location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
    10. if(location!=null){
    11. //不为空,显示地理位置经纬度
    12. showLocation(location);
    13. }
    14. //监视地理位置变化
    15. locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 3000, 1, locationListener);
    16. TelephonyManager telephonyManager = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
    17. String imei = telephonyManager.getDeviceId();
    18. imeiTxt.setText("imei:"+imei);
    19. }

    2. 运行模块

    这时候看到,激活成功之后,会提示你再次重启设备才能生效,所以这里可以看到每次如果有新的模块或者是模块代码有更新了,比如这样:

    都是需要重启设备,模块才能生效的,这一点还是有点蛋疼的和麻烦的。然后咋们重启设备之后,在运行我们的模块代码看看效果:

    从这显示结果看到了,Hook成功了,在没有Hook之前的效果是:

    这时候咋们在来看一下打印的日志信息:

    看到了,百度地图在获取我们设备的imei和位置信息,当然这是符合正常情况的,从这里可以看到,我们还可以利用这个技术来观察设备中有哪些应用在获取设备的一些隐私数据。

    3.实际用途

    本文主要是介绍了Xposed框架的基本使用以及一个简单作用,但是在实际过程中,这个框架是非常有用的,比如在文章开头就说到了,我们可以通过修改系统的一些信息来帮助测试模拟复杂的测试环境,但是这个框架现在用的最广泛的当属破解了,这个也是我们后续讲解的重点,用这个框架咋们可以进行应用的脱壳,游戏的外挂等。

    4.工程代码



    附件列表

    XPosed框架_简单的应用的更多相关文章

    1. 三星5.0以上机器最简单激活Xposed框架的经验

      对于喜欢钻研手机的哥们来说,经常会接触到XPOSED框架及种类繁多功能强大的模块,对于5.0以下的系统版本,只要手机能获得ROOT权限,安装和激活XPOSED框架是比较轻易的,但随着系统版本的更新,5 ...

    2. 华为7.0系统最简单激活xposed框架的流程

      对于喜欢搞机的哥们而言,很多时候会接触到Xposed框架及其种类繁多功能无敌的模块,对于5.0以下的系统版本,只要手机能获得root权限,安装和激活Xposed框架是异常简易的,但随着系统版本的不断更 ...

    3. 荣耀7.0系统手机最简单激活Xposed框架的步骤

      对于喜欢玩手机的小伙伴来说,很多时候会使用到Xposed框架及各类功能彪悍的模块,对于5.0以下的系统版本,只要手机能获得Root权限,安装和激活Xposed框架是比较简便的,但随着系统版本的不断更新 ...

    4. 2_MVC+EF+Autofac(dbfirst)轻型项目框架_用户权限验证

      前言 接上面两篇 0_MVC+EF+Autofac(dbfirst)轻型项目框架_基本框架 与 1_MVC+EF+Autofac(dbfirst)轻型项目框架_core层(以登陆为例) .在第一篇中介 ...

    5. [转]Android中Xposed框架篇—利用Xposed框架实现拦截系统方法

      一.前言 关于Xposed框架相信大家应该不陌生了,他是Android中Hook技术的一个著名的框架,还有一个框架是CydiaSubstrate,但是这个框架是收费的,而且个人觉得不怎么好用,而Xpo ...

    6. [转载] Android中Xposed框架篇---利用Xposed框架实现拦截系统方法

      本文转载自: http://www.wjdiankong.cn/android%E4%B8%ADxposed%E6%A1%86%E6%9E%B6%E7%AF%87-%E5%88%A9%E7%94%A8 ...

    7. python_Tornado_web_框架_分页

      如何实现web_框架_分页? -- 思考什么是xss跨站攻击? --别人把js代码提交到后台,然后从后台返回数据的时候,别人上传的js变成html中的代码, 就会插入别人的代码,带来极大的信息泄露的风 ...

    8. C++框架_之Qt的开始部分_概述_安装_创建项目_快捷键等一系列注意细节

      C++框架_之Qt的开始部分_概述_安装_创建项目_快捷键等一系列注意细节 1.Qt概述 1.1 什么是Qt Qt是一个跨平台的C++图形用户界面应用程序框架.它为应用程序开发者提供建立艺术级图形界面 ...

    9. C++框架_之Qt的窗口部件系统的详解-上

      C++框架_之Qt的窗口部件系统的详解-上 第一部分概述 第一次建立helloworld程序时,曾看到Qt Creator提供的默认基类只有QMainWindow.QWidget和QDialog三种. ...

    随机推荐

    1. 企业CIO、CTO必读的34个经典故事

      一. 用人之道 去过庙的人都知道,一进庙门,首先是弥陀佛,笑脸迎客,而在他的北面,则是黑口黑脸的韦陀.但相传在很久以前,他们并不在同一个庙里,而是分别掌管不同的庙.弥乐佛热情快乐,所以来的人非常多,但 ...

    2. JAVA初级必须要搞懂的事项(希望对新手有所帮助)

      1        安装JDK=> (1,下载JDK,安装,一般目录为C:\Program Files\Java中:2,通过Dos命令测试JDK是否安装=>java –version命令查看 ...

    3. 修改linux的时区问题

      修改linux的时区问题 配置服务器节点上的时区的步骤: 1.先生成时区配置文件Asia/Shanghai,用交互式命令 tzselect 即可: 2.拷贝该时区文件,覆盖系统本地时区配置: cp / ...

    4. ios之UILabel

      详细使用: UILabel *label = [[UILabelalloc] initWithFrame:CGRectMake(0, 0, 75, 40)];   //声明UIlbel并指定其位置和长 ...

    5. 用vue 简单写的日历

      <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

    6. js事件(事件冒泡与事件捕获)

      事件冒泡和事件捕获分别由微软和网景公司提出,这两个概念都是为了解决页面中事件流(事件发生顺序)的问题. <div id='aa' click='po'> <p id='bb' cli ...

    7. React初识整理(五)--Redux和Flux(解决状态传递问题)

      Flux 1.引入:在React的应⽤中,状态管理是⼀个⾮常重要的⼯作.我们不会直接对DOM节点进⾏操作,⽽是通过将数据设置给state,由state来同步UI,这种⽅式有个潜在的问题,每个组件都有独 ...

    8. Bzoj 1085: [SCOI2005]骑士精神 (dfs)

      Bzoj 1085: [SCOI2005]骑士精神 题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1085 dfs + 剪枝. 剪枝方法: ...

    9. OS复习

      提纲 一 操作系统的定义,各章节名词定义. 分时多道- OS四大特征,五大功能. 二 进程 创建终止挂起激活 PCB 原语:创建终止挂起激活唤醒 互斥和同步,临界资源,临界区 信号量的基础概念,受保护 ...

    10. 重置windows用户漫游配置文件

      1.备份用户数据 2.删除或修改漫游配置文件 3.用户PC管理员登陆,删除本地用户缓存文件 注册表打开: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows N ...