☰
MASTG-TEST-0325 实战:在 Android 运行时 Hook 检测机制,识别 App 的 Root Detection 逻辑
2026/10/9 5:26:11 网站建设 项目流程
  • 文档
  • 教程
  • 网络安全

【免费下载链接】mastg

The OWASP Mobile Application Security Testing Guide (MASTG) is a comprehensive manual for mobile app security testing and reverse engineering. It describes technical processes for verifying the OWASP Mobile Security Weakness Enumeration (MASWE) weaknesses, which are in alignment with the OWASP MASVS.

项目地址:https://gitcode.com/gh_mirrors/ow/mastg
点击查看免费下载

本篇基于 OWASP MASTG 仓库中的测试用例 MASTG-TEST-0325(Runtime Use of Root Detection Techniques,动态/Hook 类测试,关联 MASWE-0051),讲解如何在 Android 应用的运行时阶段通过 Hook 常见 root 检测 API、追踪系统调用的方式,确认 App 是否真正激活了 root 检测逻辑。读完本篇,你将掌握"静态定位 + 动态验证"的组合测试流程,能编写针对性的 Frida Hook 脚本与 strace 追踪命令,并准确解读测试结果与常见误报/漏报。

1. 测试目标与适用边界

MASTG-TEST-0325 的核心目标是:验证 App 是否在运行时实现了 root 检测——包括检查 rooted 设备上常见的文件/产物,以及调用已知的 root 检测 API 或第三方检测库。

该测试的元数据(Front Matter)明确了它在 MASVS 体系中的位置:

platform: android type: [dynamic, hooks] maswe: [MASWE-0051] best-practices: [MASTG-BEST-0029, MASTG-BEST-0030] knowledge: [MASTG-KNOW-0027]

三个关键定位需要先行说明:

  • 与静态测试互补,而非二选一。文档明确建议将其与 MASTG-TEST-0324(References to Root Detection Mechanisms,静态分析检测 root 检测引用)组合使用,两种顺序均可行:
    • 先静态后动态:用 MASTG-TEST-0324 得到潜在的 root 检测机制清单,再将动态测试聚焦到这些具体检查点,确认它们在运行时被触发;
    • 先动态后静态:先用运行时 Hook 找出实际生效的检测机制,再回到静态分析中深入调查其实现与覆盖范围。
  • 环境建议但非强制。推荐在已 root 的设备或模拟器上运行本测试,以确保 root 检测机制能被触发;但即便在未 root 的设备上,只要 App 执行了不依赖 root 权限的检查(例如检查 root 相关文件是否存在、系统属性等),本测试同样可以暴露出 root 检测逻辑。
  • 范围边界(Out of Scope)。本测试不评估root 检测机制的健壮性或有效性——这类评估很难仅靠自动化测试完成,可能需要手工逆向与定制插桩。文档将这一点单独标注为 Note,并指向 MASTG-BEST-0030(Implementing Root Detection)。MASTG-BEST-0030 本身也强调:root 检测只是"提高攻击成本"的环境风险信号,天然可被绕过(通过 Hook、Patch 或隐藏 root 产物),应配合完整性校验、反调试信号与服务端强制策略使用,且检测点应分散在敏感操作与会话建立处,避免单点集中式门控。

另外,文档给出一个可选的扩展方向:借助 MASTG-TECH-0144(Bypassing Root Detection)尝试绕过 App 的 root 检测并观察结果——若某些检查被成功绕过、或出现检测失败,反过来也能说明 root 检测机制的存在。

2. 背景知识:App 里常见的 Root 检测手段(Hook 时要盯住什么)

测试文档把具体技术细节委托给知识条目 MASTG-KNOW-0027(Root Detection)。要设计有效的 Hook,必须先理解这些检查在代码层面对应哪些 API 调用。按 MASTG-KNOW-0027 的分类,常见检测手段及其对应的运行时观测点如下:

2.1 文件存在性检查(File Existence Checks)

最广泛的程序化检测方式是检查 rooted 设备上典型存在的文件,包括常见 rooting 工具的包文件:

/system/app/Superuser.apk /system/etc/init.d/99SuperSUDaemon /dev/com.koushikdutta.superuser.daemon/ /system/xbin/daemonsu

以及在各处探测su二进制与 busybox:

/sbin/su /system/bin/su /system/bin/failsafe/su /system/xbin/su /system/xbin/busybox /system/sd/xbin/su /data/local/su /data/local/xbin/su /data/local/bin/su

典型 Java 实现是遍历PATH环境变量中的目录,逐个判断su是否存在:

public static boolean checkRoot(){ for(String pathDir : System.getenv("PATH").split(":")){ if(new File(pathDir, "su").exists()) { return true; } } return false; }

从运行时观测的角度看,这类检查最终都会落到java.io.File.exists()/access()等调用上——这正是 Hook 的主要切入点。在 Native 层,检测代码则通过stat系统调用实现。MASTG-KNOW-0027 给出了一个改编自 rootinspector 的 JNI 示例,用stat获取文件信息并在文件存在时返回 1:

jboolean Java_com_example_statfile(JNIEnv * env, jobject this, jstring filepath) { jboolean fileExists = 0; jboolean isCopy; const char * path = (*env)->GetStringUTFChars(env, filepath, &isCopy); struct stat fileattrib; if (stat(path, &fileattrib) < 0) { __android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NATIVE: stat error: [%s]", strerror(errno)); } else { __android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NATIVE: stat success, access perms: [%d]", fileattrib.st_mode); return 1; } return 0; }

Native 层的stat/access则对应系统调用stat/newfstatat/faccessat,可通过 strace 追踪(见 MASTG-TECH-0032 的执行追踪技术)。

2.2 执行特权命令

另一种判断su是否存在的方式是通过Runtime.getRuntime().exec尝试执行它——若su不在 PATH 上会抛出IOException。同一方法也可用于探测 busybox 等程序。运行时观测点:java.lang.ProcessBuilder.start()/Runtime.exec(),其底层会触发execve系统调用。

2.3 检查运行中的进程

Supersu 会运行一个名为daemonsu的认证守护进程,该进程的存在是另一类 root 特征。枚举进程可用ActivityManager.getRunningAppProcesses、manager.getRunningServices、ps命令或直接遍历/proc目录。示例(取自 MASTG-KNOW-0027):

public boolean checkRunningProcesses() { boolean returnValue = false; // Get currently running application processes List<RunningServiceInfo> list = manager.getRunningServices(300); if(list != null){ String tempName; for(int i=0;i<list.size();++i){ tempName = list.get(i).process; if(tempName.contains("supersu") || tempName.contains("superuser")){ returnValue = true; } } } return returnValue; }

运行时观测点:ActivityManager相关 API 的返回值。

2.4 检查已安装的 Root 管理包

用PackageManager探测已知 root 管理器包名,例如对特定包名调用getPackageInfo:

eu.chainfire.supersu com.noshufou.android.su com.koushikdutta.superuser com.topjohnwu.magisk

运行时观测点:PackageManager.getPackageInfo()。这里 MASTG-KNOW-0027 特别提示了一个 Android 11+ 的细节:包可见性限制(package visibility restrictions)会影响该检测手段——若目标包已安装但对应用不可见,getPackageInfo的表现与包未安装相同(抛出PackageManager.NameNotFoundException),从而产生漏报。开发者可通过 manifest 中的<queries>元素声明需要查询的包:

<queries> <package android:name="com.topjohnwu.magisk" /> </queries>

或使用QUERY_ALL_PACKAGES权限(受 Google Play 限制约束,未必适用于多数场景)。

2.5 其他检测维度

  • 可写分区与系统目录:系统/数据目录正常为只读挂载,rooted 设备上可能被挂载为读写。检测方式为查找带rw标志挂载的文件系统(读/proc/mounts),或在 data 目录尝试创建文件——对应openat/creat等系统调用。
  • 自定义构建检测:检查BUILD.TAGS是否含test-keys(通常表明自定义 Android 镜像)。MASTG-KNOW-0027 引用的 RootBeer 示例:
public boolean detectTestKeys() { String buildTags = android.os.Build.TAGS; return buildTags != null && buildTags.contains("test-keys"); }

缺少 Google OTA 证书也是自定义 ROM 的迹象。此外,检测也可借助第三方库(如 MASTG-TOOL-0146、MASTG-TOOL-0147,两者均未获 OWASP 背书),这些库以 Java + Native 混合实现多种检测以提高绕过难度。

2.6 从真实 Demo 印证:Native 层 root 检测长什么样

仓库中的演示 MASTG-DEMO-0133(Root Detection Logic in Native Layer with Insufficient Obfuscation)展示了一个把 root 检测下沉到 native 库的示例:Java/Kotlin 层加载librootcheck.so并调用findRootArtifactPath()检查常见su路径。该 Demo 用 Radare2 在.rodata中发现明文存储的/system/bin/su、/sbin/su、/system/xbin/su字符串,证明检测指标未经编码/加密。这正好印证了 MASTG-KNOW-0027 中 Nativestat检查的思路:当 Hook 不到 Java 层的File.exists()时,应下沉到 native 层的stat/access与 strace 系统调用层面寻找证据。

3. 测试步骤:安装、Hook、系统调用追踪与充分操作

MASTG-TEST-0325 的 Steps 部分共四步,逐条展开如下。

3.1 使用 MASTG-TECH-0005 安装 App

MASTG-TECH-0005(Installing Apps)给出了标准操作:

adb install ./myApp.apk

多设备场景下可用-d(已连接物理设备)、-e(模拟器/TCP 设备)或-s <serial>指定目标:

adb -d install ./myApp.apk # 物理设备 adb -e install ./myApp.apk # 模拟器 adb devices # 列出所有设备 adb -s 37081JEHN05882 install ./myApp.apk

注意安装的是与目标环境匹配的构建:若使用 root 设备/模拟器,需保证应用签名与调试环境兼容;对于重打包(签名不一致)的包,需先adb uninstall <package>再安装,否则会出现INSTALL_FAILED_UPDATE_INCOMPATIBLE。

3.2 使用 MASTG-TECH-0043 Hook 相关 API 调用

MASTG-TECH-0043(Method Hooking)介绍了两种主流手段:

  • Xposed 模块:通过XposedHelpers.findAndHookMethod覆写目标类方法。该技术在 MASTG-TECH-0043 中给出了完整示例——针对遍历/sbin/、/system/bin/等目录查找su的混淆方法com.example.a.b.c(),用 Xposed 模块将其返回值强制改为false并打印XposedBridge.log("Caught root check!")。
  • Frida 脚本:用Java.perform获取类包装器后覆写方法实现。

对本测试而言,Hook 的目标是**"捕获"而非"修改"**:不改变返回值,只记录哪些 root 检测 API 被调用。结合第 2 节的观测点清单,一个典型的"检测存在性"探针脚本会 Hook 如下方法并打印调用栈/参数:

'use strict'; Java.perform(function () { // 1) 文件存在性检查(第 2.1 节:File.exists / PATH 遍历 su) var File = Java.use('java.io.File'); File.exists.implementation = function () { var path = this.getAbsolutePath(); console.log('[+] File.exists(' + path + ')'); return this.exists(); }; // 2) 特权命令执行检查(第 2.2 节) var Runtime = Java.use('java.lang.Runtime'); Runtime.exec.overload('[Ljava.lang.String;').implementation = function (cmd) { console.log('[+] Runtime.exec(' + JSON.stringify(cmd) + ')'); return this.exec(cmd); }; // 3) 包名检查(第 2.4 节:Magisk / SuperSU 等) var PM = Java.use('android.app.Application').currentApplication().getPackageManager(); var PackageManager = Java.use('android.content.pm.PackageManager'); var nameFinder = PackageManager.NameNotFoundException.class; try { PM.getPackageInfo('com.topjohnwu.magisk', 0); console.log('[+] getPackageInfo(com.topjohnwu.magisk): 命中(已安装且可见)'); } catch (e) { console.log('[+] getPackageInfo(com.topjohnwu.magisk): ' + (e instanceof PackageManager.NameNotFoundException ? 'NameNotFoundException(未安装或不可见)' : e)); } // 完整做法应 Hook PackageManager.getPackageInfo 本身并记录所有被查询的包名 // 4) 进程枚举检查(第 2.3 节) var ActivityManager = Java.use('android.app.ActivityManager'); ActivityManager.getRunningAppProcesses.implementation = function () { console.log('[+] ActivityManager.getRunningAppProcesses() 被调用'); return this.getRunningAppProcesses(); }; });

上面的脚本是对文档"hook the relevant API calls"要求的具体化示例,目标类与方法名需依据 MASTG-TEST-0324 静态分析结果或目标 App 实际代码调整;核心原则是保持原始行为不变、仅做记录。

Frida 的加载方式在 MASTG-TECH-0043 与 MASTG-TECH-0144 中都有示范,如前台启动注入:

frida -U -f <package_name> -l root_check_probe.js --no-pause

MASTG-TECH-0144 还提供了一条快速路径:objection -n "<App名>" start后执行android root disable,它会 Hook 常见 root 检测 API 并返回安全值——若使用该命令前 App 出现退出/拒止行为,而执行后正常,也可作为 root 检测存在的旁证(但按测试要求,正式观测仍应以探针式 Hook 的记录输出为准)。

3.3 使用 MASTG-TECH-0032 追踪相关系统 API 调用

Java 层 Hook 不到时(检测逻辑在 Native 层,如第 2.6 节 Demo 所示),下沉到系统调用层。MASTG-TECH-0032(Execution Tracing)给出的 strace 用法与本测试高度契合——root 检测关注的是文件访问与进程探测类系统调用,可按需组合过滤:

strace -ff -s 2000 -p `pgrep -f '<package_name>' | head -1` -e trace=openat,access,fstat,newfstatat,readlinkat,execve,ptrace,prctl,mmap,mprotect

参数含义(引自 MASTG-TECH-0032):

  • -ff:跟随所有线程及 fork/clone 出的子进程,为每个线程/进程写独立输出流;
  • -s 2000:最多捕获字符串参数 2000 字节,这对观察完整路径(如/system/bin/failsafe/su)与 socket 数据很关键;
  • -p:指定目标进程 PID(示例中用pgrep -f按包名定位);
  • -e trace=:只追踪指定系统调用,降低噪音。

若只关心文件检查,可直接用-e trace=file(等价于open,openat,creat,link,unlink,...的组合):

strace -ff -s 2000 -p `pgrep -f '<package_name>' | head -1` -e trace=file

在输出中搜索第 2 节列出的路径(su、magisk、/proc/mounts、busybox等),即可确认 Native 层 root 检测正在工作。两点注意事项来自 MASTG-TECH-0032:其一,strace 依赖ptrace附加,一旦目标启用反调试就会失败;其二,要捕获生命周期早期的行为,应开启开发者选项中的"Wait for Debugger"让应用启动即挂起后再附加,或用轮询脚本尽快附加(该脚本是近似方案,并非真正的启动级追踪)。此外,若 Java 层追踪不足,jdb的trace go methods与 Android Studio Profiler 也可辅助恢复被混淆代码的执行结构;rooted 设备上还可考虑 ftrace 等内核级追踪。

3.4 充分操作 App 触发尽可能多的流程

原文档第 4 步要求:"Exercise the app extensively to trigger as many flows as possible and enter sensitive data wherever you can." 这是很多检测逻辑被漏检的原因——root 检测点常分布在登录、敏感操作(转账、导出)、后台服务等路径上,而非仅在主界面。结合 MASTG-BEST-0030 中"将检查放在敏感操作与会话建立附近"的最佳实践反推:测试时务必覆盖敏感功能入口,包括登录/登出、会话重建、推送唤醒、后台存活等,并留意检测是否只在特定进程(如:remoteviews、后台服务进程)中触发——strace 的-ff与 Frida 的进程枚举(spawn后enumerateProcesses)能帮助你发现这些额外进程中的检查。

4. 观测结果、评估标准与误报分析

4.1 Observation(期望观测)

按文档定义,输出应包含所有观察到的 root 检测检查实例,以及被 Hook 的方法/API。一次合格的观测结果通常长这样:

  • Frida 探针输出:[+] File.exists(/system/xbin/su)、[+] Runtime.exec(["su","-c",...])、[+] getPackageInfo(com.topjohnwu.magisk)等调用记录,连同调用时间线与所属线程;
  • strace 输出:openat(AT_FDCWD, "/sbin/su", O_RDONLY) = -1 ENOENT (No such file or directory)、newfstatat(..., "/system/bin/su", ...)等针对 root 指标路径的系统调用。

将两类输出与 MASTG-TEST-0324 的静态清单交叉比对,即可形成"代码中存在 → 运行时确实触发"的完整证据链;对动态发现而静态遗漏的机制(如混淆/动态加载代码),再回到静态分析中补查实现与覆盖范围。

4.2 Evaluation(评估标准)

文档的判定规则很明确:

  • 测试失败条件:未观察到任何 root 检测检查实例(即 App 未实施 root 检测)。
  • 结果解读边界:本测试的结果应被解读为"root 检测逻辑存在"的证据,而不是对其健壮性/有效性的评估。文档再次指向 MASTG-BEST-0030;该最佳实践同时提醒测试方注意检测的固有局限——可通过 Hook、Patch 或隐藏 root 产物被绕过(参见 MASTG-TECH-0144 中的重命名二进制、Zygisk/DenyList 隔离、LSPosed 进程过滤、APK 静态 Patch、内核级隐藏等绕过手段清单)。

4.3 Expected False Negatives(预期假阴性)

文档专门列出假阴性场景,这是理解本测试局限的关键:

  1. Hook/Trace 覆盖不足:App 使用的 root 检测手段未被本测试的 Hook 点或系统调用过滤集合覆盖(例如自定义的/proc解析逻辑、内存级检查、非典型系统调用路径);
  2. 检测逻辑刻意规避检测:通过混淆、动态代码加载(DexClassLoader加载运行时下载的检测 dex)、反插桩(反调试/反 Frida,如检测 frida-agent 端口、/proc/self/maps扫描、ptrace保护)等手段规避 Hook。

因此在无发现时,不能据此断言"App 没有 root 检测",可能需要进一步的手工逆向或定制插桩(例如按 MASTG-DEMO-0133 所示对 native 库做字符串/交叉引用分析,或对execve前的行为做内核级追踪)。

5. 小结:把 TEST-0325 放进完整的 MASVS-RESILIENCE 测试流

  • 知识底座:MASTG-KNOW-0027 给出了 root 检测的六大类技术手段(文件存在性、特权命令、进程枚举、包名探测、可写分区、自定义构建)与具体指标清单,是设计 Hook 点与 strace 过滤条件的直接依据;
  • 测试对偶:静态侧 MASTG-TEST-0324 负责"找出代码里有哪些检查",动态侧 MASTG-TEST-0325(本篇)负责"确认运行时是否真的执行",两者循环使用以逼近真实覆盖;
  • 执行手段:安装用 MASTG-TECH-0005,Java 层探针用 MASTG-TECH-0043,系统调用层用 MASTG-TECH-0032,可选绕过验证用 MASTG-TECH-0144;
  • 结论约束:无论正例还是反例,结论表述都应落在"检测到/未检测到 root 检测逻辑的运行时执行"这一层,避免外推为"该防御有效/无效";防御侧的加固与调优诉求请参考 MASTG-BEST-0029(Resilience 与 RASP 信号总述)与 MASTG-BEST-0030(分层防御、检查点分散、多种手段组合、按会话/版本轮换检查项等原则)。

掌握以上链路后,你可以对任意 Android 目标复现本测试:静态定位检测面 → 设计探针式 Hook 与 strace 过滤集 → 充分驱动 App 流程 → 以"存在性证据"口径输出结论,并对假阴性场景标注所需的进一步手工分析工作。

  • 文档
  • 教程
  • 网络安全

【免费下载链接】mastg

The OWASP Mobile Application Security Testing Guide (MASTG) is a comprehensive manual for mobile app security testing and reverse engineering. It describes technical processes for verifying the OWASP Mobile Security Weakness Enumeration (MASWE) weaknesses, which are in alignment with the OWASP MASVS.

项目地址:https://gitcode.com/gh_mirrors/ow/mastg
点击查看免费下载
上一篇:DeepSeek-Harness 的 dsh-code-review 技能维护机制:基于双评审人适配器的定期人工反馈采纳管线
下一篇:Podman 多阶段构建阶段标签 --stage-labels 完全指南:定位与管理中间镜像

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询