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);
}
}
@Override
public void handleLoadPackage(final LoadPackageParam lpp) throws Throwable{
Log.i("jw", "pkg:"+lpp.packageName);
//hook 系统函数getDeviceId 函数,并将返回值设置为jiangwei
hook_method("android.telephony.TelephonyManager", lpp.classLoader, "getDeviceId", new XC_MethodHook() {
@Override
protected 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(){
@Override
protected 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() {
@Override
protected 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);
//获取Location
Location location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if(location!=null){//不为空,显示地理位置经纬度showLocation(location);}
还有一处就是监听地理位置变化的回调接口中的onLocationChanged回调方法:
/**
* LocationListern监听器
* 参数:地理位置提供器、监听位置变化的时间间隔、位置变化的距离间隔、LocationListener监听器
*/
LocationListener locationListener = new LocationListener() {
@Override
public void onStatusChanged(String provider, int status, Bundle arg2) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
@Override
public void onLocationChanged(Location location) {
//如果位置发生变化,重新显示
showLocation(location);
}
};
所以如果想Hook系统的地理位置信息进行拦截,那么就需要操作这两处代码了,而他们有一个区别就是,第一处是通过返回值得到的,第二处是通过回调方法中的参数得到的。下面来看一下具体的Hook代码:
Hook第一处代码比较简单,直接构造一个假的Location对象然后设置返回值即可。
//定位
hook_methods("android.location.LocationManager", "getLastKnownLocation", new XC_MethodHook(){
@Override
protected 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() {
@Override
protected 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-data
android:name="xposedmodule"
android:value="true" />
<meta-data
android:name="xposeddescription"
android:value="Hook系统信息" />
<meta-data
android: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);
//获取Location
Location 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三种. ...
随机推荐
- 修改nagios登录界面密码
htpasswd -c /usr/local/nagios/etc/htpasswd.user nagiosadmin 输入密码: 重启httpd服务.
- sysdig安装和使用介绍
安装步骤1)安装资源库rpm --import https://s3.amazonaws.com/download.draios.com/DRAIOS-GPG-KEY.publiccurl -s -o ...
- OpenGL列主元矩阵和列主序存储
OpenGL矩阵要考虑两个点,一个是向量如何排布,一个是矩阵如何存储和恢复. 1.排布 排布决定了运算的顺序.OpenGL使用的是列主元,它的意思就是一个4X4的矩阵是由4个列向量构成(这里的v1,v ...
- windows定时任务小注
static class Program { /// <summary> /// 应用程序的主入口点. /// </summary> [STAThread] static vo ...
- UIWebView与JavaScript相互调用
UIWebView与JavaScript的那些事儿 UIWebView是IOS SDK中渲染网面的控件,在显示网页的时候,我们可以hack网页然后显示想显示的内容.其中就要用到javascript的知 ...
- 在idea下创建maven
之前一直用eclipse,现在要用idea写一个安装过程玩玩 一:New Project 二:选择maven,在project SDK上选择你安装的jdk,默认安装在c:/Program Files ...
- 传统BP对比CNN
传统BP vs CNN 存在2个问题 传统BP网络存在的问题: 权值太多,计算量太大 权值太多,需要大量样本进行训练 传统的BP来处理图像问题的话因为计算权值太多太大. 网络的建立要根据数据的大小来建 ...
- 利用java自带的base64实现加密、解密
package com.stone.util; import java.io.UnsupportedEncodingException; import sun.misc.*; public class ...
- Codeforces Round #274 (Div. 2)-C. Exams
http://codeforces.com/contest/479/problem/C C. Exams time limit per test 1 second memory limit per t ...
- QT +样式表
学习样式表的目的:可以设计出好看的控件.(比如可以给一些按钮设计成好看的图片) QT 样式表的思想很大程度上是来自于HTML的层叠式样式表(CSS),通过调用QWidget->setStyleS ...