XPosed框架_简单的应用
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方法。
- public class Main implements IXposedHookLoadPackage {
//hook 一个具体的函数private void hook_method(String className, ClassLoader classLoader, String methodName,Object... parameterTypesAndCallback){try {XposedHelpers.findAndHookMethod(className, classLoader, methodName, parameterTypesAndCallback);} catch (Exception e) {XposedBridge.log(e);}}//hook 相同函数名的函数private void hook_methods(String className, String methodName, XC_MethodHook xmh){try {Class<?> clazz = Class.forName(className);for (Method method : clazz.getDeclaredMethods())if (method.getName().equals(methodName)&& !Modifier.isAbstract(method.getModifiers())&& Modifier.isPublic(method.getModifiers())) {XposedBridge.hookMethod(method, xmh);}} catch (Exception e) {XposedBridge.log(e);}}@Overridepublic void handleLoadPackage(final LoadPackageParam lpp) throws Throwable{Log.i("jw", "pkg:"+lpp.packageName);//hook 系统函数getDeviceId 函数,并将返回值设置为jiangweihook_method("android.telephony.TelephonyManager", lpp.classLoader, "getDeviceId", new XC_MethodHook() {@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {Log.i("jw", "hook getDeviceId...");Object obj = param.getResult();Log.i("jw", "imei args:"+obj);param.setResult("jiangwei");}});//定位hook_methods("android.location.LocationManager", "getLastKnownLocation", new XC_MethodHook(){@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {Log.i("jw", "hook getLastKnownLocation...");Location l = new Location(LocationManager.PASSIVE_PROVIDER);double lo = -10000d; //经度double la = -10000d; //纬度l.setLatitude(la);l.setLongitude(lo);param.setResult(l);}});hook_methods("android.location.LocationManager", "requestLocationUpdates", new XC_MethodHook() {@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {Log.i("jw", "hook requestLocationUpdates...");if (param.args.length == 4 && (param.args[0] instanceof String)) {LocationListener ll = (LocationListener)param.args[3];Class<?> clazz = LocationListener.class;Method m = null;for (Method method : clazz.getDeclaredMethods()) {if (method.getName().equals("onLocationChanged")) {m = method;break;}}try {if (m != null) {Object[] args = new Object[1];Location l = new Location(LocationManager.PASSIVE_PROVIDER);double lo = -10000d; //经度double la = -10000d; //纬度l.setLatitude(la);l.setLongitude(lo);args[0] = l;m.invoke(ll, args);}} catch (Exception e) {XposedBridge.log(e);}}}});}}
对于IXposedHookLoadPackage这个接口和回调方法,我们可以知道,应该是拦截系统中所有应用的运行信息,这里传递回来的一个LoadPackageParam参数类型就是包括了Hook应用的具体信息,我们可以打印应用的包名就可以看到效果了。
注意:如果你想Hook一个类的具体方法,那么就必须要清楚的了解到这个方法的相信信息:参数类型和个数,返回类型等。因为在拦截的过程中必须要对这个方法进行分析,比如得到方法参数来进行具体参数修改,返回值信息来进行返回值修改,这里看到了获取imei值的方法是一个无参数的返回字符串类型的方法,那么如果要拦截他的返回值,就需要修改他的返回值使用setResult方法即可。所以从这里可以看到不管是你hook系统的方法,还是日后去hook第三方应用的具体类方法,第一步都得了解到你hook对象的具体信息,关于系统方法咋们可以通过查看源码来得到信息,而对于第三方应用的话那么只能借助反编译技术了,比如修改游戏金币功能,你必须先反编译游戏知道修改金币的类和具体方法才可行。
这里我不仅Hook了系统的imei信息,也简单的Hook了系统的地理位置信息,在Android中获取经纬度信息有三种方式,这里为了演示简单,用了GPS定位功能,一般获取经纬度信息的代码主要是两处:
一处是初始化的时候调用getLastKnowLocation方法获取最后一次系统中的地理位置信息
//获取地理位置管理器
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);//获取LocationLocation location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);if(location!=null){//不为空,显示地理位置经纬度showLocation(location);}
还有一处就是监听地理位置变化的回调接口中的onLocationChanged回调方法:
/*** LocationListern监听器* 参数:地理位置提供器、监听位置变化的时间间隔、位置变化的距离间隔、LocationListener监听器*/LocationListener locationListener = new LocationListener() {@Overridepublic void onStatusChanged(String provider, int status, Bundle arg2) {}@Overridepublic void onProviderEnabled(String provider) {}@Overridepublic void onProviderDisabled(String provider) {}@Overridepublic void onLocationChanged(Location location) {//如果位置发生变化,重新显示showLocation(location);}};
所以如果想Hook系统的地理位置信息进行拦截,那么就需要操作这两处代码了,而他们有一个区别就是,第一处是通过返回值得到的,第二处是通过回调方法中的参数得到的。下面来看一下具体的Hook代码:
Hook第一处代码比较简单,直接构造一个假的Location对象然后设置返回值即可。
//定位hook_methods("android.location.LocationManager", "getLastKnownLocation", new XC_MethodHook(){@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {Log.i("jw", "hook getLastKnownLocation...");Location l = new Location(LocationManager.PASSIVE_PROVIDER);double lo = -10000d; //经度double la = -10000d; //纬度l.setLatitude(la);l.setLongitude(lo);param.setResult(l);}});
Hook第二处代码有点复杂,需要先找到添加位置监听的方法requestLocationUpdates,然后通过反射得到这个回调对象,找到具体的回调方法,然后在进行操作,因为回调方法是通过参数把Location对象传递回来的,所以这里需要修改参数值。
hook_methods("android.location.LocationManager", "requestLocationUpdates", new XC_MethodHook() {@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {Log.i("jw", "hook requestLocationUpdates...");if (param.args.length == 4 && (param.args[0] instanceof String)) {LocationListener ll = (LocationListener)param.args[3];Class<?> clazz = LocationListener.class;Method m = null;for (Method method : clazz.getDeclaredMethods()) {if (method.getName().equals("onLocationChanged")) {m = method;break;}}try {if (m != null) {Object[] args = new Object[1];Location l = new Location(LocationManager.PASSIVE_PROVIDER);double lo = -10000d; //经度double la = -10000d; //纬度l.setLatitude(la);l.setLongitude(lo);args[0] = l;m.invoke(ll, args);}} catch (Exception e) {XposedBridge.log(e);}}}});
好了,到这里我们就编写好了Hook系统的imei值和地理位置信息的模块了。
第三步:添加模块入口
这一步是非常重要的,也是最容易忘记的,就是要告诉Xposed框架一个模块中Hook的入口,这里可以看到模块的入口是Main类,所以需要在模块的assets中添加一个xposed_init文件:

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

第四步:添加模块的额外信息
最后一步就是需要在模块的AndroidManifest.xml文件添加额外信息,具体包括模块的描述信息,版本号等:
<meta-dataandroid:name="xposedmodule"android:value="true" /><meta-dataandroid:name="xposeddescription"android:value="Hook系统信息" /><meta-dataandroid:name="xposedminversion"android:value="30" />
经过上面四步之后咋们就完成了模块的定义了,最后咋们为了验证我们Hook的结果,在新建一个Activity类,在内部调用一下系统的获取imei方法以及位置信息方法,并且显示在屏幕中:
public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_demo);locationTxt = (TextView)findViewById(R.id.location);imeiTxt = (TextView)findViewById(R.id.imei);//获取地理位置管理器locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);//获取LocationLocation location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);if(location!=null){//不为空,显示地理位置经纬度showLocation(location);}//监视地理位置变化locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 3000, 1, locationListener);TelephonyManager telephonyManager = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);String imei = telephonyManager.getDeviceId();imeiTxt.setText("imei:"+imei);}
2. 运行模块
这时候看到,激活成功之后,会提示你再次重启设备才能生效,所以这里可以看到每次如果有新的模块或者是模块代码有更新了,比如这样:

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

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

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

看到了,百度地图在获取我们设备的imei和位置信息,当然这是符合正常情况的,从这里可以看到,我们还可以利用这个技术来观察设备中有哪些应用在获取设备的一些隐私数据。
3.实际用途
本文主要是介绍了Xposed框架的基本使用以及一个简单作用,但是在实际过程中,这个框架是非常有用的,比如在文章开头就说到了,我们可以通过修改系统的一些信息来帮助测试模拟复杂的测试环境,但是这个框架现在用的最广泛的当属破解了,这个也是我们后续讲解的重点,用这个框架咋们可以进行应用的脱壳,游戏的外挂等。
4.工程代码
附件列表
XPosed框架_简单的应用的更多相关文章
- 三星5.0以上机器最简单激活Xposed框架的经验
对于喜欢钻研手机的哥们来说,经常会接触到XPOSED框架及种类繁多功能强大的模块,对于5.0以下的系统版本,只要手机能获得ROOT权限,安装和激活XPOSED框架是比较轻易的,但随着系统版本的更新,5 ...
- 华为7.0系统最简单激活xposed框架的流程
对于喜欢搞机的哥们而言,很多时候会接触到Xposed框架及其种类繁多功能无敌的模块,对于5.0以下的系统版本,只要手机能获得root权限,安装和激活Xposed框架是异常简易的,但随着系统版本的不断更 ...
- 荣耀7.0系统手机最简单激活Xposed框架的步骤
对于喜欢玩手机的小伙伴来说,很多时候会使用到Xposed框架及各类功能彪悍的模块,对于5.0以下的系统版本,只要手机能获得Root权限,安装和激活Xposed框架是比较简便的,但随着系统版本的不断更新 ...
- 2_MVC+EF+Autofac(dbfirst)轻型项目框架_用户权限验证
前言 接上面两篇 0_MVC+EF+Autofac(dbfirst)轻型项目框架_基本框架 与 1_MVC+EF+Autofac(dbfirst)轻型项目框架_core层(以登陆为例) .在第一篇中介 ...
- [转]Android中Xposed框架篇—利用Xposed框架实现拦截系统方法
一.前言 关于Xposed框架相信大家应该不陌生了,他是Android中Hook技术的一个著名的框架,还有一个框架是CydiaSubstrate,但是这个框架是收费的,而且个人觉得不怎么好用,而Xpo ...
- [转载] 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 ...
- python_Tornado_web_框架_分页
如何实现web_框架_分页? -- 思考什么是xss跨站攻击? --别人把js代码提交到后台,然后从后台返回数据的时候,别人上传的js变成html中的代码, 就会插入别人的代码,带来极大的信息泄露的风 ...
- C++框架_之Qt的开始部分_概述_安装_创建项目_快捷键等一系列注意细节
C++框架_之Qt的开始部分_概述_安装_创建项目_快捷键等一系列注意细节 1.Qt概述 1.1 什么是Qt Qt是一个跨平台的C++图形用户界面应用程序框架.它为应用程序开发者提供建立艺术级图形界面 ...
- C++框架_之Qt的窗口部件系统的详解-上
C++框架_之Qt的窗口部件系统的详解-上 第一部分概述 第一次建立helloworld程序时,曾看到Qt Creator提供的默认基类只有QMainWindow.QWidget和QDialog三种. ...
随机推荐
- 解决 FusionCharts3.2.1 首页无法载入的问题
在实际项目中测试FusionCharts3.2.1时,发现首次载入无法正常载入,第二次载入就恢复正常! 原因:FusionCharts ID与变量名重复 以下是正常写法: var member ...
- 异步 ThreadPool
线程池是单例,一个进程里只有一个线程池 private void btnThreadPool_Click(object sender, EventArgs e) { Stopwatch watch = ...
- 最完整的台达PLC培训教程(沈阳工大)学习笔记1
1) 可编程控制器的应用1 开关量逻辑控制:电动机启动与停止2 运动控制:对步进电动机或伺服电动机的单轴或多轴系统实现位置控制3 过程控制:对温度.压力.流量等连续变化的模拟量进行闭环控制4 数据处理 ...
- 动态规划初步--最长上升子序列(LIS)
一.问题 有一个长为n的数列 a0,a1,a2...,an-1a.请求出这个序列中最长的上升子序列的长度和对应的子序列.上升子序列指的是对任意的i < j都满足ai < aj的子序列. 二 ...
- Linux C++/C开发所必需的一系列工具
系统平台下的开发工具.开发环境各有不同.Linux C++/C开发所必需的一系列工具: 1. vi(vim)文本编辑器一个UNIX世界标准的文本编辑器,简约而强大,不论作为开发人员还是系统管理员,熟练 ...
- Ueditor1.4.3上传视频IE下无法播放的问题
一:百度编辑器插入视频后,自动生成一段代码: <video class="edui-upload-video vjs-default-skin video-js" contr ...
- java socket domain name 使用域名.
java 的 socket 依赖了 nameService. 引擎模式. 使得 socket tcp 层 具有了上层业务的能力 (应用层) Socket socket=new Socket(&quo ...
- shell脚本,每5个字符之间插入"|",行末不插入“|”。
文本aaaaabbbbbcccccdddd eeeeefffffkkkkkvvvv nnnnnggggg 希望得到的结果如下: aaaaa|bbbbb|ccccc|dddd eeeee|fffff|k ...
- shell脚本,当用sed删除某一文件里面的内容时,并追加到同一个文件会出现问题。
shell脚本,当用sed删除某一文件里面的内容时,并追加到同一个文件会出现问题.因为初始文件和写入文件是一个文件这是失败的.需要追加到另一个文件,然后再用mv进行操作.[root@localhost ...
- shell脚本,判断给出的字符串是否相等。
第一种方法[root@localhost wyb]# .sh #!/bin/bash #判断给出的字符串是否相等 read -p "Please Input a number:" ...
