关于 re-macos
面向 macOS 原生及闭源应用的逆向分析技能,供研究者检查应用的签名、公证、沙箱和系统权限。内容还涵盖 dyld 加载链、注入面、钥匙串与 Secure Enclave 分析,并强调隐私数据只读处理。
主要功能
- 01检查代码签名与公证状态
- 02分析 entitlements 和沙箱边界
- 03检查 TCC 权限依赖
- 04分析钥匙串与 Secure Enclave 使用
- 05检查 dyld 依赖及注入面
- 06定位反调试与签名校验
适用场景
- 01核查 macOS 应用的签名者和分发状态
- 02评估应用请求的隐私权限
- 03调查动态库劫持或注入风险
- 04分析应用的硬件密钥使用方式
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ dslsdzc/ rev-skills --skill re-macos安装后在 Claude Code 中输入/re-macos确认已加载。
附带文件references/decision-tree.mdreferences/gotchas.md
详细介绍
来自项目 READMEmacOS 应用逆向
何时使用 / 何时不用
- 用:macOS 原生/闭源应用(.app/.dylib/.framework)、带签名公证与沙箱的目标、钥匙串/Secure Enclave 硬件密钥场景
- 用:授权/分发状态判定——签名者、公证、hardened runtime、Team ID 是谁(分发面/信任面分析)
- 用:信任链问题——Dylib Hijacking、注入面、TCC 依赖(哪些隐私能力被请求/使用)
- 不用:iOS 应用(转 [[re-ios]]);纯 Mach-O 格式解析(转 [[re-format-macho]])
- 不用:Linux/Windows 目标(各走 [[re-gdb]] / [[re-x64dbg]])
- 不用:只想抓网络流量/文件行为(无 macOS 特有面时走 [[re-behavior]] / [[re-netcap]] 通用路径)
- 注意:TCC 与钥匙串数据属系统隐私范畴,只读分析不导出内容(红线)
工具准备
codesign / spctl / otool / lipo(签名与 Mach-O 工具,macOS 内置)
- macOS: 系统自带(Xcode 命令行工具
xcode-select --install) - Linux: 可静态分析 Mach-O(
llvm-otool,brew install llvm或发行版 llvm 包),签名解析受限 - 验证:
codesign --version、macOS:otool --version;Linux:llvm-otool --version
plutil / xattr(Info.plist 与 quarantine 检查,macOS 内置)
- 验证:
plutil -help、xattr -h - 用途: Info.plist 键解析(
plutil -p);com.apple.quarantine扩展属性决定 Gatekeeper 是否拦截
Hopper / IDA / Ghidra(反编译底座)
- 安装与验证见 [[re-ida]] / [[re-ghidra]]
lldb(动态调试)
- 安装与验证见 [[re-lldb]];attach 前先处理 PT_DENY_ATTACH(步骤 6)
操作步骤
按顺序执行,每步产物存档(路径 + sha256,见 [[re-triage]])。签名/entitlements 信息按 [[re-analyze/analysis-contract]] 契约记录。
-
包结构与签名检查:
file Sample.app/Contents/MacOS/Sample codesign -dv Sample.app 2>&1 | head # 签名者/Team ID(要求需 `-d -r-` 查看) spctl -a -vv Sample.app 2>&1 # 公证状态(Gatekeeper) defaults read Sample.app/Contents/Info.plist # Info.plist 关键键- 关注:签名者(Apple 开发者/分发证书)、Team ID、CDHash、Hardened Runtime(runtime 标志)、Info.plist 的 CFBundleIdentifier/版本/最低系统版本
- 架构确认:
file输出/x86_64 与 arm64 通用二进制(lipo -archs)——决定反编译与动态环境(Apple Silicon 上 arm64e 有 PAC 差异,见 [[gotchas]]) - 公证派生检查:
spctl -a通过不保证本地有 staple——xcrun stapler validate Sample.app查票证是否随包 - 隔离属性检查:
xattr -l Sample.app看com.apple.quarantine(隔离标志 + 时间戳 + 责任方 App;不含来源 URL——来源信息在 Spotlight 属性里,用mdls -name kMDItemWhereFroms Sample.app查)
-
entitlements 与沙箱:
codesign -d --entitlements :- Sample.app 2>&1 | head -30- 关键键分组:
com.apple.security.app-sandbox(沙箱总开关)、network.client/server(网络)、files.user-selected.*(用户选文件)、device.camera/microphone(设备)、application-groups(组共享)、cs.allow-dyld-environment-variables/cs.disable-library-validation(注入面)、get-task-allow(调试权限,发布版不应有) - 沙箱 profile 决定能力边界——分析授权逻辑与攻击面时先看 entitlements 清单,动态行为再交叉验证
- 异常信号:发布版带
get-task-allow(本应只用于开发调试)或越权组合(如无 UI 却开device.camera)——记录为可疑项进结论
- 关键键分组:
-
TCC 权限库:
# 用户级 TCC 库(授权记录) ls ~/Library/Application\ Support/com.apple.TCC/ # 系统级 TCC 库 ls /Library/Application\ Support/com.apple.TCC/- 前置检查:TCC.db 自身受 TCC 保护——无 Full Disk Access 时读取会权限失败,先确认授权再读
- TCC.db(SQLite)记录各 App 对隐私资源的授权;分析目标对 TCC 的依赖(请求了什么权限、何时请求、失败路径)
- 注意:TCC 数据属系统隐私数据,只读分析不导出内容(红线)
-
钥匙串与 Secure Enclave:
- 钥匙串条目类型(通用密码/互联网密码/密钥)与访问条件——
kSecAttrAccessible是可访问性(设备处于什么状态时可读:非锁定/首次解锁/此设备),不是 ACL;访问控制是kSecAttrAccessControl/SecAccessControl(生物识别/密码门槛),macOS 传统 ACL 另有SecAccess/kSecAttrAccess(见 [[gotchas]]) - Secure Enclave 密钥:用
SecKeyCreateRandomKey(属性含kSecAttrTokenID: kSecAttrTokenIDSecureEnclave)在设备内生成——SecKeyCreateWithData是从外部 key data 导入/恢复,SE 私钥永不出芯片、无法导入,别把它当 SE 生成接口;私钥不可提取(等价 Android Keystore 硬件背书,见 [[re-android-native]] Keystore 审计) - 分析:目标读哪些钥匙串条目(SecItemCopyMatching 调用点)、密钥是否 Secure Enclave 绑定(不可提取 → 记录用途与访问条件而非找字节)
- 钥匙串条目类型(通用密码/互联网密码/密钥)与访问条件——
-
dyld 加载链:
otool -L Sample.app/Contents/MacOS/Sample | head # LC_LOAD_DYLIB 依赖 otool -l Sample.app/Contents/MacOS/Sample | grep -A4 LC_RPATH- 依赖清单与 RPATH → Dylib Hijacking 面(可写目录 + 缺失依赖组合)
- 注入面:DYLD_INSERT_LIBRARIES 受 hardened runtime 限制——entitlements 无
cs.allow-dyld-environment-variables时不生效;system 完整性保护下对系统路径注入无效 - 注入验证:环境变量 + 沙箱内试跑
DYLD_INSERT_LIBRARIES=/path/to/hook.dylib ./Sample,无效即回到静态路径([[re-ghidra]]),不硬注入
-
反调试与保护:
- 调试器检测:
PT_DENY_ATTACH(ptrace 请求在 attach 时返回拒绝)——先静态定位 ptrace 调用点([[re-ghidra]] / [[re-ida]]),patch 或绕过后再 attach - 签名校验:
SecStaticCodeCheckValidity/SecRequirementCheck类调用点——改签名或注入触发校验失败的典型点,逐点定位(坑 1) - 对抗面记录:代码签名校验、调试器检测、反注入(DYLD_INSERT_LIBRARIES 检查)三类各自调用点与触发条件
- 调试器检测:
-
证据核对(收尾):签名者/Team ID/entitlements 原文、TCC 依赖点、钥匙串条目用途、dyld 依赖清单——按 [[re-analyze/analysis-contract]] 入档;动态结论与静态清单对照(能力边界以动态行为为准,见 [[decision-tree]])
跨域联合
- [[re-format-macho]]:Mach-O 格式底座(LC_* 解析)
- [[re-ios]]:iOS 侧互补(越狱生态与 entitlements 差异)
- [[re-lldb]]:动态调试
- [[re-frida]]:动态插桩(macOS 桌面支持)
- [[re-sandbox]] / [[re-analyze/platform-tips]]:动态执行隔离(签名/行为观察在沙箱内进行)
- [[re-analyze/analysis-contract]]:签名/entitlements 信息按数据契约传递
- [[re-patching]]:PT_DENY_ATTACH 与签名校验点的持久化处理
- Swift 层分析(mangling/witness table)→ [[re-swift]]
常见坑与陷阱
- 签名校验多处触发:现象——patch 后运行即退;原因——加载/运行/更新多处校验;对策——逐点定位(步骤 6),先处理校验点再过逻辑
- Secure Enclave 密钥不可提取:现象——内存搜不到私钥;原因——硬件背书;对策——记录用途与访问条件,不找字节(见步骤 4)
- TCC 权限导致功能缺失:现象——目标功能灰掉;原因——TCC 未授权;对策——分析其请求逻辑而非绕过系统权限(红线)
- 公证检查离线不可复现:现象——离线环境 spctl 结果异常;原因——公证需要网络查询(含吊销状态);对策——用 codesign 本地签名信息替代,标注「公证状态未验证」
- hardened runtime 限制注入:现象——DYLD_INSERT_LIBRARIES 无效;原因——runtime 标志未含 allow-dyld 环境变量;对策——静态分析路径([[re-ghidra]]),不硬注入
- quarantine 干扰运行:现象——目标下载来源时崩溃/弹窗;原因——
com.apple.quarantine触发 Gatekeeper 检查;对策——xattr -dr com.apple.quarantine去除后重测(仅测试环境) - 嵌套签名漏处理:现象——patch 后运行时校验失败;原因——framework/helper/扩展各自独立签名,只重签主程序不够;对策——
codesign --deep或逐层重签,核对每层 CDHash - 决策分支(动态可行性判定/数据目标分级)见 [[decision-tree]];签名/注入/TCC 边界与反例见 [[gotchas]];全部在沙箱内执行([[re-analyze/platform-tips]] 最高原则)
评论
支持 Markdown