由于某些课程实验的要求,需要通过xposed框架对某应用进行hook操作,笔者选用了开源且免费的xposed框架进行实现。虽然网上存在一些利用xposed实现特定功能的文章资源,但大多均将xposed模块的构建作为一个小节内容一笔带过,而且介绍的内容随着考虑的因素、使用的编辑环境不同也大有区别,使得笔者在实际构建过程中往往提心吊胆,出现了错误也不知道如何去改正。故而这里特将笔者最近摸索和学习到的简单xposed构建的知识记录,以供查阅和参考。

Xposed 框架

  想要使用Xposed模块实现特定的功能,必须依赖Xposed框架,正如 apk 的运行需要Android系统提供支持一样,Xposed模块任务的完成也离不开Xposed框架的支持,Xposed框架提供了Xposed模块运行所必需的环境和功能接口,同时也可以对系统上已安装的模块进行禁用、卸载等管理。故而在想通过Xposed模块完成一定任务之前,必须安装Xposed框架。

  Xposed框架Installer下载地址:http://repo.xposed.info/module/de.robv.android.xposed.installer,安装的过程可参考网络资料。

  注意:由于Xposed框架安装时需要将系统文件夹/system/bin的部分文件进行替换和备份,故而手机需要具备root权限

Xposed 模块

  下面以Android Studio 3.0.1为例,总结下简单的Xposed模块的编写所需的配置和注意事项。

  项目创建

  Xposed模块实际上是作为一种较为特殊的apk安装在系统上,由于Xposed 模块的功能通常借助于其他应用和系统资源实现,其一般没有应用界面,故而创建一个没有活动的项目即可。

  A.在Android Studio中,点击 file -> new -> new project 进行新项目的创建。指定应用名称、公司域名、存储位置和包名等信息,这里需要注意应用名和包名这两个名字;

  

  B.勾选 Phone and Tablet 选项,选择该 Xposed 模块( 实际就是apk)将要运行的 Android 环境所对应的 API。注意这里的API指定的是Android环境与apk之间交互的接口,只有该API与之后apk实际运行的Android环境相匹配,apk才能正确的安装和运行。如笔者的 Xposed 模块将要运行在 Android 4.4上,则应该选择 Android 4.4 对应的API 19.

  

  C.在接下来的界面中,选择“ add no activity ”即不添加活动( Xposed 模块不需要活动 ),即可完成项目的创建。

  项目配置

  Xposed模块被视为一种特殊的apk,故而在创建项目之外,还需要针对其进行 Xposed 模块相关的配置。

  A. 切换目录结构。点击界面左上方的竖式 Project,展开项目界面,将项目结构从 Android 切换至 Project 模式,方便之后的编辑;

  

  B. 添加 Xposed API依赖。Xposed 模块的功能借助 Xposed 框架实现,Xposed 模块通过对应的 Xposed 框架 API 来使用 Xposed 框架提供的功能。想要使用 Xposed 框架 API,则必须提供对应的库( 名为 XposedBridge API jar)的路径等信息。(以下信息来自 Using the Xposed Framework API )

    *针对 Android Studio

    Android Studio 中使用gradle进行项目的构建,故而想要使用 Xposed 框架 API 对应的库,则需要在 gradle 的配置文件中进行指定。在 应用名(test) -> app -> build.gradle 中加入以下内容:

      repositories {  //通常新项目的 build.gradle 中不包含有repositories块,直接在空白处增加1-3行即可
jcenter();   } dependencies {  //通常 build.gradle 文件中已包含dependncies块,所以只需将第6行的内容添加进已有的 dependencies 中即可
provided 'de.robv.android.xposed:api:53'
    provided 'de.robv.android.xposed:api:53:sources' //该行是可选的,用于下载API相关的文档等信息
}

    其中,第2行表示将 jcenter 作为代码仓库,可在上面引用开源项目,而第 6 行则指定引用项目的项目名和版本信息。

    第6行的声明需要注意两点:

    a) 使用 provided 关键字而不是 compile,后者会将引用的 Xposed 框架 API 类打包至生成的 apk 中,而这些类在安装好的 Xposed 框架中是已经存在的,所以可能会产生冲突,而 provided 关键字则仅保留对 API 的引用,实现具体功能的类则由安装好的 Xposed 框架提供;

    b)使用系统对应的 Xposed 框架 api 版本,不同的 Xposed 框架 API 在不同的 Android 环境中发挥作用。如Android 4.x 环境则只能选择 API 53。

    

    *针对 eclipse

    eclipse 环境下无法通过指定 jcenter 中的开源项目来实现对其的引用,所以必须在实际的项目中手动添加所需引用的库文件 XposedBridge API jar 的路径,在这里手动下载所需的 API 版本,将其复制到项目的文件夹下( 注意不要放置在项目本身已经有的 lib / libs 文件夹下,原因与Android Studio环境下使用 provided 而不是 compile 一致 ),选中 jar 包 右键 -> Build Path -> add to build path 即可。

  

  C. Android Studio 环境下需要禁用 Instant run 。在 File -> Settings -> Build, Execution, Deployment -> Instant Run 中取消其勾选,否则源程序中的类会由一个 stub 应用加载,而不是直接包含在 apk 文件中,而 Xposed 框架目前无法处理这样的情况。

  D. 修改 AndroidManifest.xml 文件中的属性。在 应用名(test) -> app -> src -> main 文件夹中找到 AndroidManifest.xml,修改其中的属性,使得我们最终生成的 apk 能够被 Xposed 框架识别。请保证最终文件的部分内容为以下格式。

    <application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme" > // App相关的信息 <meta-data
android:name="xposedmodule" //标志该 apk 为一个 Xposed 模块,供 Xposed 框架识别
android:value="true" />
<meta-data
android:name="xposedminversion"
android:value="53" />     //xposed最小版本号,请与(2)步中选用的api版本保持一致
<meta-data
android:name="xposeddescription"
android:value="hook a function" /> //针对该模块的描述,会在Xposed框架的模块管理界面中显示出来,便于模块管理 </application>

  完成上述步骤后,则可将项目文件打包成 apk ( Android Studio 下打包 apk 的简单步骤可以参见这里),并在手机中安装。安装成功后,在 Xposed 框架的模块管理界面会出现该模块对应的管理项,证明对 Xposed 模块的配置是成功的。勾选对应的模块,并重启设备,重启之后该模块则开始发挥功能。当然目前我们并没有实现任何功能。

  

  简单示例

  在完成 Xposed 框架的配置后可在该项目中进行框架功能的编写。在 应用名(test) -> app -> src -> main -> java 目录下,可以看到 Android Studio 已经自动根据我们在创建项目时指定的包名生成了一个包( package )的条目,如笔者项目中的包名为 xposed.test(见创建项目时的界面截图),选中该包右键 -> new -> java  ->class ,创建自己的一个 class ,如 test.class 。用户可在该 class 中实现简单的xposed hook功能。

  ( 以下部分不涉及具体的实现原理,仅提供函数的简单功能的描述,更多关于Xposed 框架API的功能可在这里查看)

  一个 Xposed 模块可以有多个不同的入口,其中实现的方法既可以在 Android 系统启动时被调用,也可在一个应用程序包被加载时被调用,想要在不同的时期被调用,则该功能类需要实现不同的接口。

    Xposed公共接口
package:de.robv.android.xposed.IXposedHookZygoteInit
interface :IXposedHookZygoteInit   //在Android系统启动时被调用,作用于初始的zygote进程,可用于实现应用于所有应用的hook package:de.robv.android.xposed.IXposedHookLoadPackage
interface:IXposedHookLoadPackage  //当指定应用被加载时被调用,一般用于hook特定应用的方法 package:de.robv.android.xposed.IXposedHookInitPackageResources
interface:IXposedHookInitPackageResources//指定应用的资源进行初始化时被调用,一般用于资源的替换

  

  以实现 IXposedHookLoadPackage 接口的模块为例,实现一个简单的hook功能。

  通常使用 findAndHookMethod 方法来定位待 hook 的类中的方法(官方解释在这里)

    findAndHookMethod(String className, ClassLoader classLoader, String methodName, Object... parameterTypesAndCallback)
 className:被hook的方法所在类的完整名称,包括 包名 + 类名
 classLoader:可通过 lpparam.classLoader 获得
methodName:被hook的方法的名,注意如有混淆,则应该用混淆后的名字
object... 与为被hook的方法的参数对应
Callback :指定该方法被调用时,需要被执行的回调

  例如,想要hook如下代码,即hook包 com.test.example 中的类 a 下的 b 方法

    package com.test.example
public class a{
public int b(String s, int i, MyClass m)
{}
}

  则对应的 findAndHookMethod方法应该写作

   findAndHookMethod("com.test.example.a", lpparam.classLoader,"b", String.class, int.class, "com.test.example.MyClass", new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
do somthing
}
});
这里需要注意:
(1)对于待hook函数中的java自带类型的参数,如 int 和 String,则应使用 int.class 和 String.class 作为findAndHookMethod的参数
(2)若待Hook函数中包含有形如 MyClass 这样的自定义类型的参数,则直接使用该类型的完整路径名即可,如 "com.test.example.MyClass"

  在 findAndHookMethod 方法的参数中,直接定义了一个 XC_MethodHook 回调,其中一般有两个方法可供使用者重新定义。

   @Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
// 该方法在被hook函数之前被调用
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
// 该方法在被hook函数之后被调用
}

  以下代码实现了微信的一个日志函数的简单 hook 。

 package xposed.xposed_wechat_log;  //实现的类所在的包

 import android.util.Log;       //系统提供的Log方法的包
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;  //findAndHookMethod方法所在的包
import de.robv.android.xposed.IXposedHookLoadPackage;           
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam; public class test implements IXposedHookLoadPackage {  //test类实现了IXposedHookLoadPackage接口
@Override
public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable {  // handleLoadPackage 在任意包被加载时被调用,参数lpparam,包含有加载的 app 的信息
if ( lpparam.packageName.equals("com.tencent.mm")) {             // 可通过 lpparam 中包含的包信息对包进行筛选,如这里表示 com.tencent.mm 包加载时,才执行下一步操作
findAndHookMethod("com.tencent.mm.sdk.platformtools.x",lpparam.classLoader, "d" , String.class, String.class, Object[].class,
new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
String str0 = (String) param.args[0];              //可通过 param.args[i]获得 hook 方法的参数
String str1 = (String) param.args[1];
Object[] obj2= (Object[]) param.args[2];
String str = obj2 == null ? str1 : String.format(str1, obj2); if( str==null)
str = ""; Log.e( "Xposed_hook_d"+str0,str);
super.beforeHookedMethod(param);
}
});
    }
  }
}

simple_hook

  

  完成上述模块功能的编写后,需在 应用名(test) -> app -> src -> main 目录下新建一个 assets 目录,并在该目录下建立一个名为 exposed_init 的文本文件。该文件中记录模块中所有实现了Xposed 功能接口的类的完整路径名,每一行书只写一个这样的路径。

  如在上述实例模块中,test 类实现了接口 IXposedHookLoadPackage,则 exposed_init 文件中应该有以下内容:

    xposed.test.test  //其中 xposed.test 为包名,test为实现接口的类名

  所有实现了 Xposed 接口的类均要在该文件中记录,以供 Xposed 框架进行处理。

  之后即可打包完成的项目,将其安装至设备上进行验证了。

参考资料:

  1. [TUTORIAL]Xposed module development详细的xposed模块开发示例

  2. Using the Xposed Framework API关于如何在模块中使用Xposed框架提供的API

  3.  Development tutorial简单的xposed模块示例

Xposed模块开发基本方法记录的更多相关文章

  1. Xposed模块开发学习记录

    Xposed模块相关API可以参考在线文档: https://api.xposed.info/reference/packages.html     入门教程可以参考: https://github. ...

  2. Xposed模块开发教程

    转:http://vbill.github.io/2015/02/10/xposed-1/     http://blog.csdn.net/zhangmiaoping23/article/detai ...

  3. 安卓手机安装虚拟定位的方法Xposed安装器+模拟位置(Xposed模块)

    原文:https://www.52pojie.cn/thread-571328-1-1.html 未测试,据说只支持某些手机,小米和华为很难安装,建议买其他品牌. Xposed安装器步骤:·ROOT你 ...

  4. python开发_常用的python模块及安装方法

    adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheetahcherrypy:一个WEB frameworkctype ...

  5. Qt开发的应用记录读取用户习惯设置的方法

    Qt开发的应用记录读取用户习惯设置的方法 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/w ...

  6. javascript的模块开发方法;

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. js模块开发(一)

    现在嵌入页面里面的javascript代码越来越复杂,于是可能依赖也越来越严重,使用别人开发的js也越来越多,于是在理想情况下,我们只需要实现核心的业务逻辑,其他都可以加载别人已经写好的模块. 于是j ...

  8. 基于ASP.NET MVC的热插拔模块式开发框架(OrchardNoCMS)--模块开发

    之前文章中给大家说明了下我这个小小的想法,发现还是有不少人的支持和关注.你们的鼓励是对我最大的支持. 我总结了了大家的评论,有以下几个问题: 1.希望有更多的文档说明. 2.希望介绍下Orchard的 ...

  9. js模块开发

    js模块开发(一) 现在嵌入页面里面的javascript代码越来越复杂,于是可能依赖也越来越严重,使用别人开发的js也越来越多,于是在理想情况下,我们只需要实现核心的业务逻辑,其他都可以加载别人已经 ...

随机推荐

  1. 在ubuntu下使用visual studio code编写python

    感觉有了visual studio code之后,不管编写什么语言的代码都可以,简单安装对应的语言插件即可. 这不轮到了最近比较热的python语言,蹭着AI的热度,python语言成为了工程师们又一 ...

  2. UUID 压缩为22位

    public class Generator { private static char[] BASE64 = "abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJK ...

  3. ORB-SLAM2实现(kinect V1/ROS)

    实验室电脑环境ubuntu14.04和ROS indigo已经装好. 1. 构建工作空间[非常重要的一步] mkdir -p ~/catkin_ws/src cd ~/catkin_ws/ catki ...

  4. CenOs7安装oracle图文详细过程(02)

    原创作品,转载请在文章头部(显眼位置)注明出处:https://www.cnblogs.com/sunshine5683/p/10011574.html 8.修改用户限制 vim /etc/secur ...

  5. linux服务器上部署jdk+tomcat+rocketmq+redis-cluster

    通常我们拿到一组干净的linux服务器,需要初始化安装一些基础软件,这里一站式介绍部署jdk+tomcat+rocketmq+redis-cluster 前言:如果要在多台服务器上安装,在一台服务器上 ...

  6. java 自定义泛型

    package com.direct.demo; import java.util.ArrayList; import java.util.HashMap; import java.util.Link ...

  7. BZOJ P4720[Noip2016]换教室____solution

    题目太长不表 <--无形传送,最为致命 学习一点数学期望的基础,预处理最短路,然后加上DP即可.(废话) 理解决策和结果的差别: 在这里每阶段的决策有两个:申请|不申请 结果有两个:换|不换 然 ...

  8. JS上传图片转化成Base64编码demo

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

  9. 在linux中给你的应用做压力测试

    在linux中给你的应用做压力测试 作者: 立地 邮箱: jarvin_g@126.com QQ: 511363759 一.webbench 1.在Ubuntu中安装webbench —支持get,h ...

  10. html5 移动端开发

    移动端开发总结     目录 1.手机与浏览器 2.Viewport(视窗) 3. 媒体查询 4.px,em,rem,pt 5.设备像素比devicePixelRatio 6.移动web中的图标及字体 ...