SlideShare a Scribd company logo
KeenLab iOS Jailbreak Internals:
Liang Chen (@chenliang0817)
Userland Read-Only Memory can be Dangerous
About me
• Security researcher & team leader at Tencent Keen Security Lab
• Browser vulnerability research (Safari, Chrome, IE etc.)
• Apple vulnerability research (Sandbox, Kernel, etc.)
Agenda
• Operating system memory protection overview
• iOS DMA features
• Implementation of iOS IOMMU protection
• iOS GPU notification mechanism
• The vulnerabilities
• Exploitation & Demo
• Conclusion
PART I: Operating system memory protection overview
Memory protection
• Modern OS implements memory protection at hardware
level
• Mitigate known attacks, makes exploitation harder
• Different levels
• Translation Block Entry properties at MMU (Memory Management
Unit) level
• NX, PXN, AP, etc.
• KPP, AMCC, etc.
Userland read-only memory mappings
• Old-school approach to protect userland memory
• Easy but effective
• Scenarios on iOS
• Executable memory is read-only, preventing from overwriting the code at early
stage of exploitation
• Sharing memory between processes
• Sharing memory between kernel and process
Userland memory sharing in iOS
• Make inter-process or user-to-kernel
communication more efficient
• Low privileged process only needs a
read-only mapping of the same physical
memory
• So that server process/kernel can make
sure the content of the memory is trustable
• Eliminating specific security consideration
(e.g boundary check, TOCTTOU issues, etc)
• Implementation
• Access protection bits at Translation Block
Entry
• System MMU can identify those bits
Breaking the trust boundary
• By remapping read-only memory as writable
• But without marking them COW(copy-on-write)
• Can lead to privilege escalation
• Sandbox bypass in process-to-process memory sharing scenario
• Or even kernel code execution in process-to-kernel memory sharing
scenario
Breaking the trust boundary
• How iOS prevent writable
remapping on read-only memory?
• By preventing users from setting
new_prot higher than max_prot in
vm_map_protect
• The only exception is to mark the
remapping as COW
Breaking the trust boundary
• Historical issues
• Read-only SharedMemory descriptors on Android are writable:
https://bugs.chromium.org/p/project-zero/issues/detail?id=1449
• Did the Man With No Name Feel Insecure?:
https://googleprojectzero.blogspot.com/2014/10/did-man-with-no-
name-feel-insecure.html
• On iOS, there is no such known issues
• Seems everything is fine up till now
PART II: iOS DMA features
DMA overview
• DMA(direct-memory-access) technology enables the ability
for fast data transfer between the host and peripheral
devices
• With stronger and more abundant features provided by modern
peripheral devices attached to the mobile devices
• DMA transfer does NOT involve CPU
• So access protection bits on Translation Block Entry is ignored
DMA overview
• DMA transfer use physical address, and no memory
protection any more?
• Not the case, why?
• Modern phones are 64-bit, while many of their peripheral
devices remain 32-bit
• Address translation is needed
• And, we need memory protection for DMA transfer also
IOMMU(input/output memory management unit) and DART
• IOMMU is introduced to connect a direct-memory-access capable
I/O bus to the main memory
• There is need to map 64bit physical addresses into 32bit device
addresses
• For 64bit iOS devices, DART(Device Address Resolution Table) is
responsible to perform the address translation
Host-to-device DMA and device-to-host DMA
• For 64bit iOS devices, peripheral devices such as Broadcom WIFI module,
implement DMA transfers
• Gal Beniamini of Google Project Zero team leverages DMA features on iOS to
achieve firmware to host attack in middle 2017
• Compromised WIFI firmware is able to mutate writable DMA mapping
• Kernel trust that DMA mapping , lack of boundary check, leading to code execution
• Limitation of device-to-host attack
• Short distance
• Have to compromise WIFI stack first (Attacker and victim in same WIFI environment)
Long distance remote attack?
• Browser exploit + kernel privilege escalation
• By using DMA related vulnerabilities? What?
• Looks like a crazy idea
• DMA features are kind of low level implementation which is mostly
performed at kernel level.
• Such feature is never exposed directly to the userland.
• Is there any DMA attack surface in userland?
Indirect userland DMA
• There might be indirect DMA interface at userland
• Hardware JPEG engine to accelerate the encoding and
decoding process
• IOSurface transform is done by hardware device
• Etc.
IOSurface and IOSurfaceAccelerator
• IOSurface object represents a
userland buffer which is shared with
the kernel.
• Users can create IOSurface by
providing existing userland memory
address and its length
• Kernel creates IOMemoryDescriptor
and map userland memory to kernel
• Option kIODirectionOut is set for read-only
userland mappings
• Option kIODirectionOut and kIODirectionIn
are both set for read-write userland
mappings
IOSurface and IOSurfaceAccelerator
• IOSurfaceAccelerator is a userland framework on iOS platform only
• Two most important interfaces: IOSurfaceAcceleratorCreate and
IOSurfaceAcceleratorTransferSurface
• IOSurfaceAcceleratorCreate is responsible for creating a IOKit userclient connection representing an
IOSurfaceAcceleratorClient kernel object
• IOSurfaceAcceleratorTransferSurface takes two IOSurface handles, one for source and another for
destination, along with a dictionary supplying the transferring parameters
• Transfer the surface from src to dst, with color filtering, border filling etc, processed directly by the kernel
• Typical scenario of using IOSurfaceAccelerator: Screen Snapshot
Low level implementation of IOSurfaceAccelerator
• AppleM2ScalerCSC driver architecture
• IOSurfaceAcceleratorClient talks to
AppleM2ScalerCSC which is the core driver
• Low level driver object AppleM2ScalerCSCHal is for
handling device dependent stuff and provide device
independent interface to AppleM2ScalerCSCDriver
• AppleM2ScalerCSCHal creates
ColorConversionControl, SrcDestCfgControl,
ScalingControl, DitherControl, ColorManager,etc.
• AppleM2ScalerCSCHal maps a device memory into
kernel virtual space, representing the device’s key
registers.
IOSurfaceAcceleratorTransferSurface Internals
• IOSurfaceAcceleratorTransferSurface
will reach kernel function
IOSurfaceAcceleratorClient::user_transf
orm_surface
• Overall procedure of
user_transform_surface
• We are interested in the DMA mapping part
Parameter
validation
Obtain Src/Dst
IOSurface Address
Map IOSurface
buffer via DMA
Obtain mapped
address of Src/Dst
buffer
Set device
registers
Start the Scaler
Wait for interrupt
from the device
Finish
Map IOSurface buffer via DMA
• An IODMACommand object is
created with a special IOMapper
• m_IOMapper is an instance of
IODARTMapper which is independent
between devices
• Then the IOSurface memory
descriptor is bond to the
IODMACommand
Obtain the IOSurface address in IOSpace
• After the mapping, the next step
is to obtain the device memory
visible to IOMMU
• v33 here represents the 32bit address
in IOSpace
SrcDestCfgControl object
• SrcDestCfgControl object is used to specify
the address of src and dst address of
IOSurface in IOSpace
• After IOSurface’s IOSpace address is decided,
SrcDestCfgControl object is set
• v4 represents the kernel virtual mapping of
Scaler’s device memory
• Other registers relating to transform
parameters are handling in a similar manner
Start the scaler
• After all registers are set, the scaler is
started by setting the control register
• (deviceAddrVirtual + 128) is the “powerOn”
register of the scaler
• The scaler device starts its work
immediately
• When scaler finished the processing, an
interrupt will be issued and the event will
be signaled.
• That indicates the source IOSurface has been
transferred to the destination IOSurface.
• In the case we don’t specify any transform
options in the parameter, scaler simply per-
formed a memory copy via DMA transfer.
PART III: The implementation of IOMMU memory protection
Page table specification of IOMMU
• Unlike CPU MMU, page table specification
of IOMMU is not well standardized
• On iOS DART is responsible for IOMMU
page table management
• So by reversing iOS DART code, we can
understand the page table better
• Gal Beniamini has reversed the logic in
DART module and explained the page
table specification on 64bit iOS devices.
• Similar as CPU MMU page table
Referenced from:
https://googleprojectzero.blogspot.com/2017/10/ov
er-air-vol-2-pt-3-exploiting-wi-fi.html
IOMMU memory protection
• In Gal’s blog he didn’t mention whether the IOMMU supports
memory protection or not.
• It remains unclear if IOMMU memory protection exists or not
• However we can get the answer by reversing DART implementation in iOS 11
IOMMU memory protection
• The entry point for mapping memory
in IOSpace:
IODARTMapper::iovmMapMemory
• mapOptions parameter has included the
memory’s protection bits in virtual space
• The last 3 bits in mapOptions is translated
to direction value
• Read-only mapping has direction value
2
• Write-only mapping has value 1
• Read/write mapping has the value 3.
IOMMU memory protection
• The direction variable flows and
finally reached the function in
AppleS5L8960XDART, the low level
implementation of DART
• On a device later than iPhone 5s, the
apSupport mask is always 0x180
• Indicating the 8th and 9th bit in the TTE
are AP related bits
IOMMU memory protection
• Finally we got the access protection specification in TTE
• IOMMU supports memory protection
UNK BlockAddr valid
64 36 12 2
AP
89
AP meaning
00 Read-write
01 Read-only
10 Write-only
PART IV: GPU notification mechanism
Apple Graphics workflow
• On iPhone7 device, Apple Graphics provides with 128 channels for
concurrent processing.
• Three channel categories: CL channel, GL channel and TA channel
• Kernel wraps drawing instructions from userland and put them
into those channels
• Kernel then waits for the GPU to finish processing
• A well-designed notification mechanism is necessary for GPU to
synchronize the status of instruction processing
• Considering the concurrency of GPU handling
GPU notification architecture
• GPU task owns a stampArray representing
the stamp status of each channel
• The memory is a representation of uint32
array of 128 elements, each showing the
last complete instruction’s stamp of that
channel
• stampArray memory is mapped to kernel
and userland also (userland mapping is
read-only)
Stamp address array
• Kernel also maintains a stamp
address array of 128 elements
• Each element represents the virtual
address of that mapped stamp status
kernel address
IOAccelEvent object
• The stamp value of each channel is
incremental upon each of the instruction
processing completeness.
• IOAccelEvent represents the expected
stamp value in specific channel of one
or one group of drawing instructions
• One IOAccelEvent contains 8 sub events
• One sub event is 8 bytes in size
• Lower 4 bytes represents the channel index
• Higher 4 bytes represents the expected
stamp value of that drawing instruction
IOAccelEvent object
• By comparing the expectStamp value
with the value in the stamp array,
kernel can decide whether an
IOAccelEvent has been finished or not
IOAccelEvent object
• To improve performance, some
IOAccelEvent objects are mapped
into userland as read-only
• Make userland apps understand the
status of an event without asking the
kernel
PART V: The vulnerabilities
1. The DMA mapping vulnerability
• On iOS 10 and early beta of iOS 11, the mapOptions of
the virtual memory is simply ignored by the DART mapper
mapOptions is not used in
iovmAlloc
1. The DMA mapping vulnerability
• Later on, AppleS5L8960XDART::setL3TTE is reached, which 8th and 9th
bit of the TTE set to 0
• Indicating read-write mapping
UNK BlockAddr valid
64 36 12 2
AP
89
AP meaning
00 Read-write
01 Read-only
10 Write-only
8th and 9th bit set to 0
2. The out-of-bound write vulnerability
• IOAccelResource is similar in functionality as
IOSurface object, except that
IOAccelResource represents a shared
userland buffer which would be mapped into
GPU task.
• Like IOSurface, we can create
IOAccelResource by specifying an existing
userland buffer, by specifying the size, or
even by providing an existing IOSurface
handle.
• As part of IOAccelResource initialization
process, a shared mapping will be created
2. The out-of-bound write vulnerability
• What is IOAccelClientSharedRO?
• Contains IOAccelEvent array with 4 elements
• With resource id and type information
• m_IOAccelClientSharedRO is mapped to
both userland and the kernel
• userland mapping is read-only
• The userland mapped address is
returned to user
Read-only mapping
2. The out-of-bound write vulnerability
• Userland application can delete the
IOAccelResource by calling method
1 of IOAccelSharedUserClient
• IOAccelEventMachineFast2::testEve
nt will be called if the
IOAccelResource is created with
specific option
2. The out-of-bound write vulnerability
• In IOAccelEventMachineFast2::testEvent,
it checks whether the IOAccelEvent in
IOAccelClientSharedRO has been
completed
• No boundary check is performed at
channel index
• Since the IOAccelEvent is created and managed
only by the kernel while the userland mapping is
read-only
• Kernel trust the index value
2. The out-of-bound write vulnerability
• However with the DMA mapping bug, the trust boundary is broken
• Channel index and expected stamp value can be mutated by the userland app
• Both m_inlineArrayA0x18Struct and m_stampAddressArray are arrays of 128
elements.
• With m_channelIndex changed to arbitrary value, we caused out-of-boundary read
on m_stampAddressArray, and out-of-boundary write on m_inlineArrayA0x18Struct
PART VI: Exploitation & Demo
Exploitability
• Exploitability of those two bugs depend on whether we can control
the content for for both m_inlineArrayA0x18Struct and
m_stampAddressArray with the same out-of-bound index
• Then we can perform arbitrary memory read and write
• Looks like a hard task, because
• Both arrays are created in very early stage of iOS boot process, impossible to
put controlled contents right after them
• Size of element of each array is different. The larger index we specify, the
longer span in address of the referenced array element.
Craft memory layout
• Some facts:
• Kernel heap memory starts at a relatively low address
• Heap grows linearly with more and more memory allocated
• The start address of heap differs within tens of megabytes upon each boot
• Addresses of m_inlineArrayA0x18Struct and m_stampAddressArray are closed with each
other
• It means
• We can use a relative large channel index
• Along with kernel spray techniques, we might be able to ensure content of the OOB value
of m_inlineArrayA0x18Struct[channelIndex] and m_stampAddressArray[channelIndex]
are both under our control
Feasibility of memory layouting
• Kernel heap spray
• Quite some known techniques: e.g. sending large OOL message
• On iPhone 7, we can spray around 350MB kernel memory within
container sandbox app
• After m_inlineArrayA0x18Struct and m_stampAddressArray are
created, around 50MB extra kernel memory is allocated (As a part of
boot process)
Feasibility of memory layouting
• m_inlineArrayA0x18Struct element size is 24 bytes
• m_stampAddressArray element size is 8 bytes
• So if:
• index ∗ 24 < 350MB + 50MB , and
• index ∗ 8 > 50MB
• With index value in range of [0x640000, 0x10AAAAA], the out-of-bound elements
of both m_inlineArrayA0x18Struct and
m_stampAddressArray arrays can be fallen into our sprayed data
Arbitrary read and write?
• Arbitrary memory read is not a problem
• Because m_stampAddressArray element size is 8 bytes
• You can reach every dword within each page (higher 4 bytes of a QWORD cannot
be read though, but usually not necessary)
• Arbitrary memory write is more tricky
• Because m_inlineArrayA0x18Struct element size is 24 bytes, only one of its
DWORD can be written
Write at specific offset within a page
• Thanks to mechanism of XNU zone allocator
• the base address of m_inlineArrayA0x18Struct array is always at offset 0xF0 or 0x20F0
of a 0x4000 page
• Similarly, m_stampAddressArray is allocated with 0x200, falling in kalloc.512 zone. The
address offset within a 0x4000 page can be all values dividable by 0x200.
• So how to write arbitrary page offset by OOB write on m_inlineArrayA0x18Struct
array
• For example, a vtable is usually at offset 0 of the page if the object size is large enough
• The problem can be solved by congruence theory in mathematics
Read at arbitrary offset within a page
• Because:
• 0xc000 ≡ 0(mod0x4000)
• So with arbitrary integer n:
• n ∗ 0x800 ∗ 24 ≡ 0(mod0x4000)
• With 0x4000 / 24 * 0xF0 / 16 = 0x27f6, we can get:
• 0xF0 + 0x27f6 ∗ 24 + n ∗ 0x800 ∗ 24 ≡ 0(mod0x4000)
• With arbitrary integer n, we can out-of-bound write to the first
8 bytes in a sprayed page given:
• index = 0x27f6 + n ∗ 0x800
• To reach arbitrary offset within page, with m be the offset of
the page, we just ensure index is:
• index = 0x27f6 + 0x2ab ∗ m/8 + n ∗ 0x800
Choose the best channelIndex value
• With index = 0x27f6 + 0x2ab ∗ m/8 + n ∗ 0x800 , plus the range of
[0x640000, 0x10AAAAA]
• We choose the value of 0x9e6185 (can be other values as well)
• This value can reach offset 0x568 of a 0x4000 page by writing
m_inlineArrayA0x18Struct out-of-bound
• And reach offset 0x28/0x228/0x448, etc… of a 0x4000 page by reading
m_stampAddressArray out-of-bound
First attempt to exploit
• Spray around 350MB OOL messages of
size 0x2000
• Make sure
• Offset 0x28, 0x228,0x428,0x628… of each
page is filled with a guessed value(GA), in
real case we use 0xffffffe00a5d4030
• Each QWORD in page offset 0x30 is filled
with a value to read(VR)
• Each QWORD in page offset 0x568(AW field)
is filled with a specific value(make sure VR is
different with this value)
KASLR bypass
• By first attempt of the exploit, we
then receive the OOL message to
see which message’s AW field has
been changed
• We can then obtain the
information of:
• Which OOL message is allocated at
slot C
• Which OOL message is in GA
address(slot B)
KASLR bypass
• Fill slot B with AGXGLContext
object(also in kalloc.8192)
• Change GA value to
0xffffffe00a5d4000(original GA-0x30,
base address of slot B, vtable of
AGXGLContext object)
• Exploit the OOB bug again
• And we get the lower 4 bytes of
AGXGLContext vtable by receiving OOL
message in slot C
Code execution
• To get code execution, we need to free the
slot C, and fill in an object where its 0x568
offset represents important object
• The offset 0x568 in AGXGLContext is set to
AGXAccelerator object
• Calling AGXGLContext method 0 can reach
the function IOAccelGLContext2::
context_finish
• With its 0x568 field modified to arbitrary
value , we get PC control
Overall exploit workflow
Create IOAccelResource
Obtain IOAccelEvent read-
only buffer
Trigger bug 1, modify
m_channelIndex to
0x9e6185
Prepare initial memory
layout, trigger bug 2, obtain
index of slot B and C
Prepare memory layout for KASLR
bypass, trigger bug 2, obtain vptr of
AGXGLContext
Prepare memory layout for code
execution, trigger bug 2, overwrite
AGXAccelerator pointer in
AGXGLContext
Prepare ROP, call method 0 of
AGXGLContext, obtain tfp0, post
exploitation to jailbreak
Finish
Post exploitation
• By running a piece of ROP gadget, we obtain task_for_pid 0
• Still far away from the jailbreak
• Break AMFI
• Rootfs remount
• KPP/AMCC bypass
• Etc.
• Most of those have public write-ups
• Not a scope of the talk
Demo
Conclusion
• With the first release of iOS 11, Apple fixed the DMA mapping bug
• By adding implementation of read-only mapping at its DART code
• The other OOB write bug, remains unfixed
• A good example of how security can be broken by bad implementation with good
hardware design
• We make possible a complex exploit chain to achieve jailbreak within userland applications
• Should kernel trust the userland read-only mappings?
• Last but not the least, userland read-only memory can be dangerous
Thanks & Questions

More Related Content

PPT
Il giardino segreto - Alice Barnabà
PDF
10 англ карп'юк_тетр_9год_2010_укр
PPT
The Colonies Power point
PPTX
La trinchera
PDF
CNIT 128 2. Analyzing iOS Applications (Part 2)
KEY
Jailbreaking iOS
PDF
Recon2016 shooting the_osx_el_capitan_kernel_like_a_sniper_chen_he
PDF
CodeMash 2.0.1.5 - Practical iOS App Attack & Defense
Il giardino segreto - Alice Barnabà
10 англ карп'юк_тетр_9год_2010_укр
The Colonies Power point
La trinchera
CNIT 128 2. Analyzing iOS Applications (Part 2)
Jailbreaking iOS
Recon2016 shooting the_osx_el_capitan_kernel_like_a_sniper_chen_he
CodeMash 2.0.1.5 - Practical iOS App Attack & Defense

Similar to Us 18-chen-keen lab-ios-jailbreak-internals (20)

PDF
ASFWS 2012 - Audit d’applications iOS par Julien Bachmann
PDF
How to enable AMD IOMMU in coreboot?
PDF
Ruxcon 2014 - Stefan Esser - iOS8 Containers, Sandboxes and Entitlements
PDF
Are Your Mobile Apps Secure? (Part I)
PDF
Mobile Device-Architecture
PPTX
Armadillos - or how to bypass code readout protection on microcontrollers
PDF
Behind The Code // by Exness
PDF
Synack at AppSec California with Patrick Wardle
PDF
BlackHat USA 2011 - Stefan Esser - iOS Kernel Exploitation
PDF
[HES2013] Hacking apple accessories to pown iDevices – Wake up Neo! Your phon...
PPTX
Ярослав Воронцов — Пара слов о mobile security.
PPT
Embabded system security for feuture .ppt
PDF
iPhone Data Protection in Depth
PDF
Racing the Dark: A New TOCTTOU Story from Apple's Core
PDF
iOS Application Penetation Test
PDF
Find your own iOS kernel bug
PPTX
INTERFACING2 [Autosaved] interfacing in Computer system
PDF
44CON 2014 - Stupid PCIe Tricks, Joe Fitzpatrick
PDF
iOS secure app development
PDF
Ruxmon April 2014 - Introduction to iOS Penetration Testing
ASFWS 2012 - Audit d’applications iOS par Julien Bachmann
How to enable AMD IOMMU in coreboot?
Ruxcon 2014 - Stefan Esser - iOS8 Containers, Sandboxes and Entitlements
Are Your Mobile Apps Secure? (Part I)
Mobile Device-Architecture
Armadillos - or how to bypass code readout protection on microcontrollers
Behind The Code // by Exness
Synack at AppSec California with Patrick Wardle
BlackHat USA 2011 - Stefan Esser - iOS Kernel Exploitation
[HES2013] Hacking apple accessories to pown iDevices – Wake up Neo! Your phon...
Ярослав Воронцов — Пара слов о mobile security.
Embabded system security for feuture .ppt
iPhone Data Protection in Depth
Racing the Dark: A New TOCTTOU Story from Apple's Core
iOS Application Penetation Test
Find your own iOS kernel bug
INTERFACING2 [Autosaved] interfacing in Computer system
44CON 2014 - Stupid PCIe Tricks, Joe Fitzpatrick
iOS secure app development
Ruxmon April 2014 - Introduction to iOS Penetration Testing
Ad

Recently uploaded (20)

PPTX
PA Analog/Digital System: The Backbone of Modern Surveillance and Communication
PDF
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
PDF
Electronic commerce courselecture one. Pdf
PDF
Spectral efficient network and resource selection model in 5G networks
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Empathic Computing: Creating Shared Understanding
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PDF
Review of recent advances in non-invasive hemoglobin estimation
PDF
Modernizing your data center with Dell and AMD
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PPTX
Big Data Technologies - Introduction.pptx
PDF
Encapsulation theory and applications.pdf
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
Network Security Unit 5.pdf for BCA BBA.
PA Analog/Digital System: The Backbone of Modern Surveillance and Communication
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
Electronic commerce courselecture one. Pdf
Spectral efficient network and resource selection model in 5G networks
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Chapter 3 Spatial Domain Image Processing.pdf
Empathic Computing: Creating Shared Understanding
Understanding_Digital_Forensics_Presentation.pptx
Review of recent advances in non-invasive hemoglobin estimation
Modernizing your data center with Dell and AMD
Per capita expenditure prediction using model stacking based on satellite ima...
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
20250228 LYD VKU AI Blended-Learning.pptx
Big Data Technologies - Introduction.pptx
Encapsulation theory and applications.pdf
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
Advanced methodologies resolving dimensionality complications for autism neur...
Network Security Unit 5.pdf for BCA BBA.
Ad

Us 18-chen-keen lab-ios-jailbreak-internals

  • 1. KeenLab iOS Jailbreak Internals: Liang Chen (@chenliang0817) Userland Read-Only Memory can be Dangerous
  • 2. About me • Security researcher & team leader at Tencent Keen Security Lab • Browser vulnerability research (Safari, Chrome, IE etc.) • Apple vulnerability research (Sandbox, Kernel, etc.)
  • 3. Agenda • Operating system memory protection overview • iOS DMA features • Implementation of iOS IOMMU protection • iOS GPU notification mechanism • The vulnerabilities • Exploitation & Demo • Conclusion
  • 4. PART I: Operating system memory protection overview
  • 5. Memory protection • Modern OS implements memory protection at hardware level • Mitigate known attacks, makes exploitation harder • Different levels • Translation Block Entry properties at MMU (Memory Management Unit) level • NX, PXN, AP, etc. • KPP, AMCC, etc.
  • 6. Userland read-only memory mappings • Old-school approach to protect userland memory • Easy but effective • Scenarios on iOS • Executable memory is read-only, preventing from overwriting the code at early stage of exploitation • Sharing memory between processes • Sharing memory between kernel and process
  • 7. Userland memory sharing in iOS • Make inter-process or user-to-kernel communication more efficient • Low privileged process only needs a read-only mapping of the same physical memory • So that server process/kernel can make sure the content of the memory is trustable • Eliminating specific security consideration (e.g boundary check, TOCTTOU issues, etc) • Implementation • Access protection bits at Translation Block Entry • System MMU can identify those bits
  • 8. Breaking the trust boundary • By remapping read-only memory as writable • But without marking them COW(copy-on-write) • Can lead to privilege escalation • Sandbox bypass in process-to-process memory sharing scenario • Or even kernel code execution in process-to-kernel memory sharing scenario
  • 9. Breaking the trust boundary • How iOS prevent writable remapping on read-only memory? • By preventing users from setting new_prot higher than max_prot in vm_map_protect • The only exception is to mark the remapping as COW
  • 10. Breaking the trust boundary • Historical issues • Read-only SharedMemory descriptors on Android are writable: https://bugs.chromium.org/p/project-zero/issues/detail?id=1449 • Did the Man With No Name Feel Insecure?: https://googleprojectzero.blogspot.com/2014/10/did-man-with-no- name-feel-insecure.html • On iOS, there is no such known issues • Seems everything is fine up till now
  • 11. PART II: iOS DMA features
  • 12. DMA overview • DMA(direct-memory-access) technology enables the ability for fast data transfer between the host and peripheral devices • With stronger and more abundant features provided by modern peripheral devices attached to the mobile devices • DMA transfer does NOT involve CPU • So access protection bits on Translation Block Entry is ignored
  • 13. DMA overview • DMA transfer use physical address, and no memory protection any more? • Not the case, why? • Modern phones are 64-bit, while many of their peripheral devices remain 32-bit • Address translation is needed • And, we need memory protection for DMA transfer also
  • 14. IOMMU(input/output memory management unit) and DART • IOMMU is introduced to connect a direct-memory-access capable I/O bus to the main memory • There is need to map 64bit physical addresses into 32bit device addresses • For 64bit iOS devices, DART(Device Address Resolution Table) is responsible to perform the address translation
  • 15. Host-to-device DMA and device-to-host DMA • For 64bit iOS devices, peripheral devices such as Broadcom WIFI module, implement DMA transfers • Gal Beniamini of Google Project Zero team leverages DMA features on iOS to achieve firmware to host attack in middle 2017 • Compromised WIFI firmware is able to mutate writable DMA mapping • Kernel trust that DMA mapping , lack of boundary check, leading to code execution • Limitation of device-to-host attack • Short distance • Have to compromise WIFI stack first (Attacker and victim in same WIFI environment)
  • 16. Long distance remote attack? • Browser exploit + kernel privilege escalation • By using DMA related vulnerabilities? What? • Looks like a crazy idea • DMA features are kind of low level implementation which is mostly performed at kernel level. • Such feature is never exposed directly to the userland. • Is there any DMA attack surface in userland?
  • 17. Indirect userland DMA • There might be indirect DMA interface at userland • Hardware JPEG engine to accelerate the encoding and decoding process • IOSurface transform is done by hardware device • Etc.
  • 18. IOSurface and IOSurfaceAccelerator • IOSurface object represents a userland buffer which is shared with the kernel. • Users can create IOSurface by providing existing userland memory address and its length • Kernel creates IOMemoryDescriptor and map userland memory to kernel • Option kIODirectionOut is set for read-only userland mappings • Option kIODirectionOut and kIODirectionIn are both set for read-write userland mappings
  • 19. IOSurface and IOSurfaceAccelerator • IOSurfaceAccelerator is a userland framework on iOS platform only • Two most important interfaces: IOSurfaceAcceleratorCreate and IOSurfaceAcceleratorTransferSurface • IOSurfaceAcceleratorCreate is responsible for creating a IOKit userclient connection representing an IOSurfaceAcceleratorClient kernel object • IOSurfaceAcceleratorTransferSurface takes two IOSurface handles, one for source and another for destination, along with a dictionary supplying the transferring parameters • Transfer the surface from src to dst, with color filtering, border filling etc, processed directly by the kernel • Typical scenario of using IOSurfaceAccelerator: Screen Snapshot
  • 20. Low level implementation of IOSurfaceAccelerator • AppleM2ScalerCSC driver architecture • IOSurfaceAcceleratorClient talks to AppleM2ScalerCSC which is the core driver • Low level driver object AppleM2ScalerCSCHal is for handling device dependent stuff and provide device independent interface to AppleM2ScalerCSCDriver • AppleM2ScalerCSCHal creates ColorConversionControl, SrcDestCfgControl, ScalingControl, DitherControl, ColorManager,etc. • AppleM2ScalerCSCHal maps a device memory into kernel virtual space, representing the device’s key registers.
  • 21. IOSurfaceAcceleratorTransferSurface Internals • IOSurfaceAcceleratorTransferSurface will reach kernel function IOSurfaceAcceleratorClient::user_transf orm_surface • Overall procedure of user_transform_surface • We are interested in the DMA mapping part Parameter validation Obtain Src/Dst IOSurface Address Map IOSurface buffer via DMA Obtain mapped address of Src/Dst buffer Set device registers Start the Scaler Wait for interrupt from the device Finish
  • 22. Map IOSurface buffer via DMA • An IODMACommand object is created with a special IOMapper • m_IOMapper is an instance of IODARTMapper which is independent between devices • Then the IOSurface memory descriptor is bond to the IODMACommand
  • 23. Obtain the IOSurface address in IOSpace • After the mapping, the next step is to obtain the device memory visible to IOMMU • v33 here represents the 32bit address in IOSpace
  • 24. SrcDestCfgControl object • SrcDestCfgControl object is used to specify the address of src and dst address of IOSurface in IOSpace • After IOSurface’s IOSpace address is decided, SrcDestCfgControl object is set • v4 represents the kernel virtual mapping of Scaler’s device memory • Other registers relating to transform parameters are handling in a similar manner
  • 25. Start the scaler • After all registers are set, the scaler is started by setting the control register • (deviceAddrVirtual + 128) is the “powerOn” register of the scaler • The scaler device starts its work immediately • When scaler finished the processing, an interrupt will be issued and the event will be signaled. • That indicates the source IOSurface has been transferred to the destination IOSurface. • In the case we don’t specify any transform options in the parameter, scaler simply per- formed a memory copy via DMA transfer.
  • 26. PART III: The implementation of IOMMU memory protection
  • 27. Page table specification of IOMMU • Unlike CPU MMU, page table specification of IOMMU is not well standardized • On iOS DART is responsible for IOMMU page table management • So by reversing iOS DART code, we can understand the page table better • Gal Beniamini has reversed the logic in DART module and explained the page table specification on 64bit iOS devices. • Similar as CPU MMU page table Referenced from: https://googleprojectzero.blogspot.com/2017/10/ov er-air-vol-2-pt-3-exploiting-wi-fi.html
  • 28. IOMMU memory protection • In Gal’s blog he didn’t mention whether the IOMMU supports memory protection or not. • It remains unclear if IOMMU memory protection exists or not • However we can get the answer by reversing DART implementation in iOS 11
  • 29. IOMMU memory protection • The entry point for mapping memory in IOSpace: IODARTMapper::iovmMapMemory • mapOptions parameter has included the memory’s protection bits in virtual space • The last 3 bits in mapOptions is translated to direction value • Read-only mapping has direction value 2 • Write-only mapping has value 1 • Read/write mapping has the value 3.
  • 30. IOMMU memory protection • The direction variable flows and finally reached the function in AppleS5L8960XDART, the low level implementation of DART • On a device later than iPhone 5s, the apSupport mask is always 0x180 • Indicating the 8th and 9th bit in the TTE are AP related bits
  • 31. IOMMU memory protection • Finally we got the access protection specification in TTE • IOMMU supports memory protection UNK BlockAddr valid 64 36 12 2 AP 89 AP meaning 00 Read-write 01 Read-only 10 Write-only
  • 32. PART IV: GPU notification mechanism
  • 33. Apple Graphics workflow • On iPhone7 device, Apple Graphics provides with 128 channels for concurrent processing. • Three channel categories: CL channel, GL channel and TA channel • Kernel wraps drawing instructions from userland and put them into those channels • Kernel then waits for the GPU to finish processing • A well-designed notification mechanism is necessary for GPU to synchronize the status of instruction processing • Considering the concurrency of GPU handling
  • 34. GPU notification architecture • GPU task owns a stampArray representing the stamp status of each channel • The memory is a representation of uint32 array of 128 elements, each showing the last complete instruction’s stamp of that channel • stampArray memory is mapped to kernel and userland also (userland mapping is read-only)
  • 35. Stamp address array • Kernel also maintains a stamp address array of 128 elements • Each element represents the virtual address of that mapped stamp status kernel address
  • 36. IOAccelEvent object • The stamp value of each channel is incremental upon each of the instruction processing completeness. • IOAccelEvent represents the expected stamp value in specific channel of one or one group of drawing instructions • One IOAccelEvent contains 8 sub events • One sub event is 8 bytes in size • Lower 4 bytes represents the channel index • Higher 4 bytes represents the expected stamp value of that drawing instruction
  • 37. IOAccelEvent object • By comparing the expectStamp value with the value in the stamp array, kernel can decide whether an IOAccelEvent has been finished or not
  • 38. IOAccelEvent object • To improve performance, some IOAccelEvent objects are mapped into userland as read-only • Make userland apps understand the status of an event without asking the kernel
  • 39. PART V: The vulnerabilities
  • 40. 1. The DMA mapping vulnerability • On iOS 10 and early beta of iOS 11, the mapOptions of the virtual memory is simply ignored by the DART mapper mapOptions is not used in iovmAlloc
  • 41. 1. The DMA mapping vulnerability • Later on, AppleS5L8960XDART::setL3TTE is reached, which 8th and 9th bit of the TTE set to 0 • Indicating read-write mapping UNK BlockAddr valid 64 36 12 2 AP 89 AP meaning 00 Read-write 01 Read-only 10 Write-only 8th and 9th bit set to 0
  • 42. 2. The out-of-bound write vulnerability • IOAccelResource is similar in functionality as IOSurface object, except that IOAccelResource represents a shared userland buffer which would be mapped into GPU task. • Like IOSurface, we can create IOAccelResource by specifying an existing userland buffer, by specifying the size, or even by providing an existing IOSurface handle. • As part of IOAccelResource initialization process, a shared mapping will be created
  • 43. 2. The out-of-bound write vulnerability • What is IOAccelClientSharedRO? • Contains IOAccelEvent array with 4 elements • With resource id and type information • m_IOAccelClientSharedRO is mapped to both userland and the kernel • userland mapping is read-only • The userland mapped address is returned to user Read-only mapping
  • 44. 2. The out-of-bound write vulnerability • Userland application can delete the IOAccelResource by calling method 1 of IOAccelSharedUserClient • IOAccelEventMachineFast2::testEve nt will be called if the IOAccelResource is created with specific option
  • 45. 2. The out-of-bound write vulnerability • In IOAccelEventMachineFast2::testEvent, it checks whether the IOAccelEvent in IOAccelClientSharedRO has been completed • No boundary check is performed at channel index • Since the IOAccelEvent is created and managed only by the kernel while the userland mapping is read-only • Kernel trust the index value
  • 46. 2. The out-of-bound write vulnerability • However with the DMA mapping bug, the trust boundary is broken • Channel index and expected stamp value can be mutated by the userland app • Both m_inlineArrayA0x18Struct and m_stampAddressArray are arrays of 128 elements. • With m_channelIndex changed to arbitrary value, we caused out-of-boundary read on m_stampAddressArray, and out-of-boundary write on m_inlineArrayA0x18Struct
  • 48. Exploitability • Exploitability of those two bugs depend on whether we can control the content for for both m_inlineArrayA0x18Struct and m_stampAddressArray with the same out-of-bound index • Then we can perform arbitrary memory read and write • Looks like a hard task, because • Both arrays are created in very early stage of iOS boot process, impossible to put controlled contents right after them • Size of element of each array is different. The larger index we specify, the longer span in address of the referenced array element.
  • 49. Craft memory layout • Some facts: • Kernel heap memory starts at a relatively low address • Heap grows linearly with more and more memory allocated • The start address of heap differs within tens of megabytes upon each boot • Addresses of m_inlineArrayA0x18Struct and m_stampAddressArray are closed with each other • It means • We can use a relative large channel index • Along with kernel spray techniques, we might be able to ensure content of the OOB value of m_inlineArrayA0x18Struct[channelIndex] and m_stampAddressArray[channelIndex] are both under our control
  • 50. Feasibility of memory layouting • Kernel heap spray • Quite some known techniques: e.g. sending large OOL message • On iPhone 7, we can spray around 350MB kernel memory within container sandbox app • After m_inlineArrayA0x18Struct and m_stampAddressArray are created, around 50MB extra kernel memory is allocated (As a part of boot process)
  • 51. Feasibility of memory layouting • m_inlineArrayA0x18Struct element size is 24 bytes • m_stampAddressArray element size is 8 bytes • So if: • index ∗ 24 < 350MB + 50MB , and • index ∗ 8 > 50MB • With index value in range of [0x640000, 0x10AAAAA], the out-of-bound elements of both m_inlineArrayA0x18Struct and m_stampAddressArray arrays can be fallen into our sprayed data
  • 52. Arbitrary read and write? • Arbitrary memory read is not a problem • Because m_stampAddressArray element size is 8 bytes • You can reach every dword within each page (higher 4 bytes of a QWORD cannot be read though, but usually not necessary) • Arbitrary memory write is more tricky • Because m_inlineArrayA0x18Struct element size is 24 bytes, only one of its DWORD can be written
  • 53. Write at specific offset within a page • Thanks to mechanism of XNU zone allocator • the base address of m_inlineArrayA0x18Struct array is always at offset 0xF0 or 0x20F0 of a 0x4000 page • Similarly, m_stampAddressArray is allocated with 0x200, falling in kalloc.512 zone. The address offset within a 0x4000 page can be all values dividable by 0x200. • So how to write arbitrary page offset by OOB write on m_inlineArrayA0x18Struct array • For example, a vtable is usually at offset 0 of the page if the object size is large enough • The problem can be solved by congruence theory in mathematics
  • 54. Read at arbitrary offset within a page • Because: • 0xc000 ≡ 0(mod0x4000) • So with arbitrary integer n: • n ∗ 0x800 ∗ 24 ≡ 0(mod0x4000) • With 0x4000 / 24 * 0xF0 / 16 = 0x27f6, we can get: • 0xF0 + 0x27f6 ∗ 24 + n ∗ 0x800 ∗ 24 ≡ 0(mod0x4000) • With arbitrary integer n, we can out-of-bound write to the first 8 bytes in a sprayed page given: • index = 0x27f6 + n ∗ 0x800 • To reach arbitrary offset within page, with m be the offset of the page, we just ensure index is: • index = 0x27f6 + 0x2ab ∗ m/8 + n ∗ 0x800
  • 55. Choose the best channelIndex value • With index = 0x27f6 + 0x2ab ∗ m/8 + n ∗ 0x800 , plus the range of [0x640000, 0x10AAAAA] • We choose the value of 0x9e6185 (can be other values as well) • This value can reach offset 0x568 of a 0x4000 page by writing m_inlineArrayA0x18Struct out-of-bound • And reach offset 0x28/0x228/0x448, etc… of a 0x4000 page by reading m_stampAddressArray out-of-bound
  • 56. First attempt to exploit • Spray around 350MB OOL messages of size 0x2000 • Make sure • Offset 0x28, 0x228,0x428,0x628… of each page is filled with a guessed value(GA), in real case we use 0xffffffe00a5d4030 • Each QWORD in page offset 0x30 is filled with a value to read(VR) • Each QWORD in page offset 0x568(AW field) is filled with a specific value(make sure VR is different with this value)
  • 57. KASLR bypass • By first attempt of the exploit, we then receive the OOL message to see which message’s AW field has been changed • We can then obtain the information of: • Which OOL message is allocated at slot C • Which OOL message is in GA address(slot B)
  • 58. KASLR bypass • Fill slot B with AGXGLContext object(also in kalloc.8192) • Change GA value to 0xffffffe00a5d4000(original GA-0x30, base address of slot B, vtable of AGXGLContext object) • Exploit the OOB bug again • And we get the lower 4 bytes of AGXGLContext vtable by receiving OOL message in slot C
  • 59. Code execution • To get code execution, we need to free the slot C, and fill in an object where its 0x568 offset represents important object • The offset 0x568 in AGXGLContext is set to AGXAccelerator object • Calling AGXGLContext method 0 can reach the function IOAccelGLContext2:: context_finish • With its 0x568 field modified to arbitrary value , we get PC control
  • 60. Overall exploit workflow Create IOAccelResource Obtain IOAccelEvent read- only buffer Trigger bug 1, modify m_channelIndex to 0x9e6185 Prepare initial memory layout, trigger bug 2, obtain index of slot B and C Prepare memory layout for KASLR bypass, trigger bug 2, obtain vptr of AGXGLContext Prepare memory layout for code execution, trigger bug 2, overwrite AGXAccelerator pointer in AGXGLContext Prepare ROP, call method 0 of AGXGLContext, obtain tfp0, post exploitation to jailbreak Finish
  • 61. Post exploitation • By running a piece of ROP gadget, we obtain task_for_pid 0 • Still far away from the jailbreak • Break AMFI • Rootfs remount • KPP/AMCC bypass • Etc. • Most of those have public write-ups • Not a scope of the talk
  • 62. Demo
  • 63. Conclusion • With the first release of iOS 11, Apple fixed the DMA mapping bug • By adding implementation of read-only mapping at its DART code • The other OOB write bug, remains unfixed • A good example of how security can be broken by bad implementation with good hardware design • We make possible a complex exploit chain to achieve jailbreak within userland applications • Should kernel trust the userland read-only mappings? • Last but not the least, userland read-only memory can be dangerous