一、Xposed简介

Xposed是一款优秀的android java层 hook 框架。它允许你在不修改apk源码的情况下,通过编写自己的模块来改变apk的行为。它的优点是采用了插件机制,模块能够适用不同版本的框架和rom。模块改变apk行为的操作发生在内存中,对源apk不进行任何修改。你只需要安装编写的模块并重启相应的设备即可。

二、相关资源

Xposed 官网:http://repo.xposed.info/
Xposed 项目 github 地址:https://github.com/rovo89
Xposed 官方教程 :https://github.com/rovo89/XposedBridge/wiki/Development-tutorial
Xposed Api 之XposedBridge.jar 下载:https://jcenter.bintray.com/de/robv/android/xposed/api/

三、使用Xposed

1.安装Xposed 框架

首先你需要在手机设备上安装Xposed 框架,官网上给我们提供了一个apk 来完成框架的安装。

Xposed Installer官方下载:http://repo.xposed.info/module/de.robv.android.xposed.installer

由于Android系统5.0以上默认采用了ART模式,Android系统5.0 以下默认采用Davik模式。所以目前Xposed框架主要有两个版本:一个是Android 4.0.3 to Android 4.4版本,一个是Android 5.0 以上版本。
我们以Android 4.0.3 to Android 4.4版本为例。

下载Xposed installer 成功后,将de.robv.android.xposed.installer.apk安装在海马模拟中或者已经root真机上

选择 框架 ,可看到app_process和XposedBridge.jar需要激活

选择 安装/更新,会提示重启

重启后,会发现app_process和XposedBridge.jar已经激活。

2.编写相关的模块

现在我们来编写Xposed模块。

1.创建一个Android 工程

一个Xposed 模块本质上是一个正常的apk,只是这个apk没有与用户交互的Activity界面,它仅仅包含一些mete 数据和文件,并且该apk安装后在桌面应用中没有图标显示。所以你只需要创建一个空的安卓工程,不需要添加任何Actitity.

2. 将Android 工程变成Xposed模块

在工程中添加 Xposed Framework API

Xposed模块为了使用Xposed框架的api ,需要下载相应的 XposedBridge.jar 包。

Android Studio (Gradle-based)

Xposed Framework API 在下面网址上可进行查看:
https://bintray.com/rovo89/de.robv.android.xposed/api
在 Androdri Studio 工程中app/build.gradle文件中添加依赖项:

repositories {jcenter();
}dependencies {provided 'de.robv.android.xposed:api:53'
}

重要的事情说三遍!使用 provided 不要使用 compile! compile 会将整个 API 类 编译进你的apk中而导致出问题。provided 则只是提供了API 类的引用,API 类真正的实现则在 Xposed FramWork中。
在大多数情况下,repositories已经存在,并且已经有一些依赖,所以只需要将provided 这一行添加到存在的dependcies模块中即可。
如果 需要查看api资源,则添加下面的两行:

provided 'de.robv.android.xposed:api:53'
provided 'de.robv.android.xposed:api:53:sources'

确保关闭Instant Run项File -> Settings -> Build, Execution, Deployment -> Instant Run,否者你的apk中将不包含这些类

Eclipse
Eclipse创建的工程需要创建相应的jar包,jar包地址下载:https://jcenter.bintray.com/de/robv/android/xposed/api/

推荐将下载的api-XX.jar包放入到lib子目录中,不要将jar包放入到libs 子目录中。因为libs 目录中的jar包会使Eclipse将API类编译到APK中,而事实上API只需要引用即可。

右击api-XX.jar文件选择Build Path -> Add to Build Path 即可

Xposed Framework API

android 5.0以前的版本,推荐使用API 53

http://api.xposed.info/reference/packages.html

AndroidManifest.xml 文件配置

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="de.robv.android.xposed.mods.tutorial"android:versionCode="1"android:versionName="1.0" ><uses-sdk android:minSdkVersion="15" /><application
        android:icon="@drawable/ic_launcher"android:label="@string/app_name" ><meta-data
            android:name="xposedmodule"android:value="true" /><!--应用为模块--><meta-data
            android:name="xposeddescription"android:value="Easy example which makes the status bar clock red and adds a smiley" /><!--模块描述--><meta-data
            android:name="xposedminversion"android:value="53" /> <!--版本信息--></application>
</manifest>

模块实现

在模块中创建一个类,并命名为 ’Tutorial‘,该类放在de.robv.android.xposed.mods.tutorial 包中。类名和包名是可以任意取的。

package de.robv.android.xposed.mods.tutorial;public class Tutorial {}

教程的第一步,我们只需要将加载的模块信息打印出来。

一个模块有一些进入点,这些进入点的选择取决于你想修改的位置。你可以让Xposed框架调用你模块中的函数在下面几个位置:安卓系统启动的时候(使用 IXposedHookZygoteInit 接口)、一个新的app被加载的时候(使用 IXposedHookLoadPackage 接口)、一个资源被初始化的时候( 使用 IXposedHookInitPackageResources 接口)。

所有的进入点 都是 XposedMod 接口的子接口。在本示例中,进入点是“一个新的app被加载的时候”,我们需要实现
IXposedHookLoadPackage 接口。事实上该接口只有一个带有一个参数的方法,该参数中给出了加载的应用的Context 信息:

package de.robv.android.xposed.mods.tutorial;import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;public class Tutorial implements IXposedHookLoadPackage {public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {XposedBridge.log("Loaded app: " + lpparam.packageName);}
}

log方法将写信息到标准的ogcat中(/data/data/de.robv.android.xposed.installer/log/debug.log)

assets/xposed_init

XposedBridge 从assets 目录中的xposed_init 文件中获取入口点。xposed_init文件中每行配置一个进入点,使用完全限定名。在该例子中,进行如下配置

de.robv.android.xposed.mods.tutorial.Tutorial.

3.运行模块

在设备上安装该模块,安装成功后看不到模块的界面。第一次安装该模块后,你需要在Xposed Install app中启动模块。打开Xposed Install app,选择“Modules”tab 后。勾选模块,并重启Android系统。

这时你打开Xposed Install app 日志模块,会发现下面的输出:

四、替换资源

替换Boolean, Color, Integer, int[], String and String[]类型的简单资源

1.替换系统框架(Android Framwork)资源

替换系统框架资源(对所有app 起作用)需要实现 IXposedHookZygoteInit接口的 initZygote 方法,并在该方法中调用Resources.setSystemWideReplacement(...) 方法替换资源

package de.robv.android.xposed.mods.tutorial;import android.content.res.XResources;
import de.robv.android.xposed.IXposedHookZygoteInit;public class Tutorial2  implements IXposedHookZygoteInit{@Overridepublic void initZygote(StartupParam arg0) throws Throwable {XResources.setSystemWideReplacement("android", "bool", "config_unplugTurnsOnScreen", false);}}

2.替换app应用资源

替换app应用资源需要实现 IXposedHookInitPackageResources 类的
andleInitPackageResources方法,并在该方法中调用res.setReplacement(...)方法替换资源,注意在该方法中不要使用XResources.setSystemWideReplacement 方法

package de.robv.android.xposed.mods.tutorial;import android.content.res.XResources;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import de.robv.android.xposed.IXposedHookInitPackageResources;
import de.robv.android.xposed.callbacks.XC_InitPackageResources.InitPackageResourcesParam;public class Tutorial3 implements  IXposedHookInitPackageResources  {@Overridepublic void handleInitPackageResources(InitPackageResourcesParam resparam) throws Throwable {//只替换systemui应用的资源if (!resparam.packageName.equals("com.android.systemui"))return;// 替换资源的不同方式resparam.res.setReplacement(0x7f080083, "YEAH!"); // WLAN toggle text. You should not do this because the id is not fixed. Only for framework resources, you could use android.R.string.somethingresparam.res.setReplacement("com.android.systemui:string/quickpanel_bluetooth_text", "WOO!");resparam.res.setReplacement("com.android.systemui", "string", "quickpanel_gps_text", "HOO!");resparam.res.setReplacement("com.android.systemui", "integer", "config_maxLevelOfSignalStrengthIndicator", 6);resparam.res.setReplacement("com.android.systemui", "drawable", "status_bar_background", new XResources.DrawableLoader() {@Overridepublic Drawable newDrawable(XResources res, int id) throws Throwable {return new ColorDrawable(Color.WHITE);}});//你不能直接使用Drawble类进行替换,因为Drawble类可以影响其他引用Ddrawble类实例的ImageView ,最好使用一个包装器。}}

替换复杂的资源

对于复制的资源,如动画资源 ,我们也能够替换,下面我们来替换battery icon

动画资源布局

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"android:oneshot="true" ><item android:drawable="@drawable/icon1" android:duration="150"></item><item android:drawable="@drawable/icon2" android:duration="150"></item><item android:drawable="@drawable/icon3" android:duration="150"></item><item android:drawable="@drawable/icon4" android:duration="150"></item><item android:drawable="@drawable/icon5" android:duration="150"></item><item android:drawable="@drawable/icon6" android:duration="150"></item></animation-list>

代码:

package de.robv.android.xposed.mods.tutorial;import com.example.xposedmoduletest.R;import android.content.res.XModuleResources;
import de.robv.android.xposed.IXposedHookInitPackageResources;
import de.robv.android.xposed.IXposedHookZygoteInit;
import de.robv.android.xposed.callbacks.XC_InitPackageResources.InitPackageResourcesParam;public class Tutorial4 implements IXposedHookZygoteInit, IXposedHookInitPackageResources {private static String MODULE_PATH = null;@Overridepublic void initZygote(StartupParam startupParam) throws Throwable {MODULE_PATH = startupParam.modulePath;}@Overridepublic void handleInitPackageResources(InitPackageResourcesParam resparam) throws Throwable {if (!resparam.packageName.equals("com.android.systemui"))return;XModuleResources modRes = XModuleResources.createInstance(MODULE_PATH, resparam.res);resparam.res.setReplacement("com.android.systemui", "drawable", "stat_sys_battery",modRes.fwd(R.drawable.animation));resparam.res.setReplacement("com.android.systemui", "drawable", "stat_sys_battery_charge",modRes.fwd(R.drawable.animation));}
}

Xposed框架会将模块请求资源的请求指向你模块中的资源
替换的效果:

替换布局

你可以用替换资源的方法来替换布局文件,但这样你不得不将目标apk中的整个layout文件复制出来进行修改,这样会使模块的Rom兼容性降低。并且如果两个以上的模块修改布局后,最后修改布局的模块会起作用。更重要的是,布局中指向其它资源的ID很难确定下来。推荐使用下面的方法修改布局:

package de.robv.android.xposed.mods.tutorial;import android.graphics.Color;
import android.widget.TextView;
import de.robv.android.xposed.IXposedHookInitPackageResources;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.callbacks.XC_InitPackageResources.InitPackageResourcesParam;
import de.robv.android.xposed.callbacks.XC_LayoutInflated;
import de.robv.android.xposed.callbacks.XC_LayoutInflated.LayoutInflatedParam;public class Tutorial5 implements   IXposedHookInitPackageResources{@Overridepublic void handleInitPackageResources(InitPackageResourcesParam resparam) throws Throwable {if (!resparam.packageName.equals("com.android.systemui"))return;resparam.res.hookLayout("com.android.systemui", "layout", "status_bar", new XC_LayoutInflated() {@Overridepublic void handleLayoutInflated(LayoutInflatedParam liparam) throws Throwable {TextView clock = (TextView) liparam.view.findViewById(liparam.res.getIdentifier("clock", "id", "com.android.systemui"));clock.setTextColor(Color.RED);XposedBridge.log("layout  resNames.fullname:"+liparam.resNames.fullName);XposedBridge.log("layout  resNames.id:"+liparam.resNames.id);XposedBridge.log("layout  resNames.name:"+liparam.resNames.name);XposedBridge.log("layout  resNames.pkg:"+liparam.resNames.pkg);XposedBridge.log("layout  resNames.type:"+liparam.resNames.type);XposedBridge.log("layout  resNames.variant:"+liparam.variant);XposedBridge.log("layout  resNames.view:"+liparam.view);}}); }}

回调方法handleLayoutInflated 会在layout文件被填充后回调,在方法的 LayoutInflatedParam 对象 参数中,你可以找到你想修改的View组件。你也可以通过调用resNames来确定加载的那一个布局文件。用 variant来确定加载的布局的目录’layout-land‘。res 同时也会帮你获取资源的ID和其它的资源。

五、用反射来hook方法

每当应用加载的时候,IXposedHookLoadPackPage接口的handLoadPackage方法就会被调用执行,为了让我们在正确的进程中执行,需要先判断被加载的包是不是正确的包

package de.robv.android.xposed.mods.tutorial;import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;public class Tutorial6 implements IXposedHookLoadPackage {@Overridepublic void handleLoadPackage(LoadPackageParam param) throws Throwable {if(!param.packageName.equals("com.android.systemui"))return;}}

一旦我们进入到正确的进程进后,我们就能用param变中的ClassLoad来访问该进程中加载的类

package de.robv.android.xposed.mods.tutorial;import android.webkit.WebView.FindListener;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XC_MethodHook.MethodHookParam;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
public class Tutorial6 implements IXposedHookLoadPackage {@Overridepublic void handleLoadPackage(LoadPackageParam param) throws Throwable {if(!param.packageName.equals("com.android.systemui"))return;findAndHookMethod("com.android.systemui.statusbar.policy.Clock",param.classLoader, "updateClock", new XC_MethodHook() {@Overrideprotected void beforeHookedMethod(MethodHookParam param) throws Throwable {// this will be called before the clock was updated by the original method}@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {// this will be called after the clock was updated by the original method}});}}

XposedHelpers是一个重要的工具类,推荐用Eclipse的同学静态导入该类中的方法 import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;。该类能够通过反射机制来访问方法、构造器、域。
findAndHookMehthod(String packageName,Class<?> clazz, String methodName, Object... args))方法来对函数进行Hook。如果在方法前和方法后Hook,该方法最后一个参数需要实现XC_MethodHook类的beforeHookedMethodafterHookedMethod方法,如果想要替换整个方法,则需要实现XC_MethodReplacement类的replaceHookedMethod方法
XposedBridge保存了每个Hook方法的回调方法。优先级高的回调方法被优先调用A.before -> B.before -> original method -> B.after -> A.after

package de.robv.android.xposed.mods.tutorial;import android.graphics.Color;
import android.webkit.WebView.FindListener;
import android.widget.TextView;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XC_MethodHook.MethodHookParam;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
public class Tutorial6 implements IXposedHookLoadPackage {@Overridepublic void handleLoadPackage(LoadPackageParam param) throws Throwable {if(!param.packageName.equals("com.android.systemui"))return;findAndHookMethod("com.android.systemui.statusbar.policy.Clock",param.classLoader, "updateClock", new XC_MethodHook() {@Overrideprotected void beforeHookedMethod(MethodHookParam param) throws Throwable {// this will be called before the clock was updated by the original method}@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {TextView tv = (TextView) param.thisObject;//获取调用该方法类的对象String text = tv.getText().toString();tv.setText(text + " :)");tv.setTextColor(Color.RED);}});}}

Xposed的框架的使用相关推荐

  1. Xposed Installer框架 安卓版

    Xposed Installer框架是一款可以在不修改APK的情况下影响程序运行(修改系统)的框架服务,基于它可以制作出许多功能强大的模块,且在功能不冲突的情况下同时运作. Xposed Instal ...

  2. Android逆向之旅---破解某支付软件防Xposed等框架Hook功能检测机制

    一.情景介绍 最近想写几个某支付软件的插件,大家现在都知道现在插件大部分都是基于Xposed的hook功能,包括之前写了很多的某社交软件的插件,所以不多说就直接用Jadx打开支付软件之后然后找到想要h ...

  3. fidder+Xposed JustTruestMe框架安装,解决网络错误

    fidder开启代理后部分APP为什么会出现网络错误:   查找了网上很多资料,和HTTPS中SSL Pinging 特性有关:   SSL Pinging, 即 SSL 证书绑定,是在HTTPS协议 ...

  4. xposed定位插件_GpsHook实现模拟定位,手机需安装Xposed类框架

    [实例简介] [实例截图] [核心代码] package com.markypq.gpshook; import android.Manifest; import android.annotation ...

  5. 基于xposed Hook框架实现个人免签支付方案(支付宝)

    这个有点非常复杂的,关键点在于如何逆向微信支付宝云闪付这些App,找到核心函数钩子 反编译apk稍微提一下 方法:使用jadx反编译(推荐,简单方便) 首先下载jadx,下载地址:https://gi ...

  6. Android 集成Xposed框架

    前言 Xposed(框架) Xposed框架(Xposed Framework)是一套开源的.在Android高权限模式下运行的系统框架服务,可以在不修改APK文件的情况下影响程序运行(修改系统)的框 ...

  7. 基于Xposed框架截取安卓手机应用数据信息

    首先介绍的是Xposed只是一个安卓手机的框架,并不具有任何功能,为了实现个人的需求,我们需要自己编写模块加入到这个框架中去.现如今比较主流的Xposed框架包括微信运动步数的作弊模块.微信的虚拟位置 ...

  8. Edxposed安装和xposed框架在Android 8.0以上手机使用最全攻略

    d在网上,关于Xposed模块编写的博客文章可谓是一抓一大把.但由于时间的推移,很多工具和方法都发生了变化,也正因此,网上的文章往往有一些时限性,比如现如今 provide 这个关键字已经被舍弃了却仍 ...

  9. android4.2.2原生锁屏,酷派大神Note(原生4.2.2Android)L风格+Xposed框架+自定义

    酷派大神Note(原生4.2.2Android)L风格+Xposed框架+自定义是一款残芯大的大神Note安卓原生版,希望大家会喜欢~支持:锁屏画面调整,状态栏调整,虚拟键调整,透明度调整,电源调整, ...

  10. 安装xposed(解决xposed问题)

    科学上网可轻松解决本文的问题 经过测试leidian.mumu.yeshen三个模拟器的最新版本只有leidian安装完成后可以重启,其他两个均会卡99%(模拟器再起不能).[MuMu模拟器win版] ...

最新文章

  1. Microbiome:16S扩增子测序研究中定量变异和生物量影响
  2. 畅捷通携手易后台,专注小微企业财税服务
  3. 剪刀、石头、布机器人比赛
  4. 《5G新体制天线技术》
  5. Java生鲜电商平台-订单配送模块的架构与设计
  6. 【LeetCode】3月27日打卡-Day12
  7. 【JavaScript】用Switch实现成绩等级判断
  8. mac下使用Charles抓chrome包
  9. Dubbo学习总结(10)——里程碑式 Dubbo 2.7.5 版本发布,性能提升30%,支持 HTTP/2、TLS、Protobuf等特性。
  10. 《长安十二时辰》火了!程序员版本过于真实!
  11. 2021-03-06JAVA大数据Week1
  12. java实现梯度异步通知,BIO原理及代码实现
  13. bing翻译api php,免费翻译接口
  14. mysql数据库初始化 error Found option without preceding group in config file
  15. 学计算机拼音摇号,电脑摇号:作弊100%!
  16. 二元函数凹凸性判定及最值定理
  17. 实现移动端查看控制台
  18. TP5集成支付宝h5支付接口
  19. Docker所在目录以及查询正在运行容器的所在位置
  20. Linux 之软连接

热门文章

  1. 微信小程序 —— 成员管理及开发管理
  2. storm风暴英雄 tempo_风暴英雄Tempo Storm 安娜版本天梯环境速报 安娜强度居T3
  3. 企业如何自建MDM 移动设备管理平台
  4. 多媒体数字互动技术的应用有哪些?
  5. error while trying to retrieving text
  6. 下载chrome插件离线包
  7. 进化吧,MySQL锁!无锁->偏向锁->轻量级锁->重量级锁(请自动脑补数码宝贝进化音)
  8. sql 脚本 昨天的日期获取,今天的前一天的数据获取, 前两个月的今天
  9. Kernel, tainted, 被污染的实例
  10. PointRCNN: 3D Object Proposal Generation and Detection from Point Cloud【翻译】