type
Post
status
Published
date
May 3, 2026
slug
summary
tags
LSPosed
安全
安卓
category
技术分享
icon
password
引言
提前声明:这些检测都没什么鸟用(((
方法一:检测 Linker SO 列表
原理说明
通过扫描进程中加载的动态链接库(SO)列表,检测是否存在与 LSPosed、Magisk、Zygisk 等 Hook 框架相关的特征字符串。这是最基础但也最实用的检测方法之一。
实现代码
技术要点
- SO List(共享对象列表):操作系统维护的已加载动态链接库列表
- 多路径扫描:结合
dl_iterate、linker 内部结构和/proc/self/maps三种方式,提高检测准确率
- 字符串归一化:移除下划线和连字符,转换为小写,避免简单的混淆绕过
方法二:检测 dex2oat 编译参数特征
原理说明
LSPosed 通过
mount --bind 方式拦截了 dex2oat 的调用,并添加了 --inline-max-code-units=0 参数以确保正常 Hook。该参数会在编译后的 base.odex 文件中留下痕迹。检测步骤
- 定位应用的 odex 文件:
- 提取编译参数:
- 检查是否包含
-inline-max-code-units=0参数
技术说明
- dex2oat:Android 运行时的 AOT(Ahead-Of-Time)编译器
- inline-max-code-units:控制方法内联的参数,设置为 0 表示禁用内联优化
- 此特征在 LSPosed 启用时会持久化到 odex 文件中
方法三:检查 ArtMethod 结构异常
背景知识
ArtMethod 是 Android Runtime(ART)中表示 Java 方法的 C++ 结构体。LSPosed 通过修改 ArtMethod 的入口点(Entry Point)来实现 Hook。
实现步骤
1. 定位 ArtMethod 字段偏移
2. Native 层获取入口点偏移
具体源代码可以看这里:https://github.com/bytedance/btrace/blob/f259e584ba455f44531877c0936b89b62773a344/btrace-android/rhea-library/rhea-inhouse/src/main/cpp/utils/JNIHook.cpp#L155
3. 检测匿名 RWX 内存区域
关键检测点
LSPosed 启用后会自动 Hook 以下方法:
java.lang.Thread.dispatchUncaughtException
android.app.ActivityThread.attach
dalvik.system.DexFile.openInMemoryDexFile
dalvik.system.DexFile.openInMemoryDexFiles
dalvik.system.DexFile.openDexFile
检测策略:获取这些方法的 Method 对象,传递给 Native 层检查入口点是否指向匿名 RWX 内存区域。
技术原理
- 早期 Xposed:将 Java 方法改为 Native 方法,通过 JNI 入口点实现 Hook
- LSPosed:创建匿名的可读可写可执行(RWX)内存区域,修改入口点指向该区域
- 检测依据:正常的方法入口点应指向有名称的代码段,而非匿名 RWX 区域
方法四:内存漫游检测 ClassLoader
原理说明
通过 JVMTI 或反射技术遍历堆内存中的所有 ClassLoader 实例,检查是否存在与 LSPosed 相关的 ClassLoader。
实现代码
实现方式
- Native 方式:基于 JVMTI 的 API
- Java 方式:利用反射和 Debug API 遍历对象
参考资源
详细实现可参考 @珍惜 的相关文章或看雪论坛的 ChooseUtils 实现。
方法五:基于时序的侧信道攻击
原理说明
LSPosed 拦截了 ActivityManagerService,对特定的 Transaction Code 会执行额外的检查和处理逻辑。通过测量 Binder 调用的耗时差异,可以推断是否存在 LSPosed。
Transaction Code 定义
检测实现
LSPosed-IT 的变种 Code
LSPosed-IT 版本使用基于 GitHub 用户名生成的动态 Code,以下是已知泄露的部分 Code:
局限性
Android 15+ 限制:当多次触发 Binder 错误时,Binder 连接会被系统冻结,导致此检测方法失效。此外,LSPosed-IT 的 Code 并非固定值,需要持续收集和更新。
方法六:/data/misc 目录异常检测
原理说明
LSPosed 和其他一些Xposed模块在运行时可能会在
/data/misc 目录下创建额外的子目录用于存储配置、日志等数据。由于普通应用无法直接 ls 列出该目录内容,我们可以通过以下策略检测异常:- 使用
stat系统调用获取/data/misc的子目录总数(通过st_nlink字段)
- 遍历所有已知的系统合法子目录,使用
access检查其是否存在
- 如果实际子目录数量多于已知目录数量,说明存在未知目录
st_nlink 字段:在 Unix/Linux 文件系统中,目录的硬链接数等于
子目录数量 + 2(. 和 .. 各占一个链接)。因此实际子目录数 = st_nlink - 2。权限限制:由于 SELinux 策略限制,普通应用无法使用
opendir/readdir 遍历 /data/misc,但可以:- 使用
stat获取目录元数据
- 使用
access检查特定路径是否存在
实现代码
• 由于不同厂商和 Android 版本可能有额外的系统目录,建议根据不同厂商定制不同的列表,减少遍历耗时 • 不同的android版本也有差异,我们可以收集一下不同安卓版本的差异去做一个针对安卓版本的表,减少遍历耗时
参考资料
- LSPosed 开源项目代码分析
- Android Runtime (ART) 官方文档
免责声明:本文内容仅供安全研究和技术交流使用,请勿用于非法目的。开发者应遵守相关法律法规和平台规则。
