ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

OWASP MASTG 实战:基于 Frida D-Bus 端口探测的 iOS 运行时 Hook 检测(MASTG-DEMO-0118 深度解析)

OWASP MASTG 实战:基于 Frida D-Bus 端口探测的 iOS 运行时 Hook 检测(MASTG-DEMO-0118 深度解析) 文档教程网络安全【免费下载链接】mastgThe 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 Mobile Application Security Testing GuideMASTG仓库中的 MASTG-DEMO-0118 示例展开讲解 iOS 应用如何在调用敏感加密函数CCCrypt之前检测运行时是否存在 Frida 注入并在检测到 hook 时主动终止进程以阻止敏感数据被提取。读完本文你将掌握Frida 本地端口与 D-Bus 协议指纹的基本原理、Swift 中实现 socket 探针的完整编码模式、配套 Frida 攻击脚本的攻击路径以及这类检测技术的局限性与绕过思路可直接迁移到自己的 iOS 加固方案或安全测试用例设计中。一、示例定位MASTG-TEST-0354 下的成功防御样本MASTG-DEMO-0118 是 MASTG-TEST-0354Runtime Use of Hook Detection Techniques运行时 Hook 检测技术使用的一个kind: pass示例。该测试用例验证应用是否能在运行时检测并对抗 instrumentation / hooking 企图当CCCrypt、SecItemCopyMatching、LAContext.evaluatePolicy、URLSession相关 API 等处理敏感数据的函数被 hook 时应用如果没有防御性响应密钥、明文、令牌等敏感数据就可能被提取。仓库中该测试下有三个相互关联的演示构成一个完整的攻击—防御—再攻击对抗链条演示结果含义MASTG-DEMO-0117fail无任何 Hook 检测机制CCCrypt中的敏感 API Key 被 Frida 以明文提取防御失败/攻击成功MASTG-DEMO-0118本文pass加密前探测本地 Frida 端点检测到后立即终止攻击失败防御成功/攻击失败MASTG-DEMO-0119fail通过 hookconnect()屏蔽端口探测绕过检测并重新提取明文防御失败/攻击成功环境说明该演示使用 Xcode 26.2.9 构建在运行 iOS 16.7.10以 Dopamine 2.4.9 越狱的 iPhone 上测试。核心源码位于 MastgTest.swift。二、示例设计加密前先探 Frida 指纹与未受保护的 MASTG-DEMO-0117 不同本示例的MastgTest类在执行任何敏感加密操作之前先尝试探测设备上是否存在 Frida 的控制端点尝试连接127.0.0.1上 Frida 的默认本地端口27042越狱/root 设备上frida-server通常暴露该端口连接成功后发送一个 D-BusAUTH探针若端点像 D-Bus 服务一样响应应用即判定存在 Frida 运行时产物并在任何加密操作执行之前调用exit(0)终止自身。也就是说该检测利用了两个事实frida-server默认监听 TCP 27042 端口且其通信基于 D-Bus 协议——即使端口被开放非 D-Bus 服务的普通端口不会对AUTH探针给出 D-Bus 风格应答。相关知识详见 MASTG-KNOW-0087Reverse Engineering Tools Detection中关于Checking For Ports Responding To D-Bus Auth的讨论。三、源码解析Swift 实现的 D-Bus 端口探针MASTG-TEST-0354 描述的是一类通用检测要求而本演示给出的是其中一个非常具体、可直接复用的实现形态。核心入口是mastgTest静态方法检测到 hook 立即退出否则继续执行加密演示。static func mastgTest(completion: escaping (String) - Void) { if detectHooking() { exit(0) } completion(runCryptoDemo()) }3.1 检测入口detectHooking()private static func detectHooking() - Bool { let ports: [in_port_t] [27042] return ports.contains(where: respondsToDBusAuth) }检测逻辑把待探测端口列表化当前仅27042即 Frida 默认端口只要其中任何一个端口对 D-BusAUTH有应答就判定存在 Frida。将端口收敛为数组的好处是便于后续扩展为多端口/多指纹扫描但注意Frida 允许通过命令行参数修改监听端口仅探测默认端口覆盖面有限详见后文局限性与绕过。3.2 端口指纹探测respondsToDBusAuth()这是整个防御机制的核心完整实现了建连 → 发探针 → 收应答 → 判指纹四步1建立 TCP 连接let descriptor socket(AF_INET, SOCK_STREAM, 0) guard descriptor 0 else { return false } defer { close(descriptor) } var timeout timeval(tv_sec: 1, tv_usec: 0) setsockopt(descriptor, SOL_SOCKET, SO_RCVTIMEO, timeout, socklen_t(MemoryLayouttimeval.size)) setsockopt(descriptor, SOL_SOCKET, SO_SNDTIMEO, timeout, socklen_t(MemoryLayouttimeval.size)) var address sockaddr_in() address.sin_len UInt8(MemoryLayoutsockaddr_in.size) address.sin_family sa_family_t(AF_INET) address.sin_port port.bigEndian address.sin_addr in_addr(s_addr: inet_addr(127.0.0.1)) let connected withUnsafePointer(to: address) { pointer in pointer.withMemoryRebound(to: sockaddr.self, capacity: 1) { socketAddress in connect(descriptor, socketAddress, socklen_t(MemoryLayoutsockaddr_in.size)) 0 } } guard connected else { return false }细节要点通过socket(AF_INET, SOCK_STREAM, 0)创建 IPv4 TCP socketsocket 描述符非负才继续并在defer中确保关闭SO_RCVTIMEO/SO_SNDTIMEO均设为 1 秒超时避免对不响应端口做无界阻塞——这是移动端检测必须考虑的健壮性设计目标地址固定为回环地址127.0.0.1端口以网络字节序port.bigEndian填入sockaddr_inconnect()返回 0 才认为端口可达否则直接判定为无 Frida。2发送 D-Bus AUTH 探针let authProbe UInt8 let sent authProbe.withUnsafeBytes { buffer in send(descriptor, buffer.baseAddress, buffer.count, 0) } guard sent authProbe.count else { return false }探针字节为\0AUTH\r\n——这是 D-Bus 认证协议的标准起始消息NUL 字节 AUTH CRLF。只有 D-Bus 服务才能正确理解并应答它普通 TCP 服务要么忽略、要么返回非 D-Bus 格式数据。只有完整发送全部探针字节sent authProbe.count才继续。3读取并解析应答指纹var response UInt8 let received recv(descriptor, response, response.count, 0) guard received 0 else { return false } let responseText String(decoding: response.prefix(received), as: UTF8.self).uppercased() return responseText.contains(REJECTED) || responseText.contains(OK)预留 256 字节接收缓冲区recv返回大于 0 才继续将响应内容按 UTF-8 解码并大写化只要响应文本包含 D-Bus 认证流程中的典型关键字REJECTED或OK即判定为 Frida 的 D-Bus 端点。对 D-Bus AUTH 握手而言服务端应答OK guid表示接受认证REJECTED表示拒绝——无论哪种都证明对面是一个 D-Bus 服务这正是frida-server的显著指纹。3.3 检测时机多点多段布防值得注意的实现细节是detectHooking()并非只调用一次而是在敏感操作的多个关键节点重复布防// 生成 IV 前 if detectHooking() { exit(0) } // 执行 CCCrypt 加密前PASS: MASTG-TEST-0354 if detectHooking() { exit(0) } guard let encryptedData crypt(operation: CCOperation(kCCEncrypt), ...) else { ... } // 解密前 if detectHooking() { exit(0) } guard let decryptedData crypt(operation: CCOperation(kCCDecrypt), ...) else { ... }从源码结构看检测点覆盖了生成 IV 之前、加密调用之前、解密调用之前三个节点。这与 MASTG-BEST-0048 中将检测分散到应用各处、变化检测时机例如定期、随机事件或敏感操作前的加固建议是一致的——把检查前移到每次敏感操作之前缩小了攻击者在两次检查之间完成注入的时间窗。3.4 加密演示CommonCrypto 的 CCCrypt检测通过后才执行runCryptoDemo()使用 CommonCrypto 的CCCrypt对敏感 API Key 做 AES-128-CBCPKCS7 填充加解密let sensitiveApiKey sk-OWASP-MAS-SuperSecretKey-1234567890 let key Data(0123456789abcdef0123456789abcdef.utf8) let plaintext Data(sensitiveApiKey.utf8) guard let iv randomBytes(count: kCCBlockSizeAES128) else { ... }sensitiveApiKey待保护的敏感数据模拟真实场景中的服务端 API Key是攻击方 hook 的目标keyAES-128 密钥32 个十六进制字符对应 16 字节iv通过SecRandomCopyBytes(kSecRandomDefault, ...)生成 16 字节kCCBlockSizeAES128随机 IVcrypt封装统一调用CCCrypt根据operation参数区分kCCEncrypt/kCCDecrypt输出缓冲按data.count kCCBlockSizeAES128预分配以容纳填充最终按kCCSuccess状态码校验并把outputLength之后的多余字节裁掉。四、攻击视角script.js 如何提取 CCCrypt 数据理解防御必须先理解攻击。攻击脚本 script.js 通过 Frida 的Module.findGlobalExportByName(CCCrypt)定位 CommonCrypto 导出符号并用Interceptor.attach挂钩其入口与出口onEnter读取前 11 个参数——operation0kCCEncrypt1kCCDecrypt、algorithm0kCCAlgorithmAES、dataIn输入缓冲区指针、dataInLength、dataOut、dataOutMoved等并用Thread.backtrace(this.context, Backtracer.ACCURATE)取前 8 帧调用栈DebugSymbol.fromAddress解析符号名onLeave读取返回值状态与dataOutMoved指示的实际输出长度以 UTF-8 可打印文本或十六进制两种形式输出输入/输出缓冲脚本启动即打印[] CCCrypt hooked: extracting sensitive cryptographic data。formatBuffer的细节体现了实战提取的通用技巧先尝试readUtf8String并过滤可打印字符isPrintable失败再回退到bytesToHex十六进制输出长度超过 128 字节时截断前缀避免刷屏。这正是 MASTG-DEMO-0117 中能拿到sk-OWASP-MAS-SuperSecretKey-1234567890明文的原因。启动命令封装在 run.sh 中frida -U -f org.owasp.mastestapp.MASTestApp-iOS -l ./script.js -o output.txt参数含义-U通过 USB 连接设备-f以 spawn 模式启动指定 bundle ID 的应用保证脚本在main之前注入-l加载脚本-o把输出重定向到output.txt。关于 Frida 在 iOS 上的安装与使用包括 frida-server 的默认监听配置、Sileo 源安装方式、frida-ps -U验证等参见 MASTG-TOOL-0039。五、复现步骤完整复现流程如下其中安装应用步骤参见 MASTG-TECH-0056在一台越狱iPhone 上安装该应用MASTG-TECH-0056在主机上安装 FridaMASTG-TOOL-0039并确保设备上frida-server正在运行执行run.sh以 Frida spawn 方式启动应用并注入脚本点击应用中的Start按钮触发测试流程观察应用在 hook 能捕获任何数据之前就自行终止。六、观察结果与测试评估运行后 output.txt 的全部内容仅有[] CCCrypt hooked: extracting sensitive cryptographic data也就是说Frida 脚本成功加载并完成了CCCrypt挂钩的准备工作但运行时没有任何一条CCCrypt调用记录——应用在脚本加载完成后、hook 真正触发前已被detectHooking()探测到本地 D-Bus 端点并执行exit(0)终止敏感 API Key 未被提取。评估结论pass测试通过因为 hook 企图因应用的防御性响应而失败。具体而言本环境中frida-server暴露了本地 Frida 端点且应用是以 Frida spawn 方式启动的应用向127.0.0.1:27042发送 D-BusAUTH消息端点返回 D-Bus 认证应答后应用在CCCrypthooks 执行前终止因此没有敏感数据被提取。七、局限性与绕过检测并非万无一失原演示文档特别强调即便测试通过仍存在绕过防御的可能性例如更换非默认端口frida-server可通过命令行参数修改监听端口绕过对 27042 的固定探测hook 检测所依赖的系统调用攻击者可以 hookconnect、send或recv让应用无法观察到 D-Bus 认证应答例如让connect失败或让recv返回空从而使detectHooking()返回false。这两条路径在仓库中都有直接证据MASTG-DEMO-0119 使用与 MASTG-DEMO-0118 完全相同的应用代码仅通过在 Frida 脚本中 hookconnect()阻止与 Frida 默认端口的连接就使detectHooking()返回false随后两条CCCrypt调用被成功捕获明文 API Key 重新落入攻击者手中该演示为 fail。这验证了 MASTG-KNOW-0087 的核心论断工具检测是猫鼠游戏——检测方法的效果取决于是否越狱、越狱方式与版本、工具自身版本任何单一检测都可能被绕过。此外MASTG-TEST-0354 明确声明Out of Scope该测试不评估 hook 检测机制的健壮性或抗绕过能力检测与绕过技术都在持续演进有决心的攻击者借助更高级的 instrumentation 机制终究可以绕过这类机制应作为纵深防御策略的一部分而非独立解决方案。八、加固启示从单一探针到分层防御MASTG-BEST-0048Hardening Against Reverse Engineering Tools总结了本演示背后可迁移的 iOS 加固方法论分为三类控制侦探型控制Detective扫描已知逆向工具痕迹——例如用_dyld_image_count/_dyld_get_image_name遍历已加载动态库、查找含frida、gadget、cynject等特征串的库名探测 TCP 27042 端口是否对 D-Bus AUTH 有应答即本演示所用技术。注意前者对 frida-server 注入模式无效其使用绕过 dyld 的自定义 Mach-O 加载器需多种技术组合威慑型控制Deterrent将检测逻辑写入 C 原生代码比 Swift/Objective-C 更难被ObjC/SwiftAPI hook对检测逻辑做混淆把检查分散到应用各处并变化时机避免集中在单一命名函数固定入口可被一处 hook 打掉响应型控制Responsive检测到工具后立即终止会话、清除内存中的敏感数据、通知后端标记被入侵的会话绝不在受控状态下继续运行。MASTG-DEMO-0118 的敏感加密操作前多点探测 命中即exit(0)正是侦探型 响应型控制的直接落地而检测点分散、原生实现、混淆、多技术组合则是从 DEMO-0119 的绕过中总结出的下一步演进方向。九、总结MASTG-DEMO-0118 提供了一个简洁、可复现、可测试的 iOS 运行时 Hook 检测参考实现利用frida-server默认暴露的 27042 端口与其 D-Bus 协议指纹在CCCrypt加密/解密前多点探测并终止进程从而在 MASTG-TEST-0354 的对抗测试中获得 pass。同时配套的 MASTG-DEMO-0117无防御基线与 MASTG-DEMO-0119connect()挂钩绕过清晰展示了该类防御的适用范围与边界提醒开发者任何单一检测手段都必须置于纵深防御框架内配合原生实现、逻辑混淆、多点布防与合理的响应动作才能在持续演进的攻防博弈中提升绕过成本。赞分享文档教程网络安全【免费下载链接】mastgThe 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点击查看免费下载相关推荐Android 运行时 Hook 检测实战基于 /proc/self/maps 的 Frida 检测与进程终止MASTG-DEMO-0107 深度剖析Android 运行时 Hook 检测实战基于 /proc/self/maps 的 Frida 检测与进程终止MASTG DEMO 0107 深度剖析 本文档教程网络安全绕过 Frida D-Bus 端口检测并提取敏感数据MASTG-DEMO-0119 实战解析绕过 Frida D Bus 端口检测并提取敏感数据MASTG DEMO 0119 实战解析 导读 本文围绕 OWASP MASTGMobile Appli文档教程网络安全使用 Frida 运行时监控 iOS WKWebView 本地文件访问OWASP MASTG MASTG-DEMO-0099 实战解析使用 Frida 运行时监控 iOS WKWebView 本地文件访问OWASP MASTG MASTG DEMO 0099 实战解析 本文基于 OWASP文档教程网络安全上一篇IronOS代码重构案例提高可维护性的实践下一篇PDF补丁丁专业PDF深度编辑与批量处理的终极解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表