Suzu macOS Playground

Sandbox

模擬器沙盒

脫離關卡情境,把模擬器當自由工具玩。(v1:啟動鏈、Mach-O 解剖器、程式碼簽章;後續加 SIP/TCC 決策引擎。)

Mach-O 解剖器 M02

載入內建 arm64 樣本,或上傳你自己的二進位(檔案不離開瀏覽器)。

Mach-O 解剖器

模型邊界:本工具真解析 Mach-O 結構(對照本機 otool 驗證), 但不做 CMS 簽章驗證、不算 CodeDirectory CDHash(M03)。上傳的檔案全程留在你的瀏覽器,不會上傳。僅在自有/獲授權的樣本上練習(DESIGN.md §10)。

程式碼簽章實驗室 M03

SuperBlob/CodeDirectory 拆解、CDHash 真算(Web Crypto)、entitlement 雪崩。

程式碼簽章實驗室

模型邊界:CDHash 用瀏覽器 crypto.subtle 真算 SHA-256(雪崩無法造假,與 codesign 的 CandidateCDHashFull 一致)。 但 CMS 簽章鏈僅標 ad-hoc/有 CMS,不偽造 Apple 私鑰簽章驗證(DESIGN.md §5.6 / §10)。上傳檔案不離開瀏覽器。

Gatekeeper 評估 M04

下載通道 → quarantine 解碼 → 首次執行評估流程(簽章/公證/stapling/translocation)。

Gatekeeper 評估實驗室

① 下載通道

瀏覽器啟用 LSFileQuarantineEnabled,下載即附 com.apple.quarantine。

② com.apple.quarantine 解碼
flags
0x0081 · 未評估
時間
2020-04-05T17:58:24.000Z
agent
Safari
UUID
A1B2C3D4-0000-4000-8000-000000000001
旗標位
0x0001 LaunchServices 內部旗標(下載來源/類型相關)。0x0080 LaunchServices 內部旗標(常見於瀏覽器下載)。

UUID 是 LaunchServices QuarantineEventsV2 資料庫的鍵,存原始下載 URL/來源。

③ 情境(首次執行)

quarantine:有(由①通道決定)

判定擋下
  1. quarantine有 com.apple.quarantine 且為首次執行 → 觸發 Gatekeeper 評估。
  2. code signing簽章有效。
  3. notarization未經 Apple 公證(notarize)→「Apple 無法驗證其不含惡意軟體」。

被 Gatekeeper 擋下。

XProtect(簽章式惡意程式掃描,yara)在執行時比對;XProtect Remediator 週期掃描。 模型邊界:本流程為教學決策模型,非真實 syspolicyd 逐位元;quarantine flags 部分位元為 LaunchServices 內部、標為推測。驗證於 macOS 26.3.1(見章末真機卡)。

SIP / rootless M05

csr 位元面板、檔案存取兩閘(DAC→SIP)、SSV 開機 seal 與執行期 MAC 兩層。

SIP / rootless 實驗室

① csr-active-config 位元

csr = 0x0

System Integrity Protection status: enabled.

② 檔案存取(DAC → SIP,deny-overrides)

/System 帶 SF_RESTRICTED → SIP MAC 保護。

結果拒絕 (EPERM)
  1. DAC (POSIX)uid 0(root)滿足擁有者寫入權 → DAC 通過。注意:root 仍須經過 DAC,只是通常會過。
  2. SIP (MAC)對 restricted 路徑寫入、非授權的 rootless 二進位 → EPERM。連 root 都擋。

重點:DAC 過了(你是 root),但 SIP 這道獨立 MAC 閘擋下 → EPERM。「root 寫不進 /System」就是這個原因,不是 DAC。

③ SSV:開機期 seal vs 執行期 MAC(兩層獨立)

開機期 seal(authenticated-root / SSV)

開機時以 Merkle tree 的 root hash 驗整個系統卷快照的封印(seal)。磁碟上改一個 byte → 算出的 root hash 不符 → 無法開機(除非關掉 authenticated-root)。

與執行期 SIP 無關:可以 SIP 關、但 seal 仍開。

執行期 MAC(SIP / rootless)

系統執行中,MACF policy 擋對 SF_RESTRICTED 路徑的修改,連 uid 0 都擋。

與開機 seal 兩層獨立:本機實測即 SIP disabled 但 Authenticated Root enabled。

本機實測:SIP disabled 但 Authenticated Root enabled、Snapshot Sealed: Yes — 正是兩層獨立的活證據。

模型邊界:兩閘 deny-overrides 是 M09 六閘的預習教學模型,非核心 MACF 逐位元評估順序。csr 位元、restricted 旗標、SSV 雙層皆為實測(見章末真機卡);驗證於 macOS 26.3.1。

TCC 判定 M06

tccd 判定管線:audit token 歸屬 → 雙層查表 → csreq DR 釘選 → auth_value。

TCC 判定實驗室

情境

雙層 db:~/Library/.../TCC.db(user)先於 /Library/.../TCC.db(system)。此服務無 limited。

tccd 判定提示授權
  1. attribution用 audit token 歸屬到責任 client:com.example.app(非看 PID)。
  2. lookup雙層 tcc.db 都查無 (service, client) 紀錄 → 視為 unknown。
  3. prompt無紀錄 → 由系統跳出授權提示(若無 UI 環境則視為拒絕)。

查無紀錄 → 提示使用者授權(首次請求)。

試試:把「目前簽章符合 DR」關掉(模擬冒名/重簽)→ 既有 allowed 紀錄作廢、重新提示。把 audit token 關掉 → 連歸屬都失敗。

模型邊界:tccd 判定為**教學決策模型**(audit token 歸屬 → 雙層查表 → csreq DR → auth_value),非逐欄位實作。TCC.db 受 SIP/FDA 保護,本實驗室用合成資料。驗證於 macOS 26.3.1。

六道閘門決策 M09

POSIX→ACL→Sandbox→SIP→AMFI→TCC 的 deny-overrides 收斂視圖(教學抽象)。

六道閘門決策實驗室

write()
結果拒絕(EPERM)首先擋下:SIP
  1. 1POSIX (DAC)uid 0(root)滿足擁有者寫入 → DAC 過。
  2. 2ACL不適用此操作。
  3. 3Sandbox不適用此操作。
  4. 4SIP (rootless)/System 帶 SF_RESTRICTED,非 rootless 授權的二進位 → EPERM。連 root 都擋。
  5. 5AMFI / CodeSigning不適用此操作。
  6. 6TCC不適用此操作。

點每道閘的圖示可切換 pass/deny/n/a 自由探索。deny-overrides:任一道擋下即整體拒絕——通過一層不等於整體放行。

⚠ 模型邊界:這條「固定線性六閘」是教學模型,不是真實核心評估順序。真實上 AMFI/code signing 在 exec 與 page-in 時點觸發、TCC 是 userspace tccd 的 XPC 決策(非 kernel MAC 閘)、SIP/Sandbox 是 MACF policy 但無此嚴格全域線性序。root 也不短路 DAC。

SHA-256 雪崩 M00

改一個字元,看雜湊約一半 bit 翻轉(Web Crypto 真算)。

SHA-256 雪崩玩具

sha256(A):

sha256(B):

0 / 256 bit 不同(0%)改一個字元 → 約一半 bit 翻轉、毫無「接近」可言(雪崩)。

Web Crypto 真算(crypto.subtle.digest('SHA-256'))。這個「改一點 → 全變」是 macOS 敢用「雜湊一致=沒被動過」的基礎——直接接 M03 的 CDHash 雪崩。

持久化 triage M10

持久化向量參考表 + 背景項目特徵評分(防禦盤點)。

持久化盤點 + 偵測 triage

① 持久化向量參考
向量位置偵測訊號
LaunchAgents / Daemons/Library/Launch*、~/Library/LaunchAgentslaunchctl list 狀態、對 Launch* 目錄的 ES WRITE
SMAppService 註冊項app 捆綁的 daemon/agent/login itemBTM 紀錄、登入項面板、ES BTM_LAUNCH_ITEM_ADD
傳統 login items系統設定 登入項目BTM、系統設定面板
croncrontab、/etc/crontab、/var/atcrontab -l(多半為空,不可遺漏)
Configuration Profile / MDM.mobileconfig、MDM 推送profiles list / status、納管狀態異常
② 背景項目 triage:勾選觀察到的特徵
分數 0 · 看似正常(仍需對照基線)

重點:單一特徵(例如「label 看起來怪」)不是鐵證;高可疑來自特徵的組合。最強訊號是「某背景項目剛剛出現」(事件偵測),靜態盤點只告訴你「現在有什麼」。純教學評分,非真實掃描。

ES 事件流偵測 M14

合成 es_message 流 + predicate 命中 + mute 盲區。

ES 事件流 + 偵測規則

#typekindprocpathplat
1execAUTHTerminal/bin/zsh✓
2execAUTHzsh/tmp/.x/helper✗
3openNOTIFYhelper~/Library/LaunchAgents/com.x.plist✗
4btm_addNOTIFYhelpercom.x.agent✗
5mmapNOTIFYSafari/usr/lib/dyld✓
6execAUTHlaunchd/tmp/.x/helper✗
7openNOTIFYSpotlight~/Documents/a.pdf✓
命中 2 筆

AUTH(黃)事件可即時放行/拒絕(同步、有背壓);NOTIFY 只是事後通知。predicate 太鬆 → 雜訊(FP),太緊 → 漏報(FN)。mute / event-flooding 是真實盲區:被 mute 的程序事件根本不送達 client。純教學合成流。

SBPL sandbox 求值器 M07

SBPL sandbox 求值器

profile(由上而下,last-match-wins)
  1. (deny default) ← 起點
  2. #1 (allow file-read* /usr/lib) ← 命中
  3. #2 (allow file-read* ~/Library/Containers/com.x.app/Data)
  4. #3 (allow file-write* ~/Library/Containers/com.x.app/Data)
  5. #4 (allow mach-lookup com.apple.fonts)
  6. #5 (deny file-read* ~/Library/Containers/com.x.app/Data/secret)
要求一個操作
allow

命中規則 #1(allow file-read*)。last-match-wins:後面的規則覆寫前面的。

試 file-read-data ~/Library/Containers/com.x.app/Data/secret/key:先被 allow(Data 子樹)命中、再被後面更specific 的 deny(secret 子樹)覆寫 → 最終 deny。這就是 last-match-wins。SBPL 為教學子集,非完整語言。

XPC 呼叫方驗證 M08

XPC 呼叫方驗證(confused-deputy 根因 vs 防禦)

放行⚠ confused-deputy:對「錯的」低權對象放行了高權能力
  1. 高權 service 收到請求,需決定「該不該為這個呼叫方做事」。
  2. 用 PID 識別呼叫方 → 再拿 PID 去查身分/entitlement。
  3. PID 在 check 後、use 前被回收給另一個(低權)進程(TOCTOU 窗口)。
  4. service 對「原本那個 PID 的身分」放行,實際服務的卻是新進程 → 身分對錯對象。

根因:用 PID 認呼叫方(check 與 use 之間 PID 可被回收 → 身分對錯對象)。防禦一句話:驗 audit token,不驗 PID(含 pidversion,kernel 擔保)。本實驗室只示範類別與防禦,不含提權步驟。

APFS clone / COW M11

APFS clone / COW

檔案 A
共享 extentCOW 私有 extent邏輯大小 6 塊 · 實體佔用 6 塊(共享只算一次)

clonefile 複製=兩檔共享同一批 extent,不佔額外空間;改寫某塊才 copy-on-write 出新 extent(只有那塊變私有)。snapshot 同理:對「當下狀態」釘一份共享參照,之後的改動才分裂——M05 的 SSV seal 就是蓋在這種 snapshot 上。教學抽象,非真實 APFS 結構。

逆向工具選擇 M12

逆向工作台:選對工具

你想回答的問題
otool / dyld_info靜態
otool -l app · dyld_info -linked_dylibs app

靜態看「結構」、動態看「行為」。要拆 Mach-O 結構本身可直接用 M02 解剖器。

只在自有/獲授權的程式上分析。`dtrace` 受 SIP 限制(需調整 csr);`lldb`/`frida` attach 受 `get-task-allow` / 簽章與系統保護約束。

抽象記憶體模型 M13

抽象記憶體模型:UAF × PAC

空
指標 p:—

⚠ 此為教學抽象,不等於真實可利用性。UAF 的「形狀」是:釋放後指標沒清(dangling)→ 同一塊被重新配置(重用)→ 透過舊指標操作到新物件。mitigation(PAC/PPL/SPTM-TXM/kalloc_type/zone sequestering)的意義是抬高成本、把攻擊者逼向其他面——不是「不可能」。本模型不含任何 offset/gadget/payload/PoC。

橫向專題探索 M15

橫向專題探索

Network Extension

概念 NE 框架讓第三方以 system extension 形式做 content filter / DNS proxy / packet tunnel(取代舊 kext)。流量在使用者授權下被導向 extension 處理。

防禦/研究切入 偵測面:哪個 App 裝了 NE、攔了什麼流量、是否被濫用做隱蔽通道;NE 本身也受 entitlement 與使用者同意約束。

各專題給正確心智模型與延伸方向;可選修、掛在相關模組下。深入細節以官方 Platform Security 指南與各章為準。

啟動鏈驗證 M01

啟動鏈驗證模擬器

  1. 1BootROM

    以晶片內建信任根驗證 iBoot 的 Image4 manifest

  2. 2iBoot

    驗證 kernelcache 的量測雜湊與 manifest

  3. 3kernelcache

    載入並驗證 SEP firmware (sepOS)

  4. 4sepOS (SEP)

    安全啟動完成,移交控制權

✓ 信任鏈完整:四級全部驗證通過,安全啟動完成。

模型邊界:此為「每級驗下級」的概念演示,不偽造真實 Image4/CMS 簽章驗證。 真機驗證請見章末「真機操作卡」。