Siguza là independent security researcher chuyên về iOS/macOS kernel. Write-ups của Siguza nổi tiếng vì sâu, chi tiết, và viết dưới dạng narrative dễ follow. Đặc biệt mạnh về IOKit exploitation và kernel internals documentation.


Tại Sao Siguza Quan Trọng

  • v0rtex (2017): IOSurface exploit → tfp0 cho iOS 10.x — nền tảng cho nhiều jailbreaks
  • IOHIDeous (2017): macOS kernel 0-day — IOHIDFamily exploit, brilliant write-up
  • psychicpaper (2020): sandbox escape + entitlement bypass 0-day — cực kỳ elegant
  • cl0ver (2016): iOS 9 exploit — early work nhưng write-up rất instructive
  • Kernel research articles: PAC internals, APRR, PPL deep dives
  • Collaboration: Góp phần vào nhiều jailbreak projects

Exploits Theo Thời Gian

1. cl0ver (October 2016) — iOS 9.0-9.3.4

Field Detail
Target iOS 9.0-9.3.4
Goal tfp0 (kernel task port)
Technique OSUnserializeXML heap manipulation + UAF
Blog blog.siguza.net/cl0ver
Source github.com/Siguza/cl0ver
Exploit flow:
  1. OSUnserializeXML: kernel function parse XML plist data
     → Can allocate controlled data on kernel heap
     → Primary heap spraying primitive cho iOS exploitation
     
  2. Trigger UAF in target subsystem
  
  3. Spray OSUnserializeXML objects vào freed memory
     → Controlled data overlaps freed object
     
  4. Escalate to kernel task port
  
cl0ver's contribution:
  - Added tfp0 patch cho jailbreaks mà trước đó thiếu nó
  - Write-up giải thích OSUnserializeXML technique in detail
  - Foundation cho nhiều exploits sau này

Bài học: OSUnserializeXML = controlled kernel heap allocation primitive. Được dùng rộng rãi trước khi bị hardened (iOS 12+).

2. v0rtex (December 2017) — iOS 10.x

Field Detail
CVE CVE-2017-13861 (same bug class as async_wake)
Target iOS 10.0-10.3.3, mọi devices (32-bit + 64-bit)
Component IOSurfaceRootUserClient
Technique Mach port reference count bug → UAF → fake port → tfp0
Blog siguza.github.io/v0rtex
Source github.com/Siguza/v0rtex
Vulnerability:
  "The bug decreases the ref count on a user-supplied mach port
   by one too many"
  → Extra release → port refcount reaches 0 → freed
  → But userland still has valid handle → dangling reference
  → Classic port UAF

Exploitation (detailed):
  1. Allocate target port
  2. Trigger bug → extra port_release → port freed
  3. Userland still has mach_port_t handle to freed port
  
  4. Heap spray: allocate objects same size as ipc_port
     → OSUnserializeXML cho controlled data
     → Freed port memory replaced with fake port
  
  5. Fake port setup:
     ip_bits = IO_BITS_ACTIVE | IKOT_TASK
     ip_kobject → fake task struct
     fake task → map = kernel_map
  
  6. Use dangling handle → mach_vm_read/write → kernel r/w
  
  7. Post-exploitation:
     → Get root (modify ucred)
     → Unsandbox (null sandbox slot)
     → Patch amfid (bypass code signing)
     → tfp0 (patch host_special_port)

Tại sao quan trọng:

  • Support cả 32-bit và 64-bit → rất rộng device range
  • Write-up “Turning the IOSurface inside out” — one of the best exploitation tutorials
  • Được dùng bởi Meridian jailbreak (iOS 10.x)
  • So sánh với async_wake (Ian Beer): cùng bug class nhưng different exploitation approach

3. IOHIDeous (December 2017) — macOS ≤ 10.13.1

Field Detail
Target macOS ≤ 10.13.1 (High Sierra)
Component IOHIDFamily (HID — Human Interface Device drivers)
Type Kernel read/write from any unprivileged user
Blog blog.siguza.net/IOHIDeous
Source github.com/Siguza/IOHIDeous
IOHIDFamily:
  - Handles keyboard, mouse, touchscreen, etc.
  - IOHIDSystem, IOHIDResource, IOHIDDevice
  - Runs in kernel space
  - Complex codebase, historically buggy

Vulnerability:
  Race condition trong IOHIDResource/IOHIDSystem
  → Concurrent operations on shared state
  → Use-after-free

Exploitation:
  1. Trigger race condition → kernel UAF
  2. Reallocate freed memory with controlled data
     → IOSurface property spray cho heap control
  3. Type confusion → controlled kernel read/write
  
Write-up highlights:
  - Explains IOHIDFamily architecture in detail
  - Demonstrates how to find IOKit race conditions
  - Shows timing manipulation techniques
  - Published on New Year's Eve 2017 ("Happy New Year")

Bài học:

  • IOKit race conditions: IOKit drivers are inherently multi-threaded → rich source of bugs
  • IOHIDFamily specifically: complex, many handlers, shared state between UserClients
  • macOS exploitation → directly applicable concepts to iOS (same kernel)

4. psychicpaper (May 2020) — iOS < 13.5

Field Detail
CVE CVE-2020-9839
Target iOS < 13.5 beta 3
Type Sandbox escape + entitlement bypass (0-day at disclosure)
Name meaning “Psychic paper” (Doctor Who) — shows whatever credentials you need
Blog siguza.net/psychicpaper
Source github.com/Siguza/psychicpaper
Vulnerability:
  AMFI/amfid had FOUR different entitlement parsers that disagreed:

  1. amfid (userspace daemon) — parses entitlements as plist
  2. AMFI (kernel extension) — parses entitlements differently
  3. Sandbox — has its own entitlement check
  4. Provisioning profile validation — another parser

  Parser disagreement = confusion about what entitlements a binary has

Exploitation (brilliantly simple):
  Method 1: Invalid plist structure
    → One parser sees entitlement, another doesn't
    → Binary appears to have entitlements it shouldn't

  Method 2: Specific XML encoding tricks
    → CDATA sections, entity references, comments
    → Parsers interpret differently

  Method 3: Entitlement key encoding
    → Different parsers normalize keys differently
    → Same key appears different to different checkers

Result:
  → Binary gets ANY entitlements (private, restricted, platform)
  → Escape sandbox: claim com.apple.private.security.no-sandbox
  → Get task-for-pid: claim task_for_pid-allow
  → Become platform binary: claim platform-application
  → ALL without actual Apple certificate!

Tại sao đây là exploit elegant nhất:

  • Không cần memory corruption — pure logic bug
  • Không cần kernel exploit — works entirely in userspace
  • Deterministic — works 100% of the time, no races
  • Any entitlement — unrestricted capabilities
  • Simple — once understood, exploit code is trivial

Impact:

  • Dùng bởi unc0ver jailbreak (bypass code signing step)
  • TrollStore concept inspiration (entitlement/codesign bypass path)
  • Patched in iOS 13.5 beta 3 after Siguza disclosed

Research Articles Quan Trọng

APRR Deep Dive

Siguza documented APRR (Apple Page Region Protection) — hardware feature underpinning PPL:

  • How APRR remaps page permissions per-EL
  • How PPL uses APRR to protect page tables
  • Foundation knowledge cho PPL exploitation research

PAC Internals

Analysis of Apple’s PAC implementation:

  • How keys are managed
  • Which pointers are signed and with what context
  • Where PAC coverage has gaps

Kext Documentation

Siguza documented nhiều undocumented kernel extensions:

  • IOKit driver hierarchy
  • Hidden IOKit properties
  • Undocumented system calls

Siguza’s Approach — What To Learn

1. Deep Source Code Reading

Siguza đọc XNU source code thoroughly:
  - Không chỉ tìm bugs — hiểu entire subsystem
  - Document behavior mà Apple không document
  - Tìm inconsistencies giữa documentation và code
  → Bugs thường nằm ở gaps giữa intended và actual behavior

2. Finding Logic Bugs

psychicpaper = pure logic bug, no memory corruption
  - Tìm parser disagreements
  - Tìm inconsistent state handling
  - Tìm assumption mismatches giữa components
  → Often more reliable và powerful than memory corruption

3. IOKit Expertise

v0rtex, IOHIDeous: cả hai target IOKit drivers
  - Understand IOKit object lifecycle
  - Understand UserClient patterns
  - Understand race conditions in driver callbacks
  → IOKit = largest kernel attack surface

4. Write-Up Quality

Siguza's blog posts:
  - Narrative style: tell a story
  - Explain WHY decisions were made
  - Show failed approaches before successful one
  - Include enough detail to reproduce
  → Read these write-ups as tutorials, not just reports

Tài Nguyên — Đọc Theo Thứ Tự

  1. cl0ver (2016) — First exploit, introduces OSUnserializeXML technique
  2. v0rtex (2017) — IOSurface exploitation masterclass
  3. IOHIDeous (2017) — IOKit race condition hunting
  4. psychicpaper (2020) — Logic bug artistry
  5. Siguza’s GitHub — Source code cho tất cả exploits
  6. Siguza’s Blog — Tất cả research articles

PoC Deep Dive: v0rtex — Multi-Offset Fake Port

Vấn đề 3 offsets

// Zone allocation size 0xa8 (port size) trong chunks 0x3000:
// Page boundary alignment tạo 3 possible starting offsets
// Port có thể bắt đầu tại offset 0x0, 0x68, hoặc 0x28

// Fake port structure PHẢI valid ở CẢ 3 offsets
// → Mỗi field quan trọng phải nằm ở position
//   mà KHÔNG conflict với field khác ở offset khác

// v0rtex solution: encode identification info vào fields
// mà tồn tại ở mỗi offset:
dptr[j].ip_context = (dptr[j].ip_context & 0xffffffff) |
                     ((uint64_t)(0x10000000 | i) << 32);
dptr[j].ip_messages.port.pad = 0x20000000 | i;
dptr[j].ip_lock.pad = 0x30000000 | i;
// Upper nibble (0x1/0x2/0x3) reveals which offset is active
// Lower bits reveal page index

Shared Memory Trick

// After gaining kread: remap zone-allocated OSString into userland
// → Direct r/w access to kernel memory without message passing

mach_vm_address_t shmem_addr = 0;
vm_prot_t cur = 0, max = 0;
mach_vm_remap(mach_task_self(), &shmem_addr, DATA_SIZE, 0,
    VM_FLAGS_ANYWHERE | VM_FLAGS_RETURN_DATA_ADDR,
    fakeport,           // Fake task port → kernel_map
    kernel_obj_addr,    // Address of zone allocation
    false,              // Don't copy — share!
    &cur, &max,
    VM_INHERIT_NONE);

// shmem_addr giờ trỏ đến CÙNG physical memory với kernel object
// Write to shmem_addr = write to kernel memory
// No syscall needed — just pointer dereference!

Kernel Code Execution Without ROP

// v0rtex: fake IOUserClient với single gadget
// Thay vì ROP chain phức tạp, chỉ cần 1 gadget:

// ARM64 gadget: add x0, x0, #0x10; ret
// Located in kernelcache via pattern search

// Fake IOUserClient vtable:
fake_client->vtable = controlled_vtable;
// Override getExternalTrapForIndex:
controlled_vtable[TRAP_INDEX] = gadget_addr;
// gadget returns: x0 + 0x10 = pointer to IOExternalTrap
// IOExternalTrap contains function pointer + arguments

// When iokit_user_client_trap() called:
// → getExternalTrapForIndex() returns our IOExternalTrap
// → Kernel calls: trap->func(trap->p1, ..., trap->p6)
// → ALL arguments controlled by attacker!
// → Arbitrary kernel function calls with controlled args

PoC Deep Dive: IOHIDeous — Shared Memory Race

Obtaining IOHIDUserClient

// IOHIDUserClient normally held exclusively by WindowServer
// evOpenCalled flag prevents second open

// Method 1: Force logout
system("launchctl reboot logout");
// WindowServer exits → releases IOHIDUserClient
// Brief window to grab it before new WindowServer starts

// Method 2: Wait for shutdown
signal(SIGTERM, handler);  // macOS sends SIGTERM before shutdown
// In handler: grab IOHIDUserClient

// After obtaining client: have access to shared memory
// Shared memory contains EvOffsets structure
// This is the race target

Timing the Race

// Race window is very tight — need precise timing
// Thread 1: continuously flip evGlobalsOffset in shared memory
// Thread 2: trigger IOHIDSystem::initShmem()

// Detection: after initShmem(), check evg->version
// If evg->version == 0 → race won! evg points to our offset
// If evg->version != 0 → race lost, retry

// Success rate: ~1 in 1000 attempts
// But deterministic detection → no false positives
// Just retry until success

From evg to Kernel Read

// After race: evg points into kalloc_map (attacker-controlled offset)
// evg->eventFlags field is writable via HIDKeyboardGlobalModifiers

// Trick: corrupt mach message descriptor count
// 1. Send mach message with 0 descriptors
// 2. evg write sets msgh_descriptor_count = 1
// 3. Kernel reinterprets message body as port descriptor
// 4. Craft fake port/task in shared memory (known address)
// 5. Receive message → fake port inserted into task namespace
// 6. pid_for_task(fake_port) → reads arbitrary 32-bit value

PoC Deep Dive: psychicpaper — Parser Exploitation

Full Bypass Chain (iOS 12+)

// Step 1: Create binary with crafted entitlements
// Entitlements plist contains <!---><!--> trick
// amfid (CoreFoundation parser): sees empty dict → PASSES validation
// Kernel (IOKit parser): sees private entitlements → GRANTS capabilities

// Step 2: Binary now has:
//   com.apple.private.security.no-container → no sandbox
//   task_for_pid-allow → can get task ports
//   platform-application → treated as Apple binary

// Step 3 (iOS 11+): Platform check prevents direct mach port use
// Solution: exception port proxy technique

// Spawn Apple binary (e.g., cfprefsd) with:
posix_spawnattr_t attr;
posix_spawnattr_init(&attr);
// Set exception port = our_port (catch crashes)
// Set bootstrap port = our_port (proxy launchd)
// Spawn suspended, then resume

// Binary starts → we intercept bootstrap lookups
// Binary asks for com.apple.xxx service → we return our port
// Binary sends privileged message to "service" → we receive it
// → We can impersonate any mach service to the platform binary!

// Step 4: Use platform binary as "signing oracle"
// Send messages THROUGH platform binary to privileged services
// Platform binary's identity used for authorization checks
// → Full platform-level access from unprivileged app