iOS kernel exploitation archaeology

PATROKLOS ARGYROUDISCENSUS S.A.

argp@census-labs.com
www.census-labs.com

Who am i● Computer security researcher at CENSUS S.A.
○ Vulnerability research, RE, exploit development● Before CENSUS: postdoc at TCD doing netsec● Heap exploitation obsession (userland & kernel)● Wrote some Phrack papers ;)Introduction● evasi0n7 was released by the evad3rs on 22nd Dec. 2013
○ Supported iOS 7.0 to 7.1b3 - all iDevices except ATV○ Decided to RE the kernel exploit of the jailbreak○ Not only the bug, but the techniques too!
○ Ended up doing a re-implementation of the kernel exploit● This talk is my notes on the project - NOT a jailbreakwalkthrough!
○ Focus on encountered difficulties & how they wereovercome○ Take aways useful for current iOS kernel researchOutline● evasi0n7 overview● The kernel bug● My debugging setup● My re-implementation● Lessons learned

evasi0n7 overview● Released by the evad3rs on 22nd Dec. 2013
○ That’s like ~4 years ago, therefore “archaeology”● Huge drama with geohot● Huge drama with the bundled TaiG piracy app store● The jb scene at that time was like the occult war of 1899
between Aleister Crowley and W.B. YeatsYeah… wait, what !?

evasi0n7 overview● geohot released a writeup on the userland part of evasi0n7○ Stopping at the point of gaining root
○ “since the /evasi0n7 binary is supa obfuscated good”○ AFAIK first public jb that utilized deliberate obfuscation● p0sixninja released a writeup on the kernel bug○ Stopping at the gdb crash log● I apologize in advance if I forgot/missed any details orreferences

Motivation● So, I decided to RE the /evasi0n7 binary○ Deobfuscating it seemed like an interesting challenge○ Wanted to understand the kernel exploitation techniques
implemented in it● I started around the last week of February 2014
○ While working; at most 2 days per week on thisCeremonial instruments● iPhone 4 - limera1nable, therefore easy (lol) kernel debugging○ Initially (lol) with iOS 7.0.6 (AArch32)○ iPhone 5s / iOS 7.0.6 for verifying findings on AArch64 no kernel debugging● evasi0n7-mac-1.0.0-5fbc5de0c23654546ad78bd75a703a57
24e15d39.dmg● IDA, gdb (lol), lldb (lol), Ukrainian black metal

evasi0n7 obfuscation● Not all functions were obfuscated, but some of the importantones were● I have been told that later versions of evasi0n7 were released
without obfuscation, but at that point I already had myre-implementation done

The kernel bug● Apparently discovered by p0sixninja via simple device nodefuzzing● Requires unsandboxed root privileges○ We will not cover that

The kernel bug

Back to ptsd_openpis_ioctl_list placement

Debugging setup● Started by debugging the /evasi0n7 binary in userland○ Initially with gdb, almost nothing worked○ Then with debugserver/lldb, a bit better, but still horrible● While experimenting my iPhone 4 iOS 7.0.6 device went intoa recovery loop from which no fix/restore was possible :(○ Only 7.1 signed at that time
○ My only iPhone 4 device, so I upgraded it to 7.1○ e7 didn’t support 7.1 - pis_ioctl_list bug fixed○ iPhone 4 limera1nable so fundamental for kernel
debuggingKernel debugging setup● redsn0w (util for using limera1n to boot unsigned kernels)
didn’t/doesn’t support anything newer than iOS 6.x○ Spent considerable time trying to RE/understand redsn0w
and patch it to support iOS 7.x○ In the end I gave up, too time consuming and wasn’t eventhe main task of this project● Decided to go with opensn0w○ winocm’s open source redsn0w alternative○ https://github.com/winocm/opensn0w

opensn0w● Seemed to have support for iOS 7.x○ Limit of 39 chars for boot-args (since iOS 7.1 was using
39 chars for boot-args)○ Needed to use more chars to disable kernel’s security
checks and enable KDP● Modified opensn0w to patch iBEC (which passes boot-args
to the kernel (in DFU mode))○ Patched the pointer to the boot-args variable to point toanother location in iBEC that had a lot of available space○ Able to have arbitrary-lengthed boot-args

Kernel debugging at last!
● Use the force-upgraded-to-iOS-7.1 iPhone 4 device with mypatched opensn0w to boot the iOS 7.0.6 kernel image!

● Little note: e7 claimed that it enabled KDP (when applyingthe jailbreak patches)○ Not really…
○ They missed a check for the debug-enabled variable inthe kernel○ KDP session established, but froze after a while○ My opensn0w patch included this ;)Kernel debugging at last!
● LOL! Not really!
○ Breakpoints sometimes worked!
○ Stepping sometimes just continued execution!
○ Taking too long to type commands froze KDP!
○ Issuing commands too fast froze KDP!
○ It was awesome!

● Btw, kernel debugging on iOS 6.x was much better○ More or less the same issues, but not as frequent○ How do iOS kernel engineers work ?! - rhetorical

The /evasi0n7 binary● Now I could observe what the /evasi0n7 binary was doingfrom the kernel’s point of view
○ So I started debugging it from both sides; userland andkernel○ While manually deobfuscating obfuscated functions withhints from runtime, keeping notes with IDA● Quickly found that it was abusing the tty structure○ To obtain read/write access to physical memoryRe-implementation!
● More fun to develop my own exploit○ Not from scratch but based on the notes I had up to thatpoint○ Wanted to use the vm_map_copy structures technique(by Dowd and Mandt) - heap obsession● Clear understanding of the bug, and a general/fuzzy idea
about exploiting it○ Pen and paper, testing, evaluation, repeat○ Ad nauseam; despair; new idea; repeat

Let’s revisit the bug● In essence it was an invalid indexing bug○ In the pis_ioctl_list array which is allocated on the heap(element of a global struct)○ We control the size of the array on the heap, we can growit but not shrink it○ ptmx_get_ioctl stores at the invalid index of the array theaddress of the pmtx_ioctl struct (which was allocated onkalloc.88)

vm_map_copy technique● Originally proposed by Dowd and Mandt● Spraying the kernel heap with them by sending messages to amach port with OOL descriptors (controlled size)● Overwrite its size element and/or its kdata element○ Adjacent or arbitrary leak● Overwrite its kalloc_size element○ kfree() puts it to a wrong zone
○ Allocate it back and write to it; heap overflow

vm_map_copy fuzzy idea
● I’ll use the pis_ioctl_list index bug to access the kdata pointer toleak kernel memory● Kernel heap arrangement and manipulation for achieving arbitrary
R/W primitives

Exploitation

Exploitation
Stage 1● Spray with vm_map_copy structs and create holes on thekalloc.256 zone
○ kalloc.256 selected since during debugging seemed“quiet”○ tty structs go to kalloc.384; steer clear● Move the pis_ioctl_list to kalloc.256 (by enlarging it)○ Goes into one of the holes we have created○ Next to it we have a vm_map_copy structExploitation
Stage 1

Exploitation
Stage 1

Exploitation
Stage 1

Exploitation
Stage 2● Spray with vm_map_copy structs and create holes on the kalloc.88
zone● Create a new master PTMX device with an invalid index value○ Allocates a ptmx_ioctl struct (kalloc.88)○ Goes into one of the kalloc.88 holes we have created it○ Calling open() on this device stores the address of theptmx_ioctl struct at the (invalid) index of the pis_ioctl_list○ We control the index;○ We relatively place it on the kdata field of the neighboring
vm_map_copy structExploitation
Stage 2

Exploitation
Stage 2

Exploitation
Kernel heap leak (stages 1 & 2)

Exploitation
Kernel heap leak (stages 1 & 2)
● We receive the OOL message○ We now have the kernel heap pointer that has the address ofthe newly allocated ptmx_ioctl struct○ An address of a slot of the kalloc.88 kernel heap zone

Exploitation
Kernel heap leak (stages 1 & 2)

Exploitation
Stage 3● Triggering the bug on a slave ptmx device reaches a code paththat gives us a write○ Need to survive dereferences; we know a kalloc.88 address● Clean-up the kalloc.256 zone, spray it again with vm_map_copy
structs and create holes○ Again, next to the pis_ioctl_list array we place a vm_map_copy
struct○ We use a payload/buffer for it that has a fake ptmx_ioctl
pointer○ ptmx_ioctl has a pointer to a tty struct○ We use the leaked kernel heap address for the fake tty pointerExploitation
Stage 3● Clean-up the kalloc.88 zone and spray it again● With vm_map_copy structs, to○ Use their payload to place part of the fake tty struct (doesn’t fitin kalloc.88, it’s 256 bytes*)○ We plan to use their size and/or kalloc_size fields as targets
for controlled relative writes○ Then use Dowd’s methods for arbitrary read/heap overflow via
vm_map_copy structs* But goes to kalloc.384

Exploitation
Stage 3
● Problem: our fake tty struct must be 256 bytes (since we need tosurvive various uses of it)○ Also spray kalloc.88 that something that allows us to host therest of the fake tty struct● Open the AppleJPEGDriver IOKit driver○ Spray with XML properties of length 88 (i0n1c’s technique)○ Placed on kalloc.88 after our vm_map_copy struct○ Its content is the second part of our fake tty struct○ It’s enough to reach the desired code path that gives us a write○ We corrupt the neighboring vm_map_copy structFake tty struct on kalloc.88● Note: arbitrary R/W just with the fake tty?
● Theoretically possible, in practice unstable● Remember, our two kalloc.88 slots cannot hold the whole
fake tty struct (256 bytes)● We point c_cs to the neighboring vm_map_copy struct’s sizeor kalloc_size fields

Exploitation
Stage 3

Exploitation
Stage 3

Exploitation
Stage 3

Exploitation
Stage 3

Exploitation
Stage 3

Data-only banishing ritual● We have a controlled corruption over a vm_map_copy struct○ We can use duke’s primitives for arbitrary read/heapoverflow● Plus, we know our location in the kernel heap
○ Our 1 & 2 stages; we used that knowledge extensively andbuilt on it our whole attack● Everything up to this point is data-onlyBanishing ritual● Not much work getting PC control from here
○ Play with vtables of IOKit objects● Getting from here to a whole jailbreak is out of the scope of
this talk (obviously ;)● How close to the evasi0n7 kernel exploit techniques?
○ Pretty far off I’d say ;)○ At least I temporarily satisfied my heap exploitation
obsession

Lessons learned● Don’t hack Apple○ I can’t believe Apple kernel engineers work with the same
debugging tools as the ones Apple publicly provides● jk; hack Apple ;)○ It’s becoming harder, but more fun● Need for sharing notesevasi0n7 greetz● i0n1c● winocm● ih8sn0w● SomeoneReferences
https://www.theiphonewiki.com/wiki/Evasi0n7
http://geohot.com/e7writeup.html
https://twitter.com/evad3rs
http://evasi0n.com/
http://blog.azimuthsecurity.com/2013/02/from-usr-to-svc-di
ssecting-evasi0n.html?m=1● https://github.com/winocm/opensn0w● i0n1c’s iOS kernel heap talks● Jonathan Levin’s *OS Internals Volume III has a chapter on
evasi0n7●●●●●

Questions