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。

  1. 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插件的版本和描述信息。

  1. assets文件夹下新建文件xposed_init文件,其内容为xposed插件的主类名,比如当前为com.xposedtest.XposedTest。
  2. 导入XposedBridgeApi-54.jar包。该包是xposed插件开发必不可少的支持包。在eclipse中点击"project"按钮–>“properties”–>“Java build path” -->“Libraries”–>“Add External Jars”,然后在选择框内选中jar包。
  3. 在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") 
				@Override
				protected 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") @Override
				protected 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() {
				@Override
				protected void afterHookedMethod(MethodHookParam param) throws Throwable {
						//do something after hook
				}
				
				@Override
				protected 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输出:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/22530.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C语言函数大全-- _w 开头的函数(5)

C语言函数大全 本篇介绍C语言函数大全-- _w 开头的函数 1. _wspawnl 1.1 函数说明 函数声明函数功能int _wspawnl(int mode, const wchar_t* cmdname, const wchar_t* arglist, ...);启动一个新的进程并运行指定的可执行文件 参数&#xff1a; mode &#xff1a; 启动命令的…

用爬虫分析沪深300指数超长走势

我们知道&#xff0c;一个股市里面有非常多的股票&#xff0c;我们如何能够量化整个股市整体的行情呢&#xff0c;答案是通过一些综合性的指数。本文所选用的沪深300就是这类指数中的一个。我们先来看一下百度百科对于沪深300的解释。 由于股票价格起伏无常&#xff0c; 投资者…

蓝桥杯拿到一等奖,并分享经验

昨天和群里的小伙伴在群里聊&#xff0c;有的小伙伴竟然说蓝桥杯一等奖没有含量&#xff0c;我也是醉了&#xff01; 就像去年看了一个号主写的&#xff1a;研究生遍地都是! 放眼全国14亿人口&#xff0c;别说研究生了&#xff0c;本科生占比有多少? “蓝桥杯是我人生中得到…

数慧时空20年磨一剑:推出智能遥感云平台DIEY,自然资源多模态大模型“长城”,为地理信息产业提速

作者 | 伍杏玲 出品 | CSDN 据中国地理信息产业发展报告公布的数据&#xff0c;截至2020年末&#xff0c;行业从业单位13.8万家&#xff0c;从业人数336.6万&#xff0c;到2021年末&#xff0c;从业单位增加到16.4万家&#xff0c;从业人数增加到398万&#xff0c;产业规模越…

Go colly爬虫框架精简高效【杠杠的】入门到精通

1 前言 1.1 Go Colly 爬虫介绍 爬虫框架中&#xff0c;各中流行的编程语言都有自己热门框架&#xff0c;python中的selenium、Scrapy、PySpider等&#xff0c;Java中的Nutch、Crawler4j、WebMagic、WebCollector等。golang中colly使用Go语言编写的功能强大的爬虫框架&#xf…

pdf如何删除其中一页?不妨试试这些办法

PDF格式是一种非常常见的文档格式&#xff0c;它可以在各种系统和设备上使用&#xff0c;而且无论在哪里打开&#xff0c;都可以保持格式的一致性。有时候&#xff0c;我们需要删除PDF文档中的一页&#xff0c;无论是为了更改文档的结构&#xff0c;还是为了删除错误的信息。在…

拥抱生成式大模型 --- 提示工程篇

本文为系列的第二篇&#xff0c;主要是学习和总结chatgpt类模型的提示工程。感谢吴恩达老师的开源课程。 引言 随着大型语言模型&#xff08;LLM&#xff09;的发展&#xff0c;LLM 大致可以分为两种类型&#xff0c;即基础LLM和指令微调LLM。基础LLM是基于文本训练数据&…

Python机器学习入门 - - 贝叶斯算法学习笔记

文章目录 前言一、贝叶斯算法简介二、贝叶斯算法的数学原理1. 条件概率2. 全概率公式3. 贝叶斯公式4. 朴素贝叶斯分类器5. 高斯朴素贝叶斯分类器和伯努利朴素贝叶斯分类器 三、Python实现朴素贝叶斯分类总结 前言 贝叶斯公式是我们高中就耳熟能详的统计概率定理&#xff0c;贝…

亚马逊云科技出海日6月9日盛夏盛启

向全球价值链上游奋进 中国企业增强国际竞争力的关键&#xff0c;是努力朝全球价值链上游奋进&#xff0c;发力技术出海。中国的出海新机遇&#xff0c;背后曾是疫情在全球按下数字互联和数字化升级的快进键&#xff0c;跨境电商、在线社交、移动支付、数字服务等数字经济迎来…

如何让你的 Jmeter+Ant 测试报告更具吸引力?

目录 引言 一、安装apache-Ant 二、Jmeter准备 3、生成测试报告 4、JMeter动态参数处理逻辑是什么&#xff1f; 5、JMeter是怎么做API自动化测试的&#xff1f; 结语 引言 想象一下&#xff0c;你辛苦搭建了一个复杂的网站&#xff0c;投入了大量的时间和精力进行开发和…

005 - STM32学习笔记 - 启动代码

005 - STM32学习笔记 - 启动代码 常用汇编指令 指令名称作用EQU给数字常量取一个符号名&#xff0c;相当于C语言中的#define&#xff1b;AREA汇编一个新的代码段或者数据段&#xff1b;SPACE分配内存空间&#xff1b;PRESERVE8当前文件栈需要按照8字节对齐&#xff1b;EXPORT…

k8s pv pvc的介绍|动态存储|静态存储

k8s pv pvc的介绍|动态存储|静态存储 1 emptyDir存储卷2 hostPath存储卷3 nfs共享存储卷4 PVC 和 PVNFS使用PV和PVC 4 搭建 StorageClass NFS&#xff0c;实现 NFS 的动态 PV 创建 1 emptyDir存储卷 当Pod被分配给节点时&#xff0c;首先创建emptyDir卷&#xff0c;并且只要该…

详解c++STL—函数对象

目录 1、函数对象 1.1、函数对象概念 1.2、函数对象的使用 2、谓词 2.1、谓词概念 2.2、一元谓词 2.3、二元谓词 3、内建函数对象 3.1、理解内建函数对象 3.2、算术仿函数 3.3、关系仿函数 3.4、逻辑仿函数 1、函数对象 1.1、函数对象概念 概念&#xff1a; 重载…

编译原理个人作业--第六章——基于 编译原理 国防工业出版社 第三版

2 对表达式((a)(b)) (1) 按照表6.4属性文法构造抽象语法树 (2) 按6.17翻译模式构造表达式抽象语法树 5(1) 下列文法对整型常数、实型常熟世家加法运算符 生成表达式&#xff0c;当两个整型数相加&#xff0c;结果为整形&#xff0c;否则结果为实型 E → E T ∣ T E\r…

面试技术点

一、对热修复、插件化、模块化、组件化有一定研究。 1、模块化 将共享部分或业务模块抽取出来形成独立module。 2、组件化 基于模块化&#xff0c;核心思想是角色的转换&#xff0c;在打包时是library&#xff0c;分离独立的业务组件如微信朋友圈。 3、热修复和插件化种类、…

电力系统机组组合优化调度(IEEE14节点、IEEE30节点、IEEE118节点)(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️❤️&#x1f4a5;&#x1f4a5;&#x1f4a5; &#x1f4dd;目前更新&#xff1a;&#x1f31f;&#x1f31f;&#x1f31f;电力系统相关知识&#xff0c;期刊论文&…

Java并发编程-synchronized

目录 1. synchronized在jdk 1.6中的优化 1.1 锁消除 1.2 锁粗化 1.2 锁升级/锁膨胀 1.2.1 锁升级原理 1.2.2 自适应自旋锁 2. synchronized实现原理 3. synchronized和Lock的对比 1. synchronized在jdk 1.6中的优化 在JDK1.5的时候,Doug Lee推出了ReentrantLock,lock的…

chatgpt赋能Python-python_os拷贝文件

Python os拷贝文件 – 从简介到实现 Python os库是一个经常使用的工具&#xff0c;它是Python的标准库&#xff0c;提供了与操作系统进行交互的函数和方法。其中&#xff0c;os拷贝文件是其常用的功能之一&#xff0c;可以用来实现文件备份、文件复制等等操作。接下来&#xf…

windows sever服务器安装系统新手版

混在learnsite群里已经有几年了吧&#xff0c;但是只有一段时间用了别人现成的一个iso版本还比较老&#xff0c;这次打算自己弄一个&#xff0c;一开始打算linux下弄&#xff0c;结果系统都装完了发现人家说learnsite在linux下有点bug没解决好&#xff0c;只能win下再弄&#x…

Vue+uniapp桃源婚恋交友APP 安卓小程序 nodejs java python

小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 开发模式&#xff1a;混合开发本文先提出了开发基于小程序的桃源婚恋交友APP系统的背景意义&#xff0c;然后通过功能性和非功能性分析阐述本系统的需求&#xff0c;然后进行系统设计。技术实现部分选择Jav…