Android java层hook------xposed框架的使用
xposed曾经是android平台上最好的java层hook和调试工具,由于已经不再更新,当前支持的android系统版本比较老旧,目前只能支持到android6.0,故已经逐渐落伍,目前android上最广泛使用的hook工具是frida,这是另一个话题。本文不涉及xposed的原理和底层实现,只是基于雷电模拟器和eclipse,对xposed的使用方法做一个简单说明,以期能达到熟练使用的目的。至于为什么是eclipse,因为过去一段实践内,android的主流开发工具就是eclipse加adt,android studio的广泛使用是2015、2016年之后的事了。
雷电模拟器下载地址:点击下载
本文代码工程例子下载地址:点击下载
(一)使用方法
雷电模拟器安装后如下如所示(模拟器中安装的android版本是5.1):

搜索xposed并安装:

安装xposed后,点击左上角菜单中的“框架”按钮,然后点击”version89",选择“直接安装”后,会自动下载安装xposed框架,框架安装完成后如下所示:

在左上角的按钮中点击”模块“按钮,可以看到安装的xopsed模块:

下面开始介绍插件开发。
(二)插件开发
eclipse是一个强大的多平台、多语言开发工具,到目前为止仍然有很多项目是基于此工具维护和开发的,插件开发基于古老的eclipse。
首先编写一个android程序test,包名为com.example.test,主类名为com.example.test.MainActivity,然后再该工程上右键”run as“–>“Android Application”,将其安装到模拟器中。
接下来,编写xposed插件来hook该程序主类中的onCreaete函数。
在eclipse中创建一个Android项目,包名为com.xposedtest ,接下来的项目选项一路点击"确定"。创建好项目后,在包中创建一个主类,名为XposedTest。
- Androidmanifest.xml中Application节区插入如下代码:
<meta-data android:name="xposedmodule" android:value="true" /><meta-data android:name="xposedminversion" android:value="30" /><meta-data android:name="xposeddescription" android:value="xposed_hook_test"/>
该节区是xposed插件的版本和描述信息。
- assets文件夹下新建文件xposed_init文件,其内容为xposed插件的主类名,比如当前为com.xposedtest.XposedTest。
- 导入XposedBridgeApi-54.jar包。该包是xposed插件开发必不可少的支持包。在eclipse中点击"project"按钮–>“properties”–>“Java build path” -->“Libraries”–>“Add External Jars”,然后在选择框内选中jar包XposedBridgeApi-54.jar。
- 在xposed插件的主类XposedTest中,如下编写hook代码:
package com.xposedtest;import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.text.Editable;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Toast;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XC_MethodHook.Unhook;
import de.robv.android.xposed.XposedHelpers;
//import de.robv.android.xposed.callbacks.XC_InitPackageResources.Unhook;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;public class XposedTest implements IXposedHookLoadPackage {public final static String LOG_FILE_PATH = "/storage/sdcard0/XposedLog/"; public final static String LOG_FILE_NAME = "XposedLog.txt";public final static int START_FLAG = 0;public static String TAG = "XposedTest";public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable {if (lpparam.packageName.equals("com.example.test") == true ){Log.e(TAG,"handleLoadPackage");Context context = getContext();if(context!=null){Toast.makeText(context, "handleLoadPackage", Toast.LENGTH_LONG).show();}XposedHelpers.findAndHookMethod("com.example.test.MainActivity", lpparam.classLoader, "onCreate", Bundle.class,new XC_MethodHook() {@SuppressLint("ShowToast") @Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {XposeWriteLogFile(" after param\r\n");Context context = getContext();Toast.makeText(context, "after onCreate", Toast.LENGTH_LONG).show();Log.e(TAG,"after onCreate");XposeWriteLogFile("after result:\r\n");}@SuppressLint("ShowToast") @Overrideprotected void beforeHookedMethod(MethodHookParam param) throws Throwable {XposeWriteLogFile(" before param\r\n");Context context = getContext();Toast.makeText(context, "before onCreate", Toast.LENGTH_LONG).show();Log.e(TAG,"before onCreate");}});}}public static Context getContext(){try {Class<?> ActivityThread = Class.forName("android.app.ActivityThread");Method methodcat = ActivityThread.getMethod("currentActivityThread");Object currentActivityThread = methodcat.invoke(ActivityThread);Method methodga = currentActivityThread.getClass().getMethod("getApplication");Context context =(Context)methodga.invoke(currentActivityThread);if (context == null) {Log.e(TAG, "context null");}else{Log.e(TAG, "get context ok,package name:" + context.getPackageName()+"/class name:" + context.getClass().getName());return context;}} catch (Exception e) {e.printStackTrace();}return null;}public void XposeWriteLogFile(byte [] bytestr) { String sdStatus = Environment.getExternalStorageState(); if(!sdStatus.equals(Environment.MEDIA_MOUNTED)) { return; } try { String pathName=LOG_FILE_PATH; String fileName=LOG_FILE_NAME; File path = new File(pathName); File file = new File(pathName + fileName); if( !path.exists()) { path.mkdir(); } if( !file.exists() ) { file.createNewFile(); } FileOutputStream stream = new FileOutputStream(file,true); if(bytestr.length > 0){stream.write(bytestr);}stream.write("\r\n".getBytes());stream.close(); } catch(Exception e) { e.printStackTrace(); } }public void XposeWriteLogFile(String str) { String sdStatus = Environment.getExternalStorageState(); if(!sdStatus.equals(Environment.MEDIA_MOUNTED)) { return; } try { String pathName=LOG_FILE_PATH; String fileName=LOG_FILE_NAME; File path = new File(pathName); File file = new File(pathName + fileName); if( !path.exists()) { path.mkdir(); } if( !file.exists() ) { file.createNewFile(); } FileOutputStream stream = new FileOutputStream(file,true); if(str.length() > 0){stream.write(str.getBytes());}stream.write("\r\n".getBytes());stream.close(); } catch(Exception e) { e.printStackTrace(); } }}
可以看到,该类继承自IXposedHookLoadPackage 类,在方法handleLoadPackage中,通过XposedHelpers.findAndHookMethod接口实现对android中任意其他包的方法的hook。该函数的原型如下:

其第一个参数是要hook的类名,第二个参数是lpparam.classLoader,第三个参数是方法名,第4个参数是hook的方法的参数,第5个参数是如下回调接口:
new XC_MethodHook() {@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {//do something after hook}@Overrideprotected void beforeHookedMethod(MethodHookParam param) throws Throwable {//do something before hook}}
其中的afterHookedMethod是被hook函数执行完后执行的,beforeHookedMethod在被hook函数执行前执行。函数体中实现具体的hook功能,当前例子里,是在hook函数前后分别在/storage/sdcard0/XposedLog/XposedLog.txt文件中输出一行记录,以及输出toast和log。
编写完后,同样右键工程,点击"run as"–>“Android Application”,将插件安装到模拟器中。然后打开xposed,点击"模块"菜单,在右边的选项框中选中该模块,将模拟器重启后,插件即可生效。
此时,点击test程序,在test启动和退出时,可以看到Toast输出、sd卡中的文件记录输出、log输出:



相关文章:
Android java层hook------xposed框架的使用
xposed曾经是android平台上最好的java层hook和调试工具,由于已经不再更新,当前支持的android系统版本比较老旧,目前只能支持到android6.0,故已经逐渐落伍,目前android上最广泛使用的hook工具是frida,这是另…...
css奇淫巧计
1.input文本内容替换 -webkit-text-security:通过用形状替换字符,仅影响那些字段不是的typepassword 可选值:none (无),circle (圆圈),disc (圆形),square &a…...
Web服务器实现|基于阻塞队列线程池的Http服务器|线程控制|Http协议
基于阻塞队列生产者消费者模型线程池的多线程Web服务器 代码地址:WebServer_GitHub_Addr README 摘要 本实验通过C语言,实现了一个基于阻塞队列线程池的多线程Web服务器。该服务器支持通过http协议发送报文,跨主机抓取服务器上特定资源。与…...
【C++】运算符重载(日期类的实现)
【C】运算符重载(日期类的实现) 前言运算符重载operator全局和类中 日期类的实现成员变量的确定构造函数拷贝构造 运算符重载部分的重载思路实现GETmonthdayoperator 的重载思路实现 -的与-的重载实现 各个比较运算符的重载实现 前置与后置实现 …...
【Linux】线程分离 | 线程库 | C++调用线程 | 线程局部存储
文章目录 1. 线程分离1. 为什么要线程分离?2. 具体使用3. 为什么有时候分离在调用join 会正常运行? 2. 如何理解线程库?如何理解 先描述 在组织? 3. C中使用多线程4. 线程局部存储局部变量全局变量 1. 线程分离 1. 为什么要线程分…...
c++ ffmpeg 浅谈YUV444、YUV422、YUV420(2)
本期将会给大家介绍YUV相关基础知识,同时也介绍威创网络分布式系统的卓越色彩处理技术。 1.什么是YUV色彩空间 2.YUV采样格式 3.YUV不同采样格式对图像画质的影响分析 一、什么是YUV色彩空间? YUV是视频、图片、相机等应用中常常使用的一类图像格式,是…...
Redis在Windows下安装配置教程
Redis是一个开源的高性能键值对存储数据库,常用于缓存、消息队列等场景。本文将介绍如何在Windows系统下安装配置Redis。 1. 下载地址 Redis官方网站提供了Windows版本的安装包下载地址,网址为:https://github.com/tporadowski/redis/relea…...
数据库服务器
数据库服务器,联系Web服务器与DBMS的中间件是负责处理所有的应用程序服务器,包括在web服务器和后台的应用程序或数据库之间的事务处理和数据访问。 基本信息 中文名 数据库服务器 外文名 database server 功能 数据库服务器建立在数据库系统基础上&a…...
VS输出路径和生成事件
在生成时,常常希望输出文件夹整洁,因此需要设置dll或exe输出位置,同时也希望对一些文件做一些特殊操作 VS的 UI 常用缩写 “./”:代表目前所在的目录。 " . ./"代表上一层目录。 “/”:代表根目录。 生成…...
从 WebKit 看浏览器内核架构
浏览器常见的浏览器内核有:Blink、WebKit、Gecko、Trident 等,目前 WebKit 内核占据了非常大的的市场,包括 Chrome、Safari、安卓浏览器等市面上的主流浏览器,都使用了 WebKit 内核。 从 WebKit 看浏览器内核架构 既然 WebKit 这么…...
使用原生的 JavaScript,不依赖于任何特定的库与 ROSBridge进行通信
使用原生的 JavaScript,不依赖于任何特定的库与 ROSBridge进行通信 创建与 ROS 的连接: var rosbridge_url "ws://localhost:9090"; var ws new WebSocket(rosbridge_url);ws.onopen function(event) {console.log(Connected to rosbri…...
MATLAB第十章_图像处理算法
目录 图像处理算法 图像处理基础 图像处理函数 默认显示方式 添加颜色条 显示多帧图像 显示动画 三维材质图像 图像的直方图 灰度变换 均衡直方图 图像处理应用 图像增强 图像重建 图像变换 图像压缩 图像分割 图像边缘检测 图像识别 图像处理算法 图像处理…...
RobotFramework接口测试方案
1. Robot FrameWork介绍 1.1 介绍 Robot Framework是用于验收测试和回归测试的通用测试自动化框架。它使用易于理解的表格数据语法,非常友好的实现了关键字驱动和数据驱动模式。它的测试功能可以通过使用Python或Java实现的测试库进行扩展,用户可以使用…...
chatgpt赋能python:Python中日期转换:从字符串到日期对象
Python中日期转换:从字符串到日期对象 作为一个经验丰富的Python工程师,日期转换在我的日常编码工作中经常遇到。Python提供了一些内置函数和模块,可以将字符串转换为日期对象或将日期对象格式化为特定的字符串。本篇文章将带您深入了解Pyth…...
k8s 1.27新特性in-place使用方法:避坑指南(官方文档有坑,已提issue)
背景 按照官方文档试用新版的in-place特性时,一字不差地执行了,但是却出现了执行失败的情况: 执行kubectl -n qos-example patch pod qos-demo-5 --patch {"spec":{"containers":[{"name":"qos-demo-ct…...
网络传输(传输介质、通信方式、交换方式)
目录 一、传输介质1.双绞线2.网线安装3.光纤4.无线信道 二、通信方式、交换方式1.通信方式2.同步方式3.交换方式 一、传输介质 1.双绞线 双绞线:将多根铜线按规则缠绕在一起,能够减少干扰;分为无屏蔽双绞线UTP和屏蔽双绞线STP,都…...
【Unity】Time.deltaTime有什么用?看完你就明白
大多数刚开始使用 Unity 的人(包括我),都会对Time.deltaTime感到迷惑。 看完本文,你就会明白Time.deltaTime的定义及作用。 1、deltaTime是什么? 根据定义,Time.deltaTime是每一帧之间的时间间隔(以秒为单位)。 这有助于我们使游戏与帧数无关,也就是说,无论 fps 是…...
vue实现用户动态权限登录
一、使用vueelementUI搭登录框架,主要就是1、2、3、4 配置: ①vue.config.js use strict const path require(path)function resolve(dir) {return path.join(__dirname, dir) }// All configuration item explanations can be find in https://cli.v…...
ONNX模型修改为自定义节点
参考一 首先,需要将ONNX模型中的节点修改为自定义节点。要实现这一点,您需要了解自定义节点的定义和如何在ONNX中使用它们。ONNX定义了一个自定义运算符的接口,您可以使用该接口定义自己的运算符,并将其编译为ONNX模型可以识别的…...
内存对齐原则
struct (1)结构体第一个数据成员放在offset为0的地方,后面每个成员相对于结构体首地址的偏移量(offset)都是成员大小(该变量类型所占字节)的整数倍,如有需要编译器会在成员之间加上填…...
从Office功能区的“局外人“到“掌控者“:Office RibbonX Editor深度指南
从Office功能区的"局外人"到"掌控者":Office RibbonX Editor深度指南 【免费下载链接】office-ribbonx-editor An overhauled fork of the original Custom UI Editor for Microsoft Office, built with WPF 项目地址: https://gitcode.com/g…...
基于ESP32与MQTT的家庭环境监测系统:从传感器选型到数据可视化实战
1. 项目概述与核心价值最近几年,我身边越来越多的朋友开始关注家里的空气质量、温湿度这些看不见摸不着,但又实实在在影响生活舒适度和健康的环境指标。从新装修的房子担心甲醛,到有老人小孩的家庭在意PM2.5和二氧化碳浓度,再到南…...
如何快速掌握Avidemux:新手完整入门指南与5个核心技巧
如何快速掌握Avidemux:新手完整入门指南与5个核心技巧 【免费下载链接】avidemux2 Avidemux2, simple video editor 项目地址: https://gitcode.com/gh_mirrors/avi/avidemux2 Avidemux是一款功能强大且完全开源的专业视频编辑工具,专为快速剪辑、…...
如何用Python脚本榨干百度网盘带宽:pan-baidu-download终极指南
如何用Python脚本榨干百度网盘带宽:pan-baidu-download终极指南 【免费下载链接】pan-baidu-download 百度网盘下载脚本 项目地址: https://gitcode.com/gh_mirrors/pa/pan-baidu-download 在数字时代,百度网盘已成为我们存储和分享大型文件的默认…...
【数据结构与算法】数据结构基础——栈和队列
目录栈和队列1. 栈1.1 栈的概念1.2 栈的实现方式分析1.3 栈的实现1.3.1 栈的初始化与销毁1.3.2 入栈与出栈1.3.3 栈的判空与有效元素个数1.3.4 栈顶元素1.4 栈的扩展1.4.1 两栈共享空间2. 队列2.1 队列的概念2.2 队列的实现方式分析2.3 队列的实现2.3.1 队列的初始化与销毁2.3.…...
DeepSeek重复代码识别失效了?5个被90%团队忽略的AST解析盲区及修复清单
更多请点击: https://codechina.net 第一章:DeepSeek代码重复检测失效的真相与影响 DeepSeek-R1 模型在代码理解任务中表现出色,但其内置的代码重复检测机制在特定场景下存在系统性失效。根本原因在于模型对语义等价但语法结构差异显著的代…...
万星easy-vibe:描述需求即发布 零基础无需学语法
开源Easy-Vibe是一套开源AI编程学习方案,把学习顺序从先学语法再做项目翻转为直接做项目。文章拆解了项目驱动、提示词编写、AI编辑器和多Agent协作的完整流程,解释了为什么想法比语法更重要。 github上datawhalechina/easy-vibe:它在GitHub…...
如何深度定制索尼相机:Sony-PMCA-RE逆向工程工具完整指南
如何深度定制索尼相机:Sony-PMCA-RE逆向工程工具完整指南 【免费下载链接】Sony-PMCA-RE Reverse Engineering Sony Digital Cameras 项目地址: https://gitcode.com/gh_mirrors/so/Sony-PMCA-RE 索尼相机逆向工程工具Sony-PMCA-RE是一款专业的开源工具&…...
AB包相关知识
Lua与AB包/Addressables以及YooAsset 摘自千问: Lua 是菜谱(逻辑):决定了菜怎么做,味道如何。因为你需要随时换菜谱(热更新),所以菜谱不能死板地印在墙上(编译进主包&a…...
热电效应自发电自行车灯:利用体温实现免充电照明的工程实践
1. 项目概述:从人体体温到自行车灯光你有没有想过,骑自行车时身体散发出的热量,除了让你出汗,还能干点什么?这个项目就是把我们骑车时产生的“废热”,变成照亮前路的灯光。听起来有点像科幻情节,…...
