)
文档教程网络安全【免费下载链接】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 MASTG 官方演示用例 MASTG-DEMO-0014 为主线完整演示如何对使用 CryptoKit 的 iOS 应用进行静态分析定位其二进制中硬编码的 P-256 ECDSA 私钥。读者将掌握「解包 IPA → radare2 符号与交叉引用分析 → DATA 段密钥定位」的完整检测链路并能将这套方法直接复用于任何基于 Security / CommonCrypto / CryptoKit 的 iOS 应用。背景与测试目标MASTG-TEST-0213 与 MASWE-0003本演示对应的测试用例是 MASTG-TEST-0213「Use of Hardcoded Cryptographic Keys in Code」属于 iOS 平台的静态、代码级、人工确认型type: [static, code, manual]测试关联的弱点是 MASWE-0003硬编码加密密钥。该测试明确指出了 iOS 上最常出现硬编码密钥的三个框架入口Security FrameworkSecKeyCreateWithData允许开发者直接从原始数据创建密钥CommonCryptoCCCrypt的key参数可直接传入原始密钥数据CryptoKit虽然提供了高层抽象开发者仍可能以各种格式硬编码密钥并交给P256.Signing.PrivateKey.init(rawRepresentation:)之类的初始化方法使用——这正是本演示样本的做法。测试还归纳了硬编码密钥的三种典型表现形式在分析时可以作为搜索线索表现形式说明原始字节数组Raw Byte Arrays密钥直接以[UInt8]数组或Data对象内嵌在代码中例如 32 字节的 P-256 私钥、256 位 AES 密钥Base64 编码字符串密钥以 Base64 字符串形式写入代码运行时再解码Hex 编码字符串密钥存为十六进制字符串运行时转换为Data再参与密码运算该测试同时取代了旧版 MASTG-TEST-0062「Testing Key Management」原 MSTG-CRYPTO-1 / MSTG-CRYPTO-5状态为 deprecated在 MASTG V2 中由 MASTG-TEST-0213 与 MASTG-TEST-0214 共同覆盖。样本剖析在 CryptoKit 中使用硬编码 P-256 私钥演示样本的完整 Swift 源码位于 MastgTest.swift其核心逻辑是把一个写死在代码里的 32 字节 P-256 私钥交给 CryptoKit 完成签名与验签再把结果拼成字符串输出。完整代码如下import Foundation import CryptoKit struct MastgTest { static func mastgTest(completion: escaping (String) - Void) { // Step 1: Use a hardcoded ECDSA P-256 private key (32 bytes for P-256) in bytes let privateKeyBytes: [UInt8] [ 0x7c, 0x02, 0x2a, 0x7e, 0x53, 0x7e, 0x1a, 0x2d, 0x44, 0x77, 0xd4, 0xf6, 0x20, 0x8b, 0x14, 0xdb, 0x4e, 0x8d, 0x84, 0x19, 0xd6, 0x23, 0x5f, 0xf2, 0x4e, 0x4b, 0x8d, 0x18, 0xf4, 0x2c, 0x76, 0xe2 ] let privateKeyData Data(privateKeyBytes) guard let privateKey try? P256.Signing.PrivateKey(rawRepresentation: privateKeyData) else { completion(Failed to create private key.) return } let publicKey privateKey.publicKey // Data to sign let dataToSign This is a sample text.data(using: .utf8)! // Step 2: Sign the data with the hardcoded private key let signature try! privateKey.signature(for: dataToSign) // Convert signature to hex string for display let signatureHex signature.rawRepresentation.map { String(format: %02hhx, $0) }.joined() // Step 3: Verify the signature with the public key let verificationStatus publicKey.isValidSignature(signature, for: dataToSign) let verificationResult verificationStatus ? Signature is valid. : Signature is invalid. let value Original: \(String(data: dataToSign, encoding: .utf8)!) Public Key (Hex): \(publicKey.rawRepresentation.map { String(format: %02hhx, $0) }.joined()) Signature (Hex): \(signatureHex) Verification: \(verificationResult) completion(value) } }从源码层面可以提炼出检测时关注的几个关键点硬编码密钥本身privateKeyBytes是一个 32 字节P-256 曲线私钥的标准长度的[UInt8]数组属于上述「原始字节数组」表现形式密钥的消费入口MastgTest.swift 通过P256.Signing.PrivateKey(rawRepresentation: privateKeyData)把字节数据还原成私钥对象rawRepresentation正是分析时最关键的符号密钥的派生使用privateKey.publicKey导出公钥、privateKey.signature(for:)生成 ECDSA 签名、publicKey.isValidSignature(_:for:)完成验签这些 CryptoKit 符号都会在二进制中留下可检索的导入记录。理解样本后下面进入「编译产物」层面的检测流程——即对同目录下的主二进制 MASTestApp 做静态分析。检测步骤总览原文档的检测流程包含两个核心步骤Step 1解包应用定位主二进制按照 MASTG-TECH-0058「Exploring the App Package」 的方法先用unzip解包 IPA在Payload目录下找到 Application Bundle.app主二进制即./Payload/MASTestApp.app/MASTestApp。MASTG-TECH-0058中给出的一般形式如下unzip AppName.ipa ls -1 Payload/AppName.appStep 2用 radare2 打开二进制并执行分析脚本使用 radare2MASTG-TOOL-0073 以-i选项加载本演示配套的 radare2 脚本cryptokit_hardcoded_ecdsa.r2-i表示执行脚本后进入交互模式这里结合-q静默退出并配合-A全量分析。对应的运行命令记录在 run.sh 中r2 -q -i cryptokit_hardcoded_ecdsa.r2 -A MASTestApp output.asm标准输出被重定向到output.asm供后续人工审阅。radare2 脚本逐条解析分析脚本 cryptokit_hardcoded_ecdsa.r2 是一个 radare2 命令序列先做输出环境设置再依次执行符号检索、交叉引用、反汇编与内存转储核心逻辑如下e asm.bytesfalse e scr.colorfalse e asm.varfalse ?e Uses of CryptoKit.P256.Signing.PrivateKey: afl~CryptoKit.P256.Signing.PrivateKey ?e ?e xrefs to CryptoKit.P256.Signing.PrivateKey.rawRepresentation: axt 0x100007388 ?e ?e Use of CryptoKit.P256.Signing.PrivateKey.rawRepresentation: pd-- 9 0x1000048d4 pdf sym.func.1000046dc function.asm px 32 0x1000100c8 key.asm各条命令的作用如下命令作用e asm.bytesfalse反汇编输出中不显示原始指令字节保持输出简洁可读e scr.colorfalse关闭颜色便于重定向到文件后阅读e asm.varfalse隐藏反汇编中的局部变量名聚焦指令序列afl~CryptoKit.P256.Signing.PrivateKey在函数列表afl中用~过滤出与CryptoKit.P256.Signing.PrivateKey相关的符号即二进制中导入/引用了该类型的哪些成员axt 0x100007388在地址0x100007388上执行交叉引用查询axt找出该导入符号PrivateKey 元数据符号被哪些代码位置引用pd-- 9 0x1000048d4在0x1000048d4处向前反汇编 9 条指令pd--还原rawRepresentation调用点的上下文pdf sym.func.1000046dc function.asm对包含该调用点的函数sym.func.1000046dc做完整反汇编pdf结果保存到 function.asmpx 32 0x1000100c8 key.asm在0x1000100c8处转储 32 字节内存px 32结果保存到 key.asm用于直接查看硬编码密钥的原始字节这套脚本的巧妙之处在于先用afl/axt从符号层确认「应用使用了 CryptoKit 私钥 API」再用pdf还原调用上下文最后用px直接把候选密钥字节dump出来——三层递进从「用了什么」到「在哪用」再到「密钥是什么」。观察结果解读符号层CryptoKit.P256.Signing.PrivateKey 的四处使用脚本第一段查询的输出见 output.asm列出了二进制中与CryptoKit.P256.Signing.PrivateKey相关的全部符号Uses of CryptoKit.P256.Signing.PrivateKey: 0x100007364 1 12 sym.imp.CryptoKit.P256.Signing.PrivateKey.public...F0AE06PublicF0Vvg.Public...F0Vvg...Vvg 0x100007370 1 12 sym.imp.CryptoKit.P256.Signing.PrivateKey.rawRepresentation.Foundation.ContiguousBytes...lufC 0x10000737c 1 12 sym.imp.CryptoKit.P256.Signing.PrivateKey.signature.for.ECDSASignature.Foundation.DataProtocol...lF 0x100007388 1 12 sym.imp.CryptoKit.P256.Signing.PrivateKey...VMa尽管 Swift 符号被编译期改名mangling得面目全非但仍能清晰还原出样本源码中的四个 API 使用点PrivateKey.public→ 对应源码privateKey.publicKey公钥导出PrivateKey.rawRepresentation→ 对应P256.Signing.PrivateKey(rawRepresentation:)初始化这是把硬编码字节喂给 CryptoKit 的关键入口PrivateKey.signature(for:)→ 对应privateKey.signature(for: dataToSign)ECDSA 签名PrivateKey...VMa→ 类型元数据符号表明二进制中确实实例化了该类型。交叉引用层rawRepresentation 的调用点第二段查询用axt 0x100007388反查元数据符号的引用位置输出指向了函数sym.func.1000046dcxrefs to CryptoKit.P256.Signing.PrivateKey.rawRepresentation: sym.func.1000046dc 0x1000047f0 [CALL:--x] bl sym.imp.CryptoKit.P256.Signing.PrivateKey...VMa说明sym.func.1000046dc即样本中mastgTest编译后的函数在0x1000047f0处调用了 PrivateKey 的构造/元数据符号随后pd-- 9 0x1000048d4还原出该函数内调用rawRepresentation的指令序列│ 0x1000048c8 sub x0, x29, 0x80 │ 0x1000048cc mov x8, x20 │ 0x1000048d0 mov x21, 0 │ 0x1000048d4 bl sym CryptoKit.P256.Signing.PrivateKey.rawRepresentation.Foundation.ContiguousBytes...lufC ; sym.imp.CryptoKit.P256.Signing.PrivateKey.rawRepresentation.Foundation.ContiguousBytes...lufC │ ┌─ 0x1000048d8 cbz x21, 0x100004900blbranch with link到rawRepresentation的实现符号cbz x21是 Swift 可失败初始化器try?的典型错误分支检查——这与源码中guard let privateKey try? P256.Signing.PrivateKey(rawRepresentation:)的写法一一对应。数据层DATA 段中的 32 字节私钥脚本的最后一步px 32 0x1000100c8把密钥候选内存 dump 到了 key.asm- offset - C8C9 CACB CCCD CECF D0D1 D2D3 D4D5 D6D7 89ABCDEF01234567 0x1000100c8 7c02 2a7e 537e 1a2d 4477 d4f6 208b 14db |.*~S~.-Dw.. ... 0x1000100d8 4e8d 8419 d623 5ff2 4e4b 8d18 f42c 76e2 N....#_.NK...,v.对照源码中privateKeyBytes数组二者逐字节完全一致源码: 0x7c 0x02 0x2a 0x7e 0x53 0x7e 0x1a 0x2d 0x44 0x77 0xd4 0xf6 0x20 0x8b 0x14 0xdb 内存: 7c02 2a7e 537e 1a2d 4477 d4f6 208b 14db 源码: 0x4e 0x8d 0x84 0x19 0xd6 0x23 0x5f 0xf2 0x4e 0x4b 0x8d 0x18 0xf4 0x2c 0x76 0xe2 内存: 4e8d 8419 d623 5ff2 4e4b 8d18 f42c 76e2地址0x1000100c8位于segment.__DATA段基址0x100010000偏移0xc8即密钥被编译器作为静态数据存进了二进制的 DATA 段。这与 evaluation.txt 中对0x1000047b4附近指令的注释一致adrp x0, segment.__DATA加载 DATA 段基址add x0, x0, 0xe8定位到密钥相关数据所在偏移随后调用PrivateKey初始化器完成密钥装载。函数层完整反汇编与 AI 辅助反编译pdf sym.func.1000046dc生成的 function.asm 长达 1840 字节是mastgTest函数的完整 AArch64 反汇编。其中可以清楚看到与源码一一对应的调用序列0x100004780处bl sym CryptoKit.P256.Signing.PublicKey...VMa—— PublicKey 类型元数据0x1000047f0处bl sym CryptoKit.P256.Signing.PrivateKey...VMa—— PrivateKey 类型元数据构造入口0x1000048d4处调用rawRepresentation上文已述0x1000049e8处bl sym CryptoKit.P256.Signing.PrivateKey.public...—— 对应privateKey.publicKey0x100004aa8处bl sym CryptoKit.P256.Signing.PrivateKey.signature.for...—— 对应privateKey.signature(for:)0x100004b6c处bl sym CryptoKit.P256.Signing.PublicKey.isValidSignature.for...—— 对应publicKey.isValidSignature(_:for:)字符串区0x100007f20「This is a sample text」、0x100007f60「Signature is invalid.」、0x100007fe0「Signature is valid.」等常量也都完整保留在二进制中。由于 AArch64 汇编可读性有限演示还借助人工智能对反汇编进行了二次反编译产物是 decompiled-o1-review.swift。该文件把上述汇编还原成了可读的 Swift 逻辑从内嵌数据装载 P-256 私钥、导出公钥、对「This is a sample text」签名并验签、最后把密钥与签名转成 Hex 拼接输出。需要注意原文档明确提示AI 反编译结果可能不完美、可能存在错误但在本例中它清晰地印证了CryptoKit.P256.Signing.PrivateKey的使用以及关联私钥的存在可作为人工复核汇编代码的高效辅助。评估结论按照 MASTG-TEST-0213 的评估标准——「只要在二进制中发现携带硬编码密钥的密码学函数调用测试即失败」——本样本测试失败原因非常明确在二进制中发现了一个硬编码的 ECDSA 私钥32 字节 P-256它被直接存储于 DATA 段并通过CryptoKit.P256.Signing.PrivateKey.rawRepresentation初始化器装载参与签名运算。整个证据链是完整闭环的符号证据afl过滤出PrivateKey.rawRepresentation、signature(for:)等导入符号调用证据axtpd--定位到sym.func.1000046dc内的bl rawRepresentation调用点数据证据px 32 0x1000100c8dump 出的 32 字节与源码硬编码数组逐字节一致。修复与加固方向从防御者视角修复此类问题的思路可以对照旧版 MASTG-TEST-0062 中给出的密钥管理原则密钥不得硬编码、不得在无额外保护的情况下存储、不得从不可信位置导入、不得用底层语言C/C隐藏密钥。落到 iOS 工程实践上通常的做法包括将私钥放入 Keychain可结合 Secure Enclave 支持运行时从 Keychain 读取而非写死在代码中签名私钥等敏感材料由服务端动态下发或通过受控的密钥协商流程获取避免随应用包分发至少也应把密钥以环境变量、配置文件等方式外置并配合访问控制而不是作为字节数组常量编译进二进制——因为本文已经证明这类常量在 DATA 段中一查便知。相关资源索引演示主文档MASTG-DEMO-0014.md样本源码MastgTest.swift分析脚本cryptokit_hardcoded_ecdsa.r2 与运行命令run.sh分析产物output.asm、key.asm、function.asm、evaluation.txt、decompiled-o1-review.swift关联测试用例MASTG-TEST-0213 与已废弃的 MASTG-TEST-0062配套技术文档MASTG-TECH-0058探索应用包、MASTG-TOOL-0073radare2同目录下的 MASTG-DEMO-0013 同样覆盖 MASTG-TEST-0213可作为本演示的对照案例进一步阅读。赞分享文档教程网络安全【免费下载链接】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点击查看免费下载相关推荐MASTG 安卓硬编码加密密钥检测用 semgrep 与 SecretKeySpec 静态分析实战MASTG-DEMO-0017MASTG 安卓硬编码加密密钥检测用 semgrep 与 SecretKeySpec 静态分析实战MASTG DEMO 0017 本篇文章基于 OWASP文档教程网络安全使用 radare2 静态分析 iOS Keychain 生物认证回退kSecAccessControlUserPresence 实战解析MASTG-DEMO-0043使用 radare2 静态分析 iOS Keychain 生物认证回退kSecAccessControlUserPresence 实战解析MASTG DEM文档教程网络安全OWASP MASTG 实战用 Semgrep 静态检测 Android StrictMode 使用MASTG-DEMO-0039OWASP MASTG 实战用 Semgrep 静态检测 Android StrictMode 使用MASTG DEMO 0039 导读 本文基于 OW文档教程网络安全上一篇Dism 免费系统优化工具使用手册清垃圾、修更新、备份一步到位下一篇硬盘被重复照片塞满用 AntiDupl.NET 半小时清掉数千张冗余图片创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考