reverse-skills-max: initial public release (restored, redacted, hardened)
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
# macOS 应用逆向决策树与证据分级
|
||||
|
||||
## 场景决策树(入口 → 分支)
|
||||
|
||||
### 1. 目标形态分支(第一级)
|
||||
|
||||
```
|
||||
目标对象
|
||||
├─ .app bundle → 解包 Contents/,先读 Info.plist 与可执行文件
|
||||
├─ 单二进制(命令行工具/daemon)→ 直接 codesign/Mach-O 分析
|
||||
├─ dylib / framework → 依赖关系与导出面为主(otool -L / nm)
|
||||
├─ 安装包(pkg/dmg)→ 先解包提取载荷(pkgutil --expand)
|
||||
└─ 无签名/adhoc 签名 → 跳过签名面,直接静态分析
|
||||
```
|
||||
|
||||
### 2. 签名与分发状态分支(第二级,决定动态方案)
|
||||
|
||||
```
|
||||
codesign -dv 结果
|
||||
├─ Apple 开发者/分发签名
|
||||
│ ├─ 公证通过(spctl -a 过)→ 正规分发;仍按恶意面分析(公证≠安全)
|
||||
│ ├─ 公证失败/未公证 → Gatekeeper 会拦;本地仍可分析
|
||||
│ └─ Hardened Runtime 开 → 注入受限(见分支 3)
|
||||
├─ 第三方/自签 → 注入面大,但可能带自定义校验
|
||||
└─ 无签名 → 最容易动态,但注意系统会拦截运行(Gatekeeper/AMFI)
|
||||
```
|
||||
|
||||
### 3. 动态可行性分支(第三级)
|
||||
|
||||
```
|
||||
想动态执行(lldb attach / DYLD_INSERT_LIBRARIES / frida)
|
||||
├─ Hardened Runtime 且无 cs.allow-dyld-environment-variables
|
||||
│ └─ DYLD 注入不可行 → lldb attach 或静态分析([[re-ghidra]])
|
||||
├─ PT_DENY_ATTACH(ptrace 拦截)→ 先 patch 调用点([[re-patching]])再 attach
|
||||
├─ 沙箱开启 → 动态观察被限制在沙箱能力内(以 entitlements 为准)
|
||||
└─ 全无限制 → 标准 lldb / frida 流程(沙箱环境内,[[re-analyze/platform-tips]])
|
||||
```
|
||||
|
||||
### 4. 数据目标分支(第四级)
|
||||
|
||||
```
|
||||
要拿什么
|
||||
├─ 网络行为 → 抓包([[re-netcap]])+ 沙箱网络权限确认
|
||||
├─ 钥匙串条目 → 定位 SecItemCopyMatching 调用点,读用途与访问条件(可访问性/访问控制,不导出内容,红线)
|
||||
├─ Secure Enclave 密钥 → 确认 tokenID,记录用途(不可提取,不找字节)
|
||||
├─ 本地文件/偏好 → 容器路径(沙箱下在 ~/Library/Containers/)分析
|
||||
└─ 授权/注册逻辑 → 校验 API 调用点 → [[re-license]] 方法论
|
||||
```
|
||||
|
||||
## 证据分级表
|
||||
|
||||
| 级别 | 证据形态 | 示例 | 用途 |
|
||||
|---|---|---|---|
|
||||
| A 强 | 动态 + 静态交叉闭合 | 动态观察到网络外传,静态代码与 entitlements(network.client)一致 | 可下「恶意行为」结论 |
|
||||
| B 中 | 单侧完整证据链 | 静态完整还原调用链(含触发条件),未动态确认 | 可下「高可疑」 |
|
||||
| C 弱 | 静态特征 | 只有高危 entitlement(如 device.* 全开)+ 高混淆 | 只支持「需深入」 |
|
||||
| 反证 | 良性解释 | 权限声明与功能相符、行为与声明一致 | 记录并存档 |
|
||||
|
||||
- 能力边界以动态行为为准:entitlements 声明的能力 ≠ 实际使用的能力,两者都要记录
|
||||
- 签名/公证结论与恶意结论分开陈述(「分发状态」与「行为定性」是两个维度)
|
||||
|
||||
## 实现教训(内化)
|
||||
|
||||
- 先读 Info.plist + entitlements 再定动态方案——hardened runtime/沙箱直接决定注入与观察手段
|
||||
- 签名信息本地可查(codesign -d -r- / -dv),公证状态需网络——离线时用本地信息替代并标注
|
||||
- TCC 数据只读分析、不导出内容(红线);Full Disk Access 是读取前置,先确认授权
|
||||
- Secure Enclave 密钥记用途不找字节;钥匙串条目记录访问条件与访问点而非口令内容
|
||||
- 动态观察在沙箱内进行([[re-sandbox]],[[re-analyze/platform-tips]] 最高原则)
|
||||
- 证据链记录:签名者/Team ID、entitlements 原文、TCC 依赖点、dyld 依赖清单、动态行为对照
|
||||
|
||||
## 使用注意
|
||||
|
||||
- 沙箱内执行动态([[re-sandbox]]);TCC/钥匙串数据只读不导出(红线)
|
||||
- 结论按本表分级标注,签名/公证维度与行为维度分开陈述
|
||||
@@ -0,0 +1,44 @@
|
||||
# macOS 逆向方法论坑与边界
|
||||
|
||||
## 签名与公证组(最容易误判)
|
||||
|
||||
- **公证通过 ≠ 安全**:公证只证明 Apple 扫描过且无已知恶意签名,带公证的恶意/灰色应用存在——「公证状态」与「行为定性」分开陈述
|
||||
- **离线环境 spctl 结果不可信**:公证与吊销(OCSP)检查需要网络——离线时 `spctl -a` 可能失败或异常;用 codesign 本地签名信息替代,标注「公证未验证」
|
||||
- **codesign -dv 看不到完整要求**:designated requirement 需 `codesign -d -r-` 查看;只看默认输出会漏掉额外的 requirement 校验
|
||||
- **staple 与公证是两回事**:`xcrun stapler validate` 查的是票证是否随包(离线可验证);`spctl -a` 查整体评估(可能走网络)——一个失败不代表另一个也失败
|
||||
- **改签名会破坏原签名链**:patch 后必须重签(`codesign -s -` adhoc 或开发者证书),且嵌套签名(framework/helper)要逐层处理;重签后公证状态丢失是预期
|
||||
- **quarantine 干扰测试**:下载来源的 `com.apple.quarantine` 会触发 Gatekeeper 检查(崩溃/弹窗)——测试环境 `xattr -dr com.apple.quarantine` 去除后重测,注意这会改变来源证据
|
||||
|
||||
## 注入与动态组(hardened runtime 边界)
|
||||
|
||||
- **DYLD_INSERT_LIBRARIES 受 hardened runtime 限制**:无 `com.apple.security.cs.allow-dyld-environment-variables` entitlement 时注入不生效(Apple 签名 app 默认启用运行时保护)——别把「注入无效」当 bug,改走静态或 lldb
|
||||
- **PT_DENY_ATTACH 拒绝 attach**:目标调用 `ptrace(PT_DENY_ATTACH)` 后 attach 被拒——先静态定位 ptrace 调用点 patch 掉([[re-patching]])再动态
|
||||
- **AMFI/kext 级校验在用户态之外**:系统完整性保护(SIP)下对系统路径注入/挂载无效;内核级校验(kext 签名)不在本技能能力内
|
||||
- **沙箱内 attach 自身受限**:沙箱环境([[re-sandbox]])的进程权限继承会影响目标行为——观察结论标注环境差异
|
||||
- **Apple Silicon 差异**:arm64e 指针认证(PAC)影响 hook 与补丁(指针被签名校验);Rosetta 转译层下 x86_64 行为与原生不同——按目标架构分别验证
|
||||
|
||||
## TCC 与隐私组(红线边界)
|
||||
|
||||
- **TCC.db 自身受 TCC 保护**:无 Full Disk Access 时读 TCC.db 权限失败——先确认授权,不要试图绕过系统权限(红线)
|
||||
- **TCC 数据只读不导出**:授权记录属系统隐私,只读分析(谁请求了什么权限),不导出库内容(红线)
|
||||
- **TCC 记录随时间变化**:授权可被撤销/新增,快照不代表历史全貌——结论标注采样时间
|
||||
- **系统级 vs 用户级 TCC**:`/Library/Application Support/com.apple.TCC/`(系统)与 `~/Library/...`(用户)覆盖范围不同,按目标归属查对应库
|
||||
|
||||
## 钥匙串与 Secure Enclave 组
|
||||
|
||||
- **Secure Enclave 密钥不可提取**:`kSecAttrTokenIDSecureEnclave` 绑定的私钥永不离开 SE——内存/文件搜索必然无果,记录用途与访问条件即可(反例:拿不到字节 ≠ 分析失败)
|
||||
- **可访问性 ≠ 访问控制(别混称 ACL)**:`kSecAttrAccessible` 管设备状态(何时可读:非锁定/首次解锁/此设备);`kSecAttrAccessControl`/`SecAccessControl`(生物识别/密码门槛)才是访问控制;macOS 传统 ACL 另属 `SecAccess`/`kSecAttrAccess`——分析访问点(SecItemCopyMatching 参数)比导出内容更有价值
|
||||
- **钥匙串数据敏感**:条目内容属凭据,分析只读调用面,不导出口令内容(红线)
|
||||
- **钥匙串迁移**:系统升级/备份恢复后访问控制策略可能变化——历史环境复现时注意
|
||||
|
||||
## 反例与边界组
|
||||
|
||||
- **沙箱开启 ≠ 无网络面**:`com.apple.security.network.client` 存在时沙箱 app 照样外连——先看 entitlements 再判断行为面
|
||||
- **entitlements 缺失 ≠ 无能力**:动态行为可能超出静态声明(漏洞利用/未声明调用)——能力边界以动态行为为准
|
||||
- **签名者知名 ≠ 无恶意**:合法开发者账号可被窃取/滥用;以行为证据定性
|
||||
- **无签名 app 也能分析**:Gatekeeper 拦截的是运行入口,静态分析不受影响;运行前去除隔离属性并放沙箱
|
||||
|
||||
## 使用注意
|
||||
|
||||
- 动态执行在沙箱内([[re-sandbox]],[[re-analyze/platform-tips]] 最高原则)
|
||||
- TCC/钥匙串只读不导出(红线);结论按 [[decision-tree]] 分级标注,签名维度与行为维度分开
|
||||
Reference in New Issue
Block a user