Xposed

Xposed 是一个针对 Android 系统的框架,允许开发者通过 Hook(钩取)系统或应用的函数来修改其行为,实现个性化功能,无需修改原始 APK 文件。

通过 Xposed,开发者可以轻松进行数据劫持、修改参数值和返回值、主动调用方法等操作。基于此框架,开发者能够创建出各种强大的模块,且这些模块可以在功能不冲突的前提下同时运行,极大提升了系统的可定制性。例如,可以实现消息防撤回、步数修改、去广告、界面美化等功能,满足不同用户的需求并增强用户体验。

Xposed实现原理

Xposed 框架通过替换 Android 系统原本的 app_process,使用自定义的 app_process 来启动 Zygote 进程,并加载一个额外的 XposedBridge.jar。该 JAR 包包含了 Xposed 框架的核心代码,框架会执行 XposedBridge.main() 方法。此方法的核心任务是利用 Xposed 提供的 Hook 能力,动态劫持原本将被调用的 ZygoteInit.main() 方法,从而劫持 Zygote 进程以及所有通过 Zygote 启动的应用进程。通过这种方式,Xposed 能够在不修改 APK 的情况下,通过注入代码动态修改 Dalvik/ART 虚拟机的行为,实现在系统和应用中的 Hook 和修改功能。

Xposed 框架的发展

特性 Xposed Installer EdXposed LSPosed
Android支持 4.0–8.1 8.0–11 8.1–14+
注入方式 替换app_process Riru动态注入 Zygisk集成
Hook模式 全局生效 全局生效 作用域隔离(白名单)
模块生效 需重启系统 需重启系统 仅重启应用
抗检测能力 中(依赖Riru隐藏) 高(Zygisk隐匿)

准备工作

  • 安卓开发环境(Android Studio)
  • 一台可以安装Xposed框架的手机(本文使用LSPosed)
  • jadx

编写第一个Xposed模块

项目创建

  1. 打开Android Studio,创建新项目

  2. 项目模板选择"No Activity"

  3. 设置名字,这里我们设置成"XPDemo"

  4. 本文我们使用Java语言开发

  5. 点击finish创建项目

引入依赖

修改 settings.gradle.kts 文件中的dependencyResolutionManagement节点

...
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven { url = uri("https://api.xposed.info/") } // 添加 Xposed 相关的 Maven 仓库,允许从指定地址下载相关依赖
}
}
...

修改 build.gradle.kts 文件中的dependencies节点

dependencies {
compileOnly("de.robv.android.xposed:api:82") // 仅编译时使用 Xposed API,不会打包进 APK 中
implementation(libs.appcompat)
implementation(libs.material)
testImplementation(libs.junit)
androidTestImplementation(libs.ext.junit)
androidTestImplementation(libs.espresso.core)
}

声明模块

修改AndroidManifest.xml中的application节点

    <application
...> <!-- 声明本应用是Xposed模块,,xposed根据这个判断是否是模块的 -->
<meta-data
android:name="xposedmodule"
android:value="true" />
<!-- 本模块的模块描述 -->
<meta-data
android:name="xposeddescription"
android:value="Xposed Module Demo" />
<!-- 最低xposed版本号 -->
<meta-data
android:name="xposedminversion"
android:value="52" />
<!-- 模块生效的作用域<可选> -->
<meta-data
android:name="xposedscope"
android:resource="@array/xpdemo_scope"/>
</application>

如果设置了xposedscope,就需要在src/main/res/values中创建arrays.xml文件,然后写入模块生效的应用,如下

<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="xpdemo_scope">
<item>qhmx.flat.game</item>
<item>com.example.demo1</item>
</string-array>
</resources>

创建Hook类

创建Hook类,这里我们叫HookMain,这个类的修饰符必须是public,并且需要实现IXposedHookLoadPackage接口重写handleLoadPackage方法。

package com.example.xpdemo;

import android.util.Log;

import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.callbacks.XC_LoadPackage; public class HookMain implements IXposedHookLoadPackage{
private static final String TAG = "HookMain";
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
Log.e(TAG, lpparam.packageName + "Starting");
}
}

创建xposed_init

在src/main中创建assets目录,在该目录中创建xposed_init文件,我们需要在这个文件里写上HOOK类全路径,方便Xposed模块能找到HOOK类。这个例子中就是com.example.xpdemo.HookMain.

至此框架搭建完毕。

加载Xposed 模块

把编译好的apk安装到手机上。

安装后,LSPosed就可以检测到我们的模块。

在上图中可以看到我们插件的名字和模块描述。

在上图中可以我设置模块作用的包名会有一个推荐应用的显示。

实战

我们只是为了练习Xposed 模块的编写,不讨论样本的难以程度。

我在网上下载了一个样本程序,它的功能是:需要输入一个密码,点击提交,然后他会判断密码是否是预期的密码,然后给出对应提示。

分析

使用jadx反编译MainActivity

通过反编译的结果得知,如果flag不为null,就达到我们的目的。所以继续追踪FlagGuard类的getFlag方法。

通过反编译getFlag方法的实现得知,如果str和Data类的getData方法返回相同,该函数的返回值就不为null。

我们可以通过Hook Data类的getData方法来得到正确的密码。

代码实现

目标:通过Hook getData方法使用Toast来显示出正确的密码。

提示:jadx可以通过右击方法名,复制为xposed片段,直接生成Hook代码。

package com.example.xpdemo;

import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.util.Log;
import android.widget.Toast; import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
import de.robv.android.xposed.XposedHelpers; public class HookMain implements IXposedHookLoadPackage{
private static final String TAG = "HookMain";
public static final String targetPackName = "com.XXX.crackme0x02";
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable { if(!lpparam.packageName.equals(targetPackName)) {
return;
} Log.e(TAG, lpparam.packageName + " Starting");
XposedHelpers.findAndHookMethod("com.XXX.crackme0x02.Data", lpparam.classLoader, "getData", android.content.Context.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
Context context = (Context)param.args[0];
String passWord = (String)param.getResult();
Toast.makeText(context, "Password is " + passWord, Toast.LENGTH_LONG).show();
copyTextToClipboard(passWord, context);
}
});
} private void copyTextToClipboard(String text, Context context) {
// 获取系统剪切板服务
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); // 创建 ClipData 对象,包含要复制的文本
ClipData clip = ClipData.newPlainText("label", text); // 将 ClipData 设置到剪切板
clipboard.setPrimaryClip(clip);
} }

效果

安全防范

Xposed 框架功能强大,它会对应用安全可能造成一定影响。为应对这一问题,推荐一款加固工具。Virbox Protector 通过深度加固机制应对 Xposed 框架的安全风险:其核心防护手段包括实时检测 Xposed 环境、阻断模块注入、强化反调试及内存完整性校验,有效拦截 Zygote 进程劫持与代码 Hook 行为;配合 DEX 加密、字符串混淆及防篡改技术,从根源上防止 Xposed 模块对应用逻辑的篡改与数据窃取,显著提升应用在 Root 环境下的抗逆向能力,保障开发者代码安全与用户隐私。

Xposed 模块开发指南的更多相关文章

  1. Xposed模块开发基本方法记录

    由于某些课程实验的要求,需要通过xposed框架对某应用进行hook操作,笔者选用了开源且免费的xposed框架进行实现.虽然网上存在一些利用xposed实现特定功能的文章资源,但大多均将xposed ...

  2. Xposed模块开发学习记录

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

  3. Xposed模块开发教程

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

  4. Apache模块开发指南-APR池

    转:原文: http://blog.csdn.net/zmxiangde_88/article/details/8038150 ------------------------------------ ...

  5. ECMALL模板解析机制.MVC架构分析及文件目录说明.二次开发指南手册(转)

    ECMALL模板解析语法与机制 http://www.nowamagic.net/architecture/archt_TemplateSyntaxAndAnalysis.php ECMALL模块开发 ...

  6. 基于Asterisk的VoIP开发指南——Asterisk 模块编写指南(1)

    原文:基于Asterisk的VoIP开发指南--Asterisk 模块编写指南(1) 1 开源项目概述 Asterisk是一个开源的软件包,通常运行在Linux操作系统平台上.Asterisk可以用三 ...

  7. 移动IM开发指南3:如何优化登录模块

    <移动IM开发指南>系列文章将会介绍一个IM APP的方方面面,包括技术选型.登陆优化等.此外,本文作者会结合他在网易云信多年iOS IM SDK开发的经验,深度分析实际开发中的各种常见问 ...

  8. 基于Neptune开发板的键盘蓝牙模块DIY指南

    目录: 1.下载开发板程序2.安装USB串口(CH340)驱动3.安装烧写工具4.烧写开发板程序 本期我们带来基于润和Neptune开发板(以下简称Neptune开发板)的键盘蓝牙模块DIY指南,利用 ...

  9. Jetty使用教程(四:21-22)—Jetty开发指南

    二十一.嵌入式开发 21.1 Jetty嵌入式开发HelloWorld 本章节将提供一些教程,通过Jetty API快速开发嵌入式代码 21.1.1 下载Jetty的jar包 Jetty目前已经把所有 ...

  10. JVM 平台上的各种语言的开发指南

    JVM 平台上的各种语言的开发指南 为什么我们需要如此多的JVM语言? 在2013年你可以有50中JVM语言的选择来用于你的下一个项目.尽管你可以说出一大打的名字,你会准备为你的下一个项目选择一种新的 ...

随机推荐

  1. ctf知识积累

    (1)url解码: python解码函数: from urllib.parse import unquote(quote:编码) url_code="" url_code1=unq ...

  2. IDEA 使用@Autowired提示Field injection is not recommended

    摘要:IDEA 使用@Autowired提示Field injection is not recommended问题的解决办法.   在使用@Autowired注解进行bean注入,完成自动装配的工作 ...

  3. 关于js中的toLocaleDateString()方法

    toLocaleDateString()方法是JavaScript Date对象的一个内建方法,它将日期转换为符合特定地区习惯的字符串格式. 基本用法: 如果没有传入任何参数,toLocaleDate ...

  4. Error creating bean with name 'xxx' defined in file异常处理

    SpringBoot整合mybatis 今天在使用mybatis generator时遇到一个坑,出现以下错误 Error creating bean with name 'authorizeCont ...

  5. DTMO直播预告|Taier1.1新功能详解&控制台介绍

    DTMO DTMO(DTstack Meetup Online)是袋鼠云数栈技术团队2022年的全新开源项目技术分享活动,我们秉承着开源共享的理念,旨在为大家分享大家分享袋鼠云大数据开源项目家族的最新 ...

  6. C# 对字符串进行UrlEncode/UrlDecode

    https://www.cnblogs.com/li150dan/p/13492280.html //对字符进行UrlEncode编码 string text= System.Web.HttpUtil ...

  7. 记录java使用openoffice将office转pdf遇到的问题

    openoffice使用方法:使用openOffice将office文件转成pdf 遇到了这个问题: 将 DocumentConverter converter = new OpenOfficeDoc ...

  8. 论文笔记:AlphaEdit: Null-Space Constrained Knowledge Editing for Language Models(AlphaEdit)

      论文发表于人工智能顶会ICLR(原文链接).基于定位和修改的模型编辑方法(针对ROME和MEMIT等)会破坏LLM中最初保存的知识,特别是在顺序编辑场景.为此,本文提出AlphaEdit:   1 ...

  9. 手把手教你在 Sevalla 上部署 Next.js 博客:从搭建到上线全流程

    很多开发者会纠结:"现在博客平台这么多,为啥还要自己搭博客?" 答案很简单:用 Next.js 搭的博客,是真正属于你的 "数字资产". 为什么选 Next.j ...

  10. CF1990D Grid Puzzle 题解

    CF1990D Grid Puzzle DP 好题.考虑分析两种操作的性质,不难发现操作 \(1\) 至多只能涂白 \(4\) 个方格,而操作 \(2\) 可以涂白的方格取决于这一行的方格数,几乎无上 ...