news 2026/10/7 9:57:12

使用 radare2 静态分析 iOS 越狱检测实现:OWASP MASTG-DEMO-0021 实战解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
使用 radare2 静态分析 iOS 越狱检测实现:OWASP MASTG-DEMO-0021 实战解析
  • 文档
  • 教程
  • 网络安全

【免费下载链接】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-DEMO-0021 演示样例为主线,完整拆解一套"从 Swift 源码到 Mach-O 二进制"的 iOS 越狱检测实现,并演示如何使用 radare2 以-i参数批处理脚本方式对应用二进制进行静态取证分析。读完本文,你将掌握越狱检测四类常见检测手法(文件路径、URL Scheme、环境变量、沙盒外写权限)的实现细节,并能独立复现用 radare2 搜索敏感字符串、定位交叉引用、反汇编关键函数的完整流程。

演示样例概览:MASTG-DEMO-0021

MASTG-DEMO-0021 位于仓库的 demos/ios/MASVS-RESILIENCE 目录,属于 MASVS-RESILIENCE(抗逆向工程)类别,对应的测试用例为 MASTG-TEST-0240:Jailbreak Detection in Code。该样例对应 MASVS v2 的MASVS-RESILIENCE-1(设备锁定与完整性校验)与弱点枚举MASWE-0051(越狱检测缺失或可绕过)。

整个演示目录包含五个文件,构成了一个可完整复现的"检测实现 + 逆向取证"闭环:

文件作用
MastgTest.swift越狱检测的 Swift 源码实现(编译进MASTestApp二进制)
MASTestApp已编译的 iOS 应用主二进制(Mach-O 格式)
jailbreak_detection.r2radare2 批处理脚本,定义全部搜索与反汇编指令
run.sh一键执行脚本,驱动 radare2 并把输出重定向到output.asm
output.asm逆向分析的最终输出,即本文 Observation 部分的原始依据

越狱检测源码实现拆解

MASTgTest.swift(源码中文件名为MastgTest.swift)定义了三个类:MastgTest(测试入口)、JailbreakDetector(检测器本体)和DeviceUtils(设备环境工具)。

测试入口与运行环境判断

MastgTest.mastgTest(completion:)是检测的入口,它调用JailbreakDetector.isDeviceJailbroken()并把结果字符串通过 completion 回调返回:

class MastgTest { static func mastgTest(completion: @escaping (String) -> Void) { let jailbreakDetails = JailbreakDetector.isDeviceJailbroken() completion(jailbreakDetails) } }

isDeviceJailbroken()首先通过DeviceUtils.isSimulator()判断是否运行在模拟器上——实现方式是检查进程环境变量SIMULATOR_DEVICE_NAME是否存在:

class DeviceUtils { static func isSimulator() -> Bool { return ProcessInfo.processInfo.environment["SIMULATOR_DEVICE_NAME"] != nil } }

若在模拟器上运行,则返回"Warning: Running on a simulator (\(simulatorName)).\n\nProof:\n\n" + collectJailbreakProof(),其中模拟器名称取自SIMULATOR_DEVICE_NAME环境变量,缺失时回退为"Unknown Simulator"。在真机上则收集证据:证据列表为空返回"Jailbreak: False\n\nNo signs of a jailbreak detected.",非空则返回"Jailbreak: True\n\nProof:\n\n"拼接所有证据。

四类检测手法

collectJailbreakProof()依次执行四类检测,把命中的证据逐条追加到reasons数组,最后用换行符拼接返回。这与知识库 MASTG-KNOW-0084:Jailbreak Detection 归纳的典型手法(基于文件、基于文件权限、基于协议处理器)一一对应,并额外增加了环境变量检查。

检测 1:常见越狱文件与目录(file-based checks)

通过FileManager.default.fileExists(atPath:)检查 19 个路径,涵盖主流越狱商店、Substrate 注入框架、SSH 组件与 APT 痕迹:

let jailbreakPaths = [ "/Applications/Cydia.app", "/Applications/Sileo.app", "/Applications/Zebra.app", "/Applications/Installer.app", "/Library/MobileSubstrate/MobileSubstrate.dylib", "/usr/libexec/cydia", "/usr/libexec/ssh-keysign", "/usr/sbin/sshd", "/usr/bin/ssh", "/var/cache/apt", "/var/lib/apt", "/var/lib/cydia", "/var/log/syslog", "/bin/bash", "/bin/sh", "/etc/apt", "/private/var/lib/undecimus", "/private/var/root/Library/PreferenceLoader/Preferences", "/private/etc/apt" ]

检测 2:自定义 URL Scheme(protocol handler checks)

通过UIApplication.shared.canOpenURL(_:)探测越狱生态常用协议是否可被打开:

let urlSchemes = [ "cydia://", "sileo://", "zebra://", "filza://" ]

其中cydia://正是知识库中提到的、安装 Cydia 后默认可用的协议处理器(对应工具 MASTG-TOOL-0047 生态)。

检测 3:可疑环境变量(suspicious environment variables)

检查DYLD_INSERT_LIBRARIES、DYLD_FRAMEWORK_PATH、DYLD_LIBRARY_PATH是否被注入。这类变量常被 Frida、Substrate 等动态注入框架用来强制加载 dylib,是进程级注入的重要指纹。

检测 4:沙盒外写入权限(file permission / sandbox escape check)

尝试向应用沙盒之外的两个受限目录写入文件,写成功后立即删除。若能写入,说明文件系统权限未被沙盒约束,是设备已越狱的强信号(对应知识库中的写权限检测模式):

let paths = [ "/private/jailbreak.txt", "/private/var/mobile/Library/jailbreak.txt" ] for path in paths { do { try "test".write(toFile: path, atomically: true, encoding: .utf8) try FileManager.default.removeItem(atPath: path) reasons.append("Write access detected at \(path)") } catch { continue } }

从 IPA 到主二进制:静态分析前的准备

演示文档的第一步是解包应用并定位主二进制,这对应技术文档 MASTG-TECH-0058:Exploring the App Package 的标准流程:

  1. 使用unzip或任意 ZIP 工具解包 IPA;
  2. 进入Payload目录,找到 Application Bundle(.app);
  3. 主二进制通常与 bundle 同名且不带.app后缀——本样例中即./Payload/MASTestApp.app/MASTestApp。
unzip MASTestApp.ipa ls -1 Payload/MASTestApp.app/

与 Android 可将 DEX 反编译为 Java 不同,iOS 的 Mach-O 二进制只能反汇编而非"还原源码"(MASTG-TECH-0058 对此有明确说明),这正是静态分析环节必须借助 radare2 这类逆向框架的原因。Info.plist、_CodeSignature/、Frameworks/等目录是此阶段值得顺带核查的资产(权限声明、签名、原生库)。

用 radare2 批处理脚本完成自动化取证

演示文档第二步要求用 MASTG-TOOL-0073:radare2(iOS) 打开二进制并执行脚本。radare2 是完整的二进制逆向分析框架,支持 Mach-O 等格式加载与反汇编(其配套的 rabin2 子工具可单独提取符号、导入导出、字符串等元数据)。

run.sh 给出了完整命令:

#!/bin/bash r2 -q -i jailbreak_detection.r2 -A MASTestApp > output.asm

各参数含义:

  • -q:quiet 模式,不进入交互式 REPL,脚本执行完即退出(适合批处理与脚本化取证);
  • -i jailbreak_detection.r2:加载并顺序执行脚本文件中的 radare2 命令;
  • -A:在打开文件后自动执行aaa(全量分析),为后续pdf反汇编和axt交叉引用提供符号/函数信息;
  • > output.asm:把全部输出重定向到 output.asm,便于留存取证记录。

脚本指令逐行解读

jailbreak_detection.r2 的头部先做输出环境配置:

e asm.bytes=false ; 反汇编时不显示原始机器码字节,输出更紧凑 e scr.color=false ; 关闭 ANSI 颜色,保证重定向到文件的文本干净 e asm.var=false ; 不显示栈变量名注释,聚焦指令本身

随后用?e(echo)输出分隔标题,用/(搜索字符串命令)在二进制中逐条搜索越狱路径、URL Scheme 和环境变量:

/ /Applications/Cydia.app / /Applications/Sileo.app / /Applications/Zebra.app / /usr/sbin/sshd / /usr/bin/ssh / /var/cache/apt / /var/lib/apt / /var/lib/cydia / /var/log/syslog / /bin/bash / /bin/sh / /etc/apt / /private/jailbreak.txt / /private/var/mobile/Library/jailbreak.txt
/ cydia:// / sileo:// / zebra:// / filza://
/ DYLD_INSERT_LIBRARIES / DYLD_FRAMEWORK_PATH / DYLD_LIBRARY_PATH

脚本末尾的三个命令则完成"字符串确认 → 交叉引用 → 反汇编"的取证收尾:

iz~+jail ; 列出数据段字符串(iz),并用 grep 过滤器 ~+ 保留含 "jail" 的行 axt 0x10011db00 ; 查找引用 "Jailbreak: True" 字符串地址的交叉引用(xref) pdf @ 0x100008c14 ; 反汇编 0x100008c14 处的函数(print disassembly)
  • iz是 radare2 的数据段字符串列表命令;~+是 radare2 内置的 grep 过滤器,~+pattern表示只输出匹配行,这里用它从大量字符串中筛出所有包含jail的条目。
  • axt(address xrefs to)列出哪些代码位置引用了给定地址,是定位"某个字符串被哪个函数使用"的捷径。
  • pdf(print disassembly function)对指定地址所在函数做完整反汇编。

观察:输出揭示了什么

output.asm 是脚本的真实执行结果,演示文档明确指出:输出揭示了应用中对文件权限、协议处理器和文件目录的使用。逐段解读如下。

字符串命中:印证源码与二进制的一致性

越狱路径搜索命中从0x10011d850起连续排列的字符串区段,例如hit4_0 "4/Applications/Cydia.app/Applic"、hit8_0 "/usr/sbin/sshd/usr/bin/ssh/var/cache/a"——由于 Swift 会把相邻字符串常量紧凑拼接存储,命中结果显示的是"多个路径字符串连续排布"的原始字节视图,这与源码中jailbreakPaths数组的声明顺序一致。

URL Scheme 命中集中在0x1001a0e50区段(cydia://sileo://连续拼接),环境变量命中在0x10011d9c0区段(DYLD_INSERT_LIBRARIESDYLD_...)。这三组字符串分别对应源码中的jailbreakPaths、urlSchemes、suspiciousEnvVars三个数组,证明编译产物完整保留了这些检测常量。

iz~+jail:越狱检测的输出字符串与类型元数据

iz过滤结果定位到4.__TEXT.__cstring(C 字符串节)中的关键字符串:

0x0011da20 /private/jailbreak.txt 0x0011da40 /private/var/mobile/Library/jailbreak.txt 0x0011da90 _TtC10MASTestApp17JailbreakDetector 0x0011db00 Jailbreak: True\n\nProof:\n\n 0x0011db20 Jailbreak: False\n\nNo signs of a jailbreak detected. 0x0011dc30 Detected jailbreak file or directory at

其中_TtC10MASTestApp17JailbreakDetector是 Swift 的 mangled 类型名(_TtC+ 模块名长度10+MASTestApp+ 类名长度17+JailbreakDetector),可直接对应源码中的JailbreakDetector类;Jailbreak: True/False与Detected jailbreak file or directory at则是isDeviceJailbroken()与collectJailbreakProof()的输出文案。此外5.__TEXT.__const节中的JailbreakDetector字符串是 Swift 元数据(类型描述符)的一部分。

axt交叉引用:把字符串"绑定"到函数

xrefs to Jailbreak strings: sym.func.100008c14 0x100008dc8 [STRN:-w-] add x9, x9, str.Jailbreak:_True_n_nProof:_n_n

axt 0x10011db00确认地址0x100008dc8处的指令引用了Jailbreak: True字符串,而该指令位于sym.func.100008c14函数内。结合函数体内出现的SIMULATOR_DEVICE_NAME、Unknown Simulator等字符串(见下文反汇编),可以推断sym.func.100008c14正是JailbreakDetector.isDeviceJailbroken()的编译产物。

pdf反汇编:从函数序言到分支逻辑

对0x100008c14的反汇编显示这是一个724 字节的 ARM64 函数:

  • 函数序言:sub sp, sp, 0x60分配 0x60 字节栈帧,随后成对保存x26/x25 ... x29/x30寄存器,add x29, var_50h建立帧指针——标准的 Swift/ObjC 混编函数序言;
  • 环境变量读取:通过objc_msgSend调用读取进程环境,随后直接引用字符串"SIMULATOR_DEVICE_NAME"(0x10011dae0)做判断,对应源码ProcessInfo.processInfo.environment["SIMULATOR_DEVICE_NAME"];"Unknown Simulator"(0x10011db60)作为回退值出现;
  • 分支逻辑:cbz/tbz条件分支实现"模拟器 → 警告信息""证据为空 →Jailbreak: False文案""证据非空 →Jailbreak: True文案"三条输出路径,字符串拼接通过Swift.String.append(Swift.String)完成;
  • 证明收集调用:函数内调用sym.func.1000082b4,从结构看对应collectJailbreakProof()的证据收集子流程。

也就是说,仅凭iz+axt+pdf三个命令,就能在不开交互式会话的情况下,从二进制中重建出"检测器类 → 检测入口函数 → 输出文案 → 分支逻辑"的完整证据链,这正是该 r2 脚本的设计价值。

与测试用例的对应关系与评价

该演示是静态分析型测试 MASTG-TEST-0240:Jailbreak Detection in Code 的配套样例。该测试的判定逻辑为:

对应用二进制进行静态分析,检查是否包含常见越狱检测检查(如第三方应用商店 Sileo/Zebra 的存在性、典型越狱文件或目录的存在性)。测试失败的条件是应用未实现越狱检测。

具体步骤为:先用 MASTG-TECH-0058 从应用包中提取相关二进制,再用对应技术文档(如搜索 API/字符串)在二进制中查找相关检测痕迹。对照 MASTG-DEMO-0021 的 Evaluation 结论——"测试通过,因为应用中实现了越狱检测检查"——四类检测常量(路径、Scheme、环境变量)与输出文案均在output.asm中被完整检索到,静态证据充分。

需要强调的是测试元数据中的两个重要标注:

  • false_negative_prone: true:静态分析天然存在漏报风险。如果应用使用更复杂的混淆、间接字符串构造或加密存储检测逻辑,字符串搜索可能一无所获,此时需要人工逆向与去混淆(测试文档明确提示了这一点);
  • deprecated旧版测试:仓库 tests/ios/MASVS-RESILIENCE/MASTG-TEST-0088.md 是被废弃的 v1 版本,其思路是"把应用装到已越狱设备上运行观察崩溃/弹窗",由MASTG-TEST-0240与MASTG-TEST-0241在 MASTG V2 中取代。

局限性、适用前提与后续延伸

  1. 字符串搜索的边界:/与iz只能发现"以明文常量形式存在于二进制"的检测特征。真实世界中的应用常把路径拆成多段运行时拼接,或用String(format:)动态构造,这类实现需要动态分析配合(如 Frida 插桩或 r2frida 会话)。
  2. 静态分析 ≠ 行为确认:发现检测代码只能证明"实现了检测",不能证明"检测在运行时正确生效且不可绕过"。知识库 MASTG-KNOW-0084 明确指出,越狱检测单独使用效果有限,需分散在应用各处并与整体防篡改方案配合;绕过技术(如 hook 掉fileExists/canOpenURL返回值)对应 MASTG-TECH-0152 系列。
  3. 运行前提:本文全部命令以 radare2 已安装、且持有待分析 Mach-O 二进制为前提;-A全量分析在大二进制上耗时较长,若只想快速验证字符串可先去掉该参数。

如需继续深入,可直接在本仓库中复现:阅读 MastgTest.swift 对照 jailbreak_detection.r2 修改搜索词,重新执行 run.sh 生成新的output.asm,即可把该流程复用到任意 iOS 应用的越狱检测审计中。

  • 文档
  • 教程
  • 网络安全

【免费下载链接】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
点击查看免费下载
上一篇:Haystack 集成指南:使用 UnstructuredFileConverter 将多格式文档转换为 Document
下一篇:MLflow 模型依赖恢复实战:使用 mlflow.pyfunc.get_model_dependencies 精确还原训练环境

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/7 9:56:19

如何用RPCS3把PS3游戏调到60帧

如何用RPCS3把PS3游戏调到60帧 【免费下载链接】rpcs3 PlayStation 3 emulator and debugger 项目地址: https://gitcode.com/GitHub_Trending/rp/rpcs3 游戏一启动就卡成幻灯片,跑几分钟还闪退?RPCS3(PlayStation 3模拟器&#xff09…

作者头像 李华
网站建设 2026/10/7 9:55:54

Cadence Allegro 过孔替换:5种方法、参数核算与避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/7 9:55:13

游戏引擎基础架构详解:核心模块、主循环与资源管理

在游戏行业摸爬滚打这些年,我始终保持着拆引擎的习惯。你可能也在用Unity、Unreal,或者公司内部的引擎做项目,但当你真正去关心"游戏引擎架构"这几个字时,会发现市面上大多数教程都在教你怎么调API、怎么写玩法逻辑&…

作者头像 李华
网站建设 2026/10/7 9:54:51

Linux内核PM QoS:资源调度的契约机制与实战调优

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华