Code signing là cơ chế đảm bảo chỉ code được Apple (hoặc developer được Apple cấp certificate) tin tưởng mới được phép chạy trên iOS. Entitlements là hệ thống capability-based security gắn liền với code signature.


Tại Sao Quan Trọng

  • Jailbreak phải bypass code signing để chạy unsigned code
  • Entitlements quyết định quyền hạn — nhiều exploit chains cần entitlement manipulation
  • Trust Cache injection là bước thiết yếu trong modern jailbreaks
  • TrollStore hoạt động nhờ CoreTrust bypass — hiểu cơ chế = hiểu bug

Kiến Trúc Code Signing Trên iOS

Tầng 1: AMFI (AppleMobileFileIntegrity)

AMFI là kernel extension (kext) kiểm tra code signature trước khi cho phép:

  • Mỗi page của code khi được load vào memory đều được verify hash
  • Process amfid (userspace daemon) hỗ trợ AMFI cho các checks phức tạp
  • AMFI quyết định: binary này có được phép chạy không, với entitlements nào

Flow kiểm tra:

exec() system call
  └─→ XNU kernel calls AMFI
       ├─→ Check Trust Cache (kernel-loaded list of trusted cd_hashes)
       │     └─→ Found? → ALLOW (no further checks needed)
       │
       ├─→ Send to amfid (userspace) for full validation
       │     ├─→ Verify certificate chain (up to Apple Root CA)
       │     ├─→ Verify CMS signature
       │     ├─→ Verify Code Directory hashes
       │     └─→ Return result to kernel
       │
       └─→ Decision: allow/deny execution + which entitlements to grant

Tầng 2: CoreTrust (iOS 12+)

CoreTrust là kernel extension thực hiện certificate validation trong kernel, thay vì phụ thuộc amfid:

  • Chạy trong KTRR-protected memory → khó patch hơn
  • Validate certificate chain cho App Store apps
  • Nếu CoreTrust approve → binary chạy với entitlements không bị filter

Tại sao Apple thêm CoreTrust:

  • Trước iOS 12: amfid chạy ở userspace → jailbreaks hook amfid để bypass code signing
  • CoreTrust đưa validation vào kernel → không thể hook từ userspace

Tầng 3: TXM (iOS 17+, A15+)

Trusted Execution Monitor thay thế cả AMFI và CoreTrust:

  • Chạy tại EL2 (hypervisor level) — cao hơn kernel
  • Kernel exploit alone không đủ để bypass TXM

Code Directory & cd_hash

Code Directory

struct CodeDirectory {
    uint32_t magic;        // CSMAGIC_CODEDIRECTORY (0xFADE0C02)
    uint32_t length;
    uint32_t version;
    uint32_t flags;
    uint32_t hashOffset;   // Offset to hash array
    uint32_t identOffset;  // Offset to identifier string
    uint32_t nSpecialSlots; // Number of special slots (before hash array)
    uint32_t nCodeSlots;   // Number of code page hashes
    uint64_t codeLimit;    // Limit of code pages
    uint8_t  hashSize;     // Hash output size (20 for SHA-1, 32 for SHA-256)
    uint8_t  hashType;     // Hash algorithm
    uint8_t  platform;     // Platform identifier
    uint8_t  pageSize;     // log2(page size in bytes), usually 12 (4KB) or 14 (16KB)
    // ... followed by hash slots
};

cd_hash = hash của Code Directory itself. Đây là unique identifier cho mỗi signed binary.

Special Slots:

Slot Nội dung
-1 Info.plist hash
-2 Requirements hash
-3 Resource Directory hash
-4 Application Specific (unused)
-5 Entitlements hash
-6 DER Entitlements hash
-7 Launch Constraints hash

Code Slots: Hash của mỗi page (thường 16KB trên iOS) của binary code. Khi page được loaded vào memory, AMFI verify hash này.


Entitlements

Entitlements là XML/DER plist embedded trong code signature, quy định capabilities:

Entitlements Quan Trọng

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN">
<plist version="1.0">
<dict>
    <!-- Cho phép debug (get-task-allow → tfp) -->
    <key>get-task-allow</key>
    <true/>

    <!-- Chạy không bị sandbox -->
    <key>com.apple.private.security.no-sandbox</key>
    <true/>

    <!-- Platform binary status (Apple binaries) -->
    <key>platform-application</key>
    <true/>

    <!-- Task-for-pid — đọc/ghi memory process khác -->
    <key>task_for_pid-allow</key>
    <true/>

    <!-- Root access -->
    <key>com.apple.private.persona-mgmt</key>
    <true/>

    <!-- Keychain access groups -->
    <key>keychain-access-groups</key>
    <array>
        <string>com.apple.token</string>
    </array>

    <!-- Sandbox container -->
    <key>com.apple.security.app-sandbox</key>
    <true/>

    <!-- Mach port lookup permissions -->
    <key>com.apple.security.exception.mach-lookup.global-name</key>
    <array>
        <string>com.apple.backboardd</string>
    </array>
</dict>
</plist>

Phân Loại Entitlements

Loại Ví dụ Ai được phép
Public com.apple.security.app-sandbox Mọi developer
Private com.apple.private.security.* Chỉ Apple binaries
Restricted task_for_pid-allow Chỉ platform binaries có đúng profile
Managed com.apple.developer.kernel.* Cần Apple approval

Platform binaries = binaries signed bởi Apple với Apple-internal certificate. Chúng có thể dùng private entitlements mà third-party apps không thể.


Trust Cache

Trust Cache là danh sách cd_hashes được tín nhiệm tự động bởi AMFI, không cần full certificate validation.

Các Loại Trust Cache

  1. Static Trust Cache: Embedded trong firmware, chứa hashes của tất cả system binaries
  2. Loadable Trust Cache: Có thể load thêm tại runtime (cần entitlement đặc biệt)
  3. Engineering Trust Cache: Cho development/debug builds

Trust Cache Structure

struct trust_cache_entry_v2 {
    uint8_t cd_hash[20];     // SHA-1 cd_hash
    uint8_t hash_type;       // 1 = SHA-1, 2 = SHA-256
    uint8_t flags;
    uint16_t constraint_category;
};

struct trust_cache_v2 {
    uint32_t version;        // 2
    uuid_t uuid;
    uint32_t entry_count;
    struct trust_cache_entry_v2 entries[];  // sorted for binary search
};

Trust Cache Injection (Jailbreak technique)

Modern jailbreaks inject trust cache entries để AMFI trust unsigned binaries:

  1. Gain kernel read/write
  2. Tìm loadedTrustCaches linked list trong kernel
  3. Allocate kernel memory cho new trust cache
  4. Thêm cd_hashes của jailbreak binaries
  5. Link vào loadedTrustCaches

Bypass Techniques Đã Biết

1. amfid Hook (Pre-iOS 12)

  • Jailbreak inject code vào amfid process
  • Hook hàm validation → luôn return “valid”
  • CoreTrust khắc phục bằng cách đưa validation vào kernel

2. TOCTOU Attack

  • Thay đổi cd_hash khi AMFI đang evaluate nhưng chưa xong
  • Race condition giữa “check hash” và “use hash”

3. CoreTrust Multiple Signer Bug (TrollStore)

  • Binary có nhiều signers
  • CoreTrust evaluate signer cuối nhưng apply policy từ signer đầu
  • Cho phép self-signed binary có App Store policy flags
  • Đây là cơ sở cho TrollStore — permanently install bất kỳ IPA nào

4. CoreTrust Root Certificate Bug

  • Craft certificate chain trick CoreTrust chấp nhận custom root CA
  • Cho phép sign binary với bất kỳ entitlements nào

5. Trust Cache Injection (Runtime)

  • Sau khi có kernel r/w, inject entries vào loaded trust caches
  • Binary với matching cd_hash sẽ bypass mọi signature checks

Thực Hành

# Extract entitlements từ system binary
codesign -d --entitlements :- /usr/libexec/mobileassetd

# Xem code signature details
codesign -dvvv /usr/bin/ls

# Trên jailbroken device, dump trust cache
# (cần kernel r/w tool)

# Dùng jtool2
jtool2 --ent /path/to/binary
jtool2 --sig /path/to/binary

Tài Nguyên