Xposed-Hook

配置 Xposed 模块的 AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="your.package.name"><applicationandroid:label="Your Xposed Module Name"android:icon="@mipmap/ic_launcher"><meta-dataandroid:name="xposedmodule"android:value="true" /><meta-dataandroid:name="xposeddescription"android:value="这是一个用于监控字符串操作的 Xposed 模块" /><meta-dataandroid:name="xposedminversion"android:value="53" /><meta-dataandroid:name="xposedscope"android:resource="@array/xposed_scope" /></application>
</manifest>

在app/src/main/assets创建一个xposed_init文件 。

xposed_init 文件是 Xposed 模块必需的一个配置文件,它用来指定模块的入口类。这个文件需要包含你的 Xposed 模块的主类的完整类名(包含包名):

your.package.name.MainHook

app/build.gradle配置一下:

dependencies {implementation 'androidx.appcompat:appcompat:1.6.1'implementation 'com.google.android.material:material:1.9.0'// Xposed Framework APIcompileOnly 'de.robv.android.xposed:api:82'compileOnly 'de.robv.android.xposed:api:82:sources'// 如果需要使用 LSPosed API(可选)// compileOnly 'org.lsposed.hiddenapibypass:hiddenapibypass:4.3'
}

LoadPackageParam (简称 lpparam) 是 Xposed 框架中的一个重要参数类,它包含了被加载的应用程序的相关信息。

LoadPackageParam 是 XC_LoadPackage 的一个内部类,以下是它的所有成员变量:

public static final class LoadPackageParam extends XCallback.Param {/** 应用的包名 */public String packageName;/** 进程的名称 */public String processName;/** 应用的 ClassLoader */public ClassLoader classLoader;/** 应用的 Application 对象 */public ApplicationInfo appInfo;/** 是否是第一次加载 */public boolean isFirstApplication;/** 系统服务的进程名(如果是系统服务) */public String[] initiatingPackages;/** 系统服务的进程名(如果是系统服务) */public String initiatingPackage;
}
   // 获取当前加载的应用包名String pkgName = lpparam.packageName;// 例如: "com.android.chrome"
   // 获取当前进程名String procName = lpparam.processName;// 可能是: "com.android.chrome"// 或者: "com.android.chrome:sandbox"

类加载器

  • 它负责找到并加载你需要的工具(类)

       // 相当于说"帮我找到这个工具"

       Class<?> targetClass = lpparam.classLoader.loadClass("com.example.Target");

       

       // 找到后就可以使用这个类了

       XposedHelpers.findAndHookMethod(targetClass, "方法名", ...);

   // 获取应用的类加载器ClassLoader loader = lpparam.classLoader;// 用于加载目标应用中的类Class<?> targetClass = loader.loadClass("com.example.Target");
   // 获取应用的信息ApplicationInfo info = lpparam.appInfo;// 可以获取很多应用相关信息String sourceDir = info.sourceDir;        // APK 路径String nativeLibDir = info.nativeLibraryDir;  // native库路径int targetSdkVersion = info.targetSdkVersion; // 目标SDK版本

XposedHelpers

查找和 Hook 方法

// 1. 基本的方法 Hook
XposedHelpers.findAndHookMethod("com.example.Class",  // 类名lpparam.classLoader,  // 类加载器"methodName",        // 方法名String.class,        // 参数类型1int.class,           // 参数类型2new XC_MethodHook() {@Overrideprotected void beforeHookedMethod(MethodHookParam param) {// 方法执行前的处理}@Overrideprotected void afterHookedMethod(MethodHookParam param) {// 方法执行后的处理}}
);// 2. Hook 构造方法
XposedHelpers.findAndHookConstructor(targetClass,         // 类String.class,        // 参数类型new XC_MethodHook() { ... }
);

获取/设置字段值

// 获取字段值
Object fieldValue = XposedHelpers.getObjectField(object, "fieldName");
int intValue = XposedHelpers.getIntField(object, "fieldName");
String stringValue = XposedHelpers.getStaticObjectField(class, "fieldName");// 设置字段值
XposedHelpers.setObjectField(object, "fieldName", newValue);
XposedHelpers.setIntField(object, "fieldName", 123);
XposedHelpers.setStaticObjectField(class, "fieldName", newValue);

调用方法

// 调用实例方法
Object result = XposedHelpers.callMethod(object, "methodName", arg1, arg2);// 调用静态方法
Object result = XposedHelpers.callStaticMethod(class, "methodName", arg1, arg2);

创建新实例

// 创建对象实例
Object newInstance = XposedHelpers.newInstance(class);
Object newInstance = XposedHelpers.newInstance(class, "构造参数1", "构造参数2");

查找类

// 查找类
Class<?> class = XposedHelpers.findClass("com.example.Class", lpparam.classLoader);

Hook Api


GravityBox

GravityBox 是一个非常著名的 Xposed 模块,它是一个系统级的调整工具箱。

  • 更改赋予 Android 终端硬件按钮的功能

  • 修改状态栏的外观和显示的选项

  • 改变可以在手机或平板电脑屏幕上显示的亮度(这个是积极的,尤其是最小的,以节省电池)

  • 直接应用程序分配给设备的触摸按钮

  • 管理终端 RAM 的使用,了解此应用程序的消耗

Xposed Hook


  • choose: 查找某个类的所有实例对象
  • enumerateClassLoaders: 查找所有的类加载器

Java.choose() 和 Java.enumerateClassLoaders() 是 Frida 中两个不同的 API,它们的用途不同:

// 用于查找指定类的所有实例
Java.choose("com.example.TargetClass", {onMatch: function(instance) {// 每找到一个实例就会调用一次console.log("找到实例:", instance);console.log("实例字段值:", instance.fieldName);},onComplete: function() {// 搜索完成时调用console.log("搜索完成");}
});

// 用于列举所有的类加载器
Java.enumerateClassLoaders({onMatch: function(loader) {// 每找到一个类加载器就会调用一次console.log("类加载器:", loader);// 可以尝试用这个加载器加载类try {loader.loadClass("com.example.TargetClass");console.log("这个加载器可以加载目标类");} catch(e) {console.log("这个加载器无法加载目标类");}},onComplete: function() {console.log("搜索完成");}
});

主要区别:

  • choose: 查找某个类的所有实例对象
  • enumerateClassLoaders: 查找所有的类加载器

简单说:

  • 想找对象用 choose
  • 想找类加载器用 enumerateClassLoaders
// 1. 最简单的使用方式
Java.perform(function() {// 获取默认的类加载器var targetClass = Java.use("com.example.TargetClass");
});// 2. 当默认加载器找不到类时,可以遍历所有"图书管理员"
Java.enumerateClassLoaders({onMatch: function(loader) {try {// 让每个"管理员"都尝试找这本"书"loader.loadClass("com.example.TargetClass");console.log("找到了!这个管理员可以找到这本书");} catch(e) {console.log("这个管理员找不到这本书");}}
});

让我用更简单的方式解释 IXposedHookLoadPackage:

想象你是一个保安,站在商场门口:

  • 每当有人(应用)要进商场时,你都会被通知
  • 你可以检查他们的身份(包名),决定要不要对他们做什么
// 你就是这个保安
public class MainHook implements IXposedHookLoadPackage {@Overridepublic void handleLoadPackage(LoadPackageParam lpparam) throws Throwable {// 1. 检查是不是你要找的人if (lpparam.packageName.equals("com.taobao.qianniu")) {// 是千牛应用XposedBridge.log("发现千牛启动了!");// 2. 对这个应用做一些事// 比如:监控它的某个方法XposedHelpers.findAndHookMethod("com.taobao.qianniu.MainActivity",  // 类名lpparam.classLoader,                // 类加载器"onCreate",                         // 方法名Bundle.class,                       // 参数类型new XC_MethodHook() {@Overrideprotected void beforeHookedMethod(MethodHookParam param) {XposedBridge.log("千牛正在启动...");}});}}
}

handleLoadPackage 是 IXposedHookLoadPackage 接口中唯一需要实现的方法。它的作用是:

public class MainHook implements IXposedHookLoadPackage {@Overridepublic void handleLoadPackage(LoadPackageParam lpparam) throws Throwable {// 这个方法会在每个应用启动时被调用// 1. 可以获取应用的包名String packageName = lpparam.packageName;// 2. 可以获取应用的类加载器ClassLoader classLoader = lpparam.classLoader;// 3. 实际使用示例if (packageName.equals("com.taobao.qianniu")) {// 找到目标应用后,就可以开始 Hook 了XposedBridge.log("找到千牛了!");// Hook 示例XposedHelpers.findAndHookMethod("目标类名",classLoader,"方法名",new XC_MethodHook() {@Overrideprotected void beforeHookedMethod(MethodHookParam param) {// 方法执行前的处理}});}}
}

// Xposed 模块中使用 XposedBridge.log

XposedBridge.log("发现目标应用:" + TARGET_PACKAGE);  // 这是 Java 代码

// Frida 脚本中使用 console.log

console.log("发现目标应用:" + TARGET_PACKAGE);  // 这是 JavaScript 代码

XC_MethodHook 是 Xposed 框架中用来 Hook 方法的核心类。它让你可以在方法执行前后添加自己的代码。

XposedHelpers 最常用的方法


// 1. Hook 相关
XposedHelpers.findAndHookMethod(    // Hook 实例方法className,      // 类名classLoader,    // 类加载器methodName,     // 方法名parameterTypes, // 参数类型callback        // 回调
);XposedHelpers.findAndHookConstructor(  // Hook 构造方法className,classLoader,parameterTypes,callback
);// 2. 查找类
Class<?> cls = XposedHelpers.findClass("com.example.TargetClass",classLoader
);// 3. 调用方法
// 调用实例方法
Object result = XposedHelpers.callMethod(object,        // 对象"methodName",  // 方法名params         // 参数
);// 调用静态方法
Object result = XposedHelpers.callStaticMethod(className,     // 类名"methodName",  // 方法名params         // 参数
);// 4. 获取/设置字段
// 获取实例字段
Object value = XposedHelpers.getObjectField(object,        // 对象"fieldName"    // 字段名
);// 获取静态字段
Object value = XposedHelpers.getStaticObjectField(className,     // 类名"fieldName"    // 字段名
);// 设置实例字段
XposedHelpers.setObjectField(object,        // 对象"fieldName",   // 字段名newValue       // 新值
);// 设置静态字段
XposedHelpers.setStaticObjectField(className,     // 类名"fieldName",   // 字段名newValue       // 新值
);// 5. 创建新实例
Object newObj = XposedHelpers.newInstance(className,     // 类名params         // 构造参数
);

setAccessible 是 Java 反射中用来绕过访问限制的方法。它可以让你访问私有成员:

// 1. 基本用法
Field field = targetClass.getDeclaredField("privateField");
field.setAccessible(true);  // 允许访问私有字段
Object value = field.get(object);  // 现在可以访问了// 2. 实际例子
try {// 获取私有方法Method method = targetClass.getDeclaredMethod("privateMethod");method.setAccessible(true);  // 设置可访问method.invoke(object);  // 调用私有方法// 获取私有字段Field field = targetClass.getDeclaredField("privateField");field.setAccessible(true);  // 设置可访问field.set(object, newValue);  // 修改私有字段值
} catch (Exception e) {XposedBridge.log("访问失败: " + e);
}

  • Java.use().$new(): 创建新的 Java 对象
  • Java.cast(): 转换对象类型
  • Java.choose(): 查找已存在的对象实例

$new() 里面的参数对应 Java 类的构造函数参数。让我用具体例子说明:

Java.perform(function() {// 1. 无参数构造函数var StringBuilder = Java.use("java.lang.StringBuilder");var sb1 = StringBuilder.$new();  // 等同于 new StringBuilder()// 2. 带参数构造函数var sb2 = StringBuilder.$new("Hello");  // 等同于 new StringBuilder("Hello")// 3. String 类例子var String = Java.use("java.lang.String");var str1 = String.$new();  // new String()var str2 = String.$new("Hello");  // new String("Hello")// 4. 自定义类例子var MyClass = Java.use("com.example.MyClass");// 如果 MyClass 构造函数需要两个参数:String 和 intvar myObj = MyClass.$new("参数1", 123);  // new MyClass("参数1", 123)
});

下面是Java.cast(): 转换对象类型:

  • View 就像是一个"容器"
  • 通过 cast 告诉系统:"这个容器其实是个按钮"
  • 转换后就可以用按钮特有的功能了
Java.perform(function() {// 1. 找到一个普通的 ViewJava.choose("com.example.MainActivity", {onMatch: function(activity) {// findViewById 返回的是 View 类型var view = activity.findViewById(123);  // 这时候只能用 View 的方法// 把 View 转成 Buttonvar button = Java.cast(view, Java.use("android.widget.Button"));// 现在可以用 Button 特有的方法了button.setText("点击我");     // 设置按钮文字button.setEnabled(true);    // 设置按钮可点击button.setOnClickListener(/* ... */);  // 设置点击事件}});
});
// TextView 转换
var textView = Java.cast(view, Java.use("android.widget.TextView"));
textView.setText("这是文本");// ImageView 转换
var imageView = Java.cast(view, Java.use("android.widget.ImageView"));
imageView.setImageResource(R.drawable.icon);// EditText 转换
var editText = Java.cast(view, Java.use("android.widget.EditText"));
editText.setHint("请输入...");

主要区别:

  • $new() 是 Frida (JavaScript) 的方法
  • newInstance 是 Xposed (Java) 的方法
  • 功能是一样的,都是创建新对象

简单说:

  • 在 Frida 脚本中用 $new()
  • 在 Xposed 模块中用 newInstance

Frida 的 $new()

Java.perform(function() {// Frida 方式创建对象var String = Java.use("java.lang.String");var str = String.$new("Hello");  // 创建字符串var ArrayList = Java.use("java.util.ArrayList");var list = ArrayList.$new();  // 创建列表
});

Xposed 的 newInstance

// Xposed 方式创建对象
String str = (String) XposedHelpers.newInstance(String.class,  // 类"Hello"       // 参数
);ArrayList list = (ArrayList) XposedHelpers.newInstance(ArrayList.class  // 类
);

简单说就是三步:

  • 找到类 (findClass)
  • 创建实例 (newInstance)
  • 调用方法 (callMethod)
public void handleLoadPackage(LoadPackageParam lpparam) throws Throwable {// 1. 首先查找类Class<?> targetClass = XposedHelpers.findClass("com.example.TargetClass",  // 类名lpparam.classLoader         // 类加载器);// 2. 创建类的实例Object instance = XposedHelpers.newInstance(targetClass);// 如果构造函数有参数// Object instance = XposedHelpers.newInstance(targetClass, "参数1", 123);// 3. 调用实例的方法XposedHelpers.callMethod(instance,       // 实例对象"methodName",   // 方法名"参数1",        // 方法参数123            // 更多参数);
}

NanoHTTPD


NanoHTTPD 是一个轻量级的 HTTP 服务器库。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Transformer+vit原理分析

目录 一、Transformer的核心思想 1. 自注意力机制&#xff08;Self-Attention&#xff09; 2. 多头注意力&#xff08;Multi-Head Attention&#xff09; 二、Transformer的架构 1. 整体结构 2. 编码器层&#xff08;Encoder Layer&#xff09; 3. 解码器层&#xff08;Decoder…

WPS mathtype间距太大、显示不全、公式一键改格式/大小

1、间距太大 用mathtype后行距变大的原因 mathtype行距变大到底怎么解决-MathType中文网 段落设置固定值 2、显示不全 设置格式&#xff1a; 打开MathType编辑器点击菜单栏中的"格式(Format)"选择"间距(Spacing)"在弹出的对话框中调整"分数间距(F…

C# 添加、替换、提取、或删除Excel中的图片

在Excel中插入与数据相关的图片&#xff0c;能将关键数据或信息以更直观的方式呈现出来&#xff0c;使文档更加美观。此外&#xff0c;对于已有图片&#xff0c;你有事可能需要更新图片以确保信息的准确性&#xff0c;或者将Excel 中的图片单独保存&#xff0c;用于资料归档、备…

Python练习(2)

今日题单 吃鱼还是吃肉 PTA | 程序设计类实验辅助教学平台 降价提醒机器人PTA | 程序设计类实验辅助教学平台 幸运彩票 PTA | 程序设计类实验辅助教学平台 猜帽子游戏 PTA | 程序设计类实验辅助教学平台 谁管谁叫爹 PTA | 程序设计类实验辅助教学平台 就不告诉你 PTA | 程…

Formality:黑盒(black box)

相关阅读 Formalityhttps://blog.csdn.net/weixin_45791458/category_12841971.html?spm1001.2014.3001.5482 简介 在使用Formality时&#xff0c;黑盒(black box)的概念很重要&#xff0c;指的是一个其功能未知的设计。黑盒通常用于设计中不可综合的组件&#xff0c;包括RAM…

开源2+1链动模式AI智能名片S2B2C商城小程序:利用用户争强好胜心理促进分享行为的策略研究

摘要&#xff1a;随着互联网技术的快速发展和社交媒体的普及&#xff0c;用户分享行为在企业营销中的作用日益凸显。本文旨在探讨如何利用用户的争强好胜心理&#xff0c;通过开源21链动模式AI智能名片S2B2C商城小程序&#xff08;以下简称“小程序”&#xff09;促进用户分享行…

八股学习 微服务篇

微服务篇 常见面试内容Spring Cloud 常见组件注册中心Ribbon负载均衡策略服务雪崩 常见面试内容 Spring Cloud 常见组件 Spring Cloud有5个常见组件&#xff1a; Eureka/Nacos:注册中心&#xff1b;Ribbon:负载均衡&#xff1b;Feign:远程调用&#xff1b;Hystrix/Sentinel:服…

Synology 群辉NAS安装(6)安装mssql

Synology 群辉NAS安装&#xff08;6&#xff09;安装mssql 写在前面mssql 2019:成功安装说明&#xff0c;这个最终成功了 mssql 2022没有成功1. pull image2.启动mssql docker container 远程连接 写在前面 mssq是一个重要节点。 这是因为我对mysql没有一丝好感。虽然接触了许…

mysql_init和mysql_real_connect的形象化认识

解析总结 1. mysql_init 的作用 mysql_init 用于初始化一个 MYSQL 结构体&#xff0c;为后续数据库连接和操作做准备。该结构体存储连接配置及状态信息&#xff0c;是 MySQL C API 的核心句柄。 示例&#xff1a; MYSQL *conn mysql_init(NULL); // 初始化连接句柄2. mysql_…

qt-QtQuick笔记之常见项目类简要介绍

qt-QtQuick笔记之常见项目类简要介绍 code review! 文章目录 qt-QtQuick笔记之常见项目类简要介绍1.QQuickItem2.QQuickRectangle3.QQuickImage4.QQuickText5.QQuickBorderImage6.QQuickTextInput7.QQuickButton8.QQuickSwitch9.QQuickListView10.QQuickGridView11.QQuickPopu…

0 基础学运维:解锁 K8s 云计算运维工程师成长密码

前言&#xff1a;作为一个过来人&#xff0c;我曾站在技术的门槛之外&#xff0c;连电脑运行内存和内存空间都傻傻分不清&#xff0c;完完全全的零基础。但如今&#xff0c;我已成长为一名资深的k8s云计算运维工程师。回顾这段历程&#xff0c;我深知踏上这条技术之路的艰辛与不…

Spring Boot - 数据库集成06 - 集成ElasticSearch

Spring boot 集成 ElasticSearch 文章目录 Spring boot 集成 ElasticSearch一&#xff1a;前置工作1&#xff1a;项目搭建和依赖导入2&#xff1a;客户端连接相关构建3&#xff1a;实体类相关注解配置说明 二&#xff1a;客户端client相关操作说明1&#xff1a;检索流程1.1&…

联想拯救者R720笔记本外接显示屏方法,显示屏是2K屏27英寸

晚上23点10分前下单&#xff0c;第二天上午显示屏送到&#xff0c;检查外包装没拆封过。这个屏幕左下方有几个按键&#xff0c;按一按就开屏幕、按一按就关闭屏幕&#xff0c;按一按方便节省时间&#xff0c;也支持阅读等模式。 显示屏是 &#xff1a;AOC 27英寸 2K高清 100Hz…

什么是线性化PDF?

线性化PDF是一种特殊的PDF文件组织方式。 总体而言&#xff0c;PDF是一种极为优雅且设计精良的格式。PDF由大量PDF对象构成&#xff0c;这些对象用于创建页面。相关信息存储在一棵二叉树中&#xff0c;该二叉树同时记录文件中每个对象的位置。因此&#xff0c;打开文件时只需加…

你的连接不是专用连接

当你打开网站看到如下提示&#xff0c;说明SSL证书到期了。 攻击者可能试图www窃取你的信息&#xff08;例如、密码、消息或信用卡&#xff09;。详细了解此警告 NET::ERR_CERT_DATE_INVALID 此服务器无法证明它是WWW ;它的安全证书已于2天前到期。这可能是错误配置或攻击者…

51单片机开发:定时器中断

目标&#xff1a;利用定时器中断&#xff0c;每隔1s开启/熄灭LED1灯。 外部中断结构图如下图所示&#xff0c;要使用定时器中断T0&#xff0c;须开启TE0、ET0。&#xff1a; 系统中断号如下图所示&#xff1a;定时器0的中断号为1。 定时器0的工作方式1原理图如下图所示&#x…

【电工基础】1.电能来源,触电伤害,触电预防,触电急救

一。电能来源 1.电能来源 发电-》输电-》变电-》配电 2.分配电 一类负荷 如果供电中断会造成生命危险&#xff0c;造成国民经济的重大损失&#xff0c;损坏生产的重要设备以致使生产长期不能恢复或产生大量废品&#xff0c;破坏复杂的工艺过程&#xff0c;以及破坏大…

简易计算器(c++ 实现)

前言 本文将用 c 实现一个终端计算器&#xff1a; 能进行加减乘除、取余乘方运算读取命令行输入&#xff0c;输出计算结果当输入表达式存在语法错误时&#xff0c;报告错误&#xff0c;但程序应能继续运行当输出 ‘q’ 时&#xff0c;退出计算器 【简单演示】 【源码位置】…

python-leetcode-从前序与中序遍历序列构造二叉树

105. 从前序与中序遍历序列构造二叉树 - 力扣&#xff08;LeetCode&#xff09; # Definition for a binary tree node. # class TreeNode: # def __init__(self, val0, leftNone, rightNone): # self.val val # self.left left # self.right r…

NLP深度学习 DAY4:Word2Vec详解:两种模式(CBOW与Skip-gram)

用稀疏向量表示文本&#xff0c;即所谓的词袋模型在 NLP 有着悠久的历史。正如上文中介绍的&#xff0c;早在 2001年就开始使用密集向量表示词或词嵌入。Mikolov等人在2013年提出的创新技术是通过去除隐藏层&#xff0c;逼近目标&#xff0c;进而使这些单词嵌入的训练更加高效。…