1. About

With iOS 8.1.3 out, Apple has patched the bugs that made both Pangu8 ( xuanyuansword ) and TaiG work. Apple has credited both teams with the vulnerabilities, but (as can be expected) the vulnerability descriptions in CVE entries are somewhat laconic. Virtually no documentation exists on either exploit. What better way to pass a long transpacific flight but to do a write up? (what more, I figure I'll need this anyway for the upcoming 2nd edition of MOXiI, which has a full chapter on Jailbreaks).

Why should you care? (Target Audience)

Yes, the vulnerabilities have been patched. So no, this isn't exploitable anymore (at least, for those people who [voluntarily|force] upgraded to 8.1.3. But TaiG is a particularly elegant jailbreak (much "cleaner" in most terms than XuanYuan), and there is much to be learned from it.

While I'm all for security, full disclosure and all that, I have a somewhat different stance when it involves iOS. IMMHO, the true potential of iOS is when jailbroken. I therefore don't believe that every version merits a jailbreak - only major ones (e.g. the upcoming 8.2, because it will support the Watch). Jailbreaking a minor update achieves nothing but forcing Apple to patch. In fact, TaiG blew a perfectly good set of exploits which could have and likely should have been saved for later. In a similar manner, documenting exploits before they are patched will only force Apple to patch them faster, because every 0-day, if properly detailed, can be used for malware. This writeup is therefore only published now because these are "burnt" exploits.

Toolset and process

Taig is a Windows based app. Unlike Pangu (which consistently froze my Win7 in VMware Fusion), it actually works well in a VM, which proved useful since I've long "converted" to an all-Apple system. The tools used to analyze on Windows were:

Process Explorer: Mark Russinovich's legendary tool (I named my OS X ncurses top replacement in homage of it). Provides unbelieveable information about all processes in the system.

replacement in homage of it). Provides unbelieveable information about all processes in the system. Process Monitor: Yet another awesome, awesome tool from Mark - this one providing API logs.

IDA: Because there is no better disassembler for Windows

WinDBG: My favorite debugger. Use here was limited since TaiG does not cooperate with debuggers.

In the iOS realm, I used an already pre-JB 8.x device (broken with Pangu) to run my own set diagnostic tools, and those of Apple:

FileMon : My FSEvents viewer, recently re-written to be more stable and grep(1) able

: My FSEvents viewer, recently re-written to be more stable and able fs_usage : The kdebug based utility (same functionality as in OS X). Terrible output, but used to double check FileMon, since FSEvents can sometimes get lost.

: The kdebug based utility (same functionality as in OS X). Terrible output, but used to double check FileMon, since FSEvents can sometimes get lost. jtool : Because there is no better disassembler for iOS. But then, I'm heavily biased on that one ;-)

Having a device already jailbroken proved invaluable - runtime analysis is much more easier than static analysis. The added 'bonus' is that Pangu leaves the kernel is such a shaky state that any access using OSKextRequest (even something entirely benign like my own jketstat tool), causes a panic - so there was no risk of TaiG making any permanent changes, and thereby potentially bricking my device.

Windows

The Windows Binary of TaIG is huge - 51,938,816 bytes, to be exact. This is because it uses the PE format to embed pretty much everything - its code, graphic resources, and the payload to the device - inside the PE's .rdata sections. IDA was somewhat disappointing in figuring out these, although less interesting data (such as the Base64 encoded PNGs) did stick out like a sore thumb.

At first glance, what's interesting is that there are no direct dependencies on Apple's libraries (CoreFoundation, AppleMobileDevice, iTuneSMobileDevice and friends) even though they are clearly used. The mystery was clearly solved by looking at the file system, wherein a small DLL appeared in the temp directory - TaiXXX.tmp , wherein XXX is a temporary file name. The file is easily recognizable as a DLL (MZ..). Further, looking at TaiG through SysInternals' Process Explorer one could see the DLL was loaded, and had a thread - CreateDevHelp - which is an exported symbol. Its "true name", btw, is TGHelp.dll .

The Windows part isn't all THAT interesting, so I'll summarize the key points (and, more importantly, the addresses, if you want to disassemble the DLL on your own). The DLL, incidentally, can be found here

0x10011E60: is the function which gets all the symbols from Apple's libraries ( CoreFoundation.dll, MobileDevice.dll, iTunesMobileDevice.dll and AirTrafficHost.dll . It does so by calling 0x10011DE0, which uses LdrLoadDll (from ntdll.dll ) rather than use LoadLibrary (from kernel32 ), likely in an attempt to not be that blatantly obvious. The symbols are all linked - whether or not they're actually used. You can see the relevant code in the following figure: Note that it's a little tricky, since the GetProcAddress calls (which get the function pointer back into EAX) and the actual store in memory of the pointer ( mov ...., eax ) are sometimes interrupted by push instructions, which provide the symbol to be obtained by the next call of GetProcAddress ) - you can see that with the CreatePairingMaterial call, above. Further, as I mentioned - ALL symbols are obtained, even though a large part are not used. This is why I left dword_108676c (which holds AMdeviceCreateFromProperties ) because it's simply unused. The symbols are are linked and stored beginning at dword_100865A0 (a static which gets "1" if the linkage is complete, so as not to do the process all over again). The symbols that are used are shown in the following table: DLL Address(es) Notes CoreFoundation.dll 0x10086784 ( CFDataAppendBytes ) through 0x1008683c ( kCFBooleanTrue ) Most of the CoreFoundation symbols, with few exceptions (e.g. CFAbsoluteTimeGetCurrent ). The symbols are linked in reverse order (i.e kCFBooleanTrue is first). MobileDevice.dll see above See above - that's why I put the figure iTunesMobileDevice.dll 0x10086774 USBMuxConnectByPort called by 0x10013250 (which also calls AMDServiceConnectionCreate and handles pairing), and 0x10013160 (which creates a socket to USBMux) 0x10086770 AMDeviceNotificationSubscribe called by 0x10014574, which sets 0x10014310 as a callback 0x10086768 AMDeviceIsPaired

... 64 AMDeviceValidatePairing .. 60 AMDevicePair

...5c AMDevicePairWithOptions All called by 0x10013740 (which handles pairing) 0x1008672c AMDeviceCopyValue Used by 0x10013740, as well as 0x100114D0, which wraps it along with all the annoying CF* calls required to convert the value (from a char * in the 3rd arg) to a CFString which can then be obtained. TaiG uses this to detect device lock ("PasswordProtected"), Find-My-iPhone ("com.apple.fmip"), "DeviceName","DeviceClass", "ProductVersion, "UniqueDeviceID", "ProductType", "ProductVersion" (all used for the GUI), and "isAssociated" 0x100866c4 AMRestoreRegisterForDeviceNotification Setting 0x10014410 (dfu_connect), 0x10014490 (recovery_connect), 0x10014450 (dfu_disconnect) and again 0x10014490 (recovery_disconnect) as callbacks. 0x100086718 AMdeviceStartService called by 0x100164E0, which starts its second argument by pairing (0x10013740) and then working the CF* magic. syslog_relay and afc2d (used also to detect an already TaiG-JB device) are started this way. ... todo...

. It does so by calling 0x10011DE0, which uses (from ) rather than use (from ), likely in an attempt to not be blatantly obvious. The symbols are all linked - whether or not they're actually used. You can see the relevant code in the following figure: Note that it's a little tricky, since the calls (which get the function pointer back into EAX) and the actual store in memory of the pointer ( ) are sometimes interrupted by instructions, which provide the symbol to be obtained by the call of ) - you can see that with the call, above. Further, as I mentioned - ALL symbols are obtained, even though a large part are not used. This is why I left (which holds ) because it's simply unused. The symbols are are linked and stored beginning at (a static which gets "1" if the linkage is complete, so as not to do the process all over again). The symbols that used are shown in the following table: 1001465C - checks activation state

10013AC9 - checks PasswordProtected

10017DE0 - Connects to com.apple.mobilebackup2

10011360 - connects to com.apple.afc2

The list, while not comprehensive, should provide enough breakpoints/focus-for-reverse-engineering. You can get a very detailed reference of AMD APIs from libmobiledevice or any of the various GIT repositories from people who reversed it (with some blatantly claiming copyright over the source.. funny :-). Google is (for a change) your friend here. If you're reading this, however, you're probably more interested in what happens on the device, right? So let's get to that.

iOS

Recap: Jailbreaking steps

Apple lists several vulnerabilities in APPLE-SA-2015-01-27-2, with CVE #s and all, but as I mentioned, doesn't go into detail of which vulnerability is responsible for what. Due to iOS's hardened (but not bulletproof) structure, it requires a combination of exploits to achieve the much coveted jailbreak. Specifically, we're looking at the following, which holds true for *all* jailbreaks (past, present, and likely future:

Breaking out of the sandbox: As all apps are confined by default, thanks to Sandbox.kext , and its evil henchKext/accomplice, AppleMobileFileIntegrity.kext .

As all apps are confined by default, thanks to , and its evil henchKext/accomplice, . Obtaining arbitrary (unsigned) code execution: which either involves exploiting a valid code signed binary (mostly Apple's services) by injecting an ROP payload, or bypassing code signatures. The latter involves messing with amfid (the user mode lackey of the AMFI kext), usually through libmis , which we'll discuss in a little bit here.

which either involves exploiting a valid code signed binary (mostly Apple's services) by injecting an ROP payload, or bypassing code signatures. The latter involves messing with amfid (the user mode lackey of the AMFI kext), usually through , which we'll discuss in a little bit here. Obtaining root: Which involves ROP in a native iOS daemon which already runs as root, or - via the filesystem - dropping a binary which launchd will happily execute for you as root, if you know how to ask (and form a plist)

Which involves ROP in a native iOS daemon which already runs as root, or - via the filesystem - dropping a binary which will happily execute for you as root, if you know how to ask (and form a plist) Patching the kernel: To hit AMFI where it hurts - home base. This can be had by patching the boot-args (in memory, not in nvram, since iBoot long ignores them), or patching other parts of the kernel using the set of patches attributed to comex.

The above doesn't imply you need four different payloads - sometimes you can achieve a combination of the first three by directly exploiting a built-in service (which is, in fact, what TaiG does, thanks to AFC's dull-witted and overly helpful servitude). Patching the kernel always requires a separate payload. XNU proper has long been hardened (due to a rough history of repeat exploitation and its (slowly diminishing) open source code base. IOKit drivers, however, provide a rife breeding ground for many an exploit.

The exploits

I: AFC (CVE-2014-4480)

If TaiG was a greek tragedy, its protagonist would most likely AFC. In it, we have a daemon, whose sole raison d'etre is to provide assistance and support for moving files back and forth from the host to the iDevice. Through the AFC* set of APIs, an application (which is supposedly iTunes, but in our case, TaiG) can direct the daemon to create directories, read and write files, and remove them at will. TaiG uses it to create directories in /private/var/mobile/Media (where, among other things photos and books are stored - so obviously AFC can write to there!). First, as _exhelp, then as _mv help. See here: 126 afcd Created dir /private/var/mobile/Media/_exhelp 126 afcd Created dir /private/var/mobile/Media/_exhelp/a 126 afcd Created dir /private/var/mobile/Media/_exhelp/a/a 126 afcd Created dir /private/var/mobile/Media/_exhelp/a/a/a 126 afcd Created dir /private/var/mobile/Media/_exhelp/var 126 afcd Created dir /private/var/mobile/Media/_exhelp/var/mobile 126 afcd Created dir /private/var/mobile/Media/_exhelp/var/mobile/Media 126 afcd Created dir /private/var/mobile/Media/_exhelp/var/mobile/Media/Books 126 afcd Created dir /private/var/mobile/Media/_exhelp/var/mobile/Media/Books/Purchases 126 afcd Created /private/var/mobile/Media/_exhelp/var/mobile/Media/Books/Purchases/mload 126 afcd Created /private/var/mobile/Media/_exhelp/a/a/a/c (symlink) 126 afcd Created dir /private/var/mobile/Media/_mvhelp 126 afcd Created dir /private/var/mobile/Media/_mvhelp/a 126 afcd Created dir /private/var/mobile/Media/_mvhelp/a/a 126 afcd Created dir /private/var/mobile/Media/_mvhelp/a/a/a 126 afcd Created dir /private/var/mobile/Media/_mvhelp/a/a/a/a 126 afcd Created dir /private/var/mobile/Media/_mvhelp/a/a/a/a/a 126 afcd Created dir /private/var/mobile/Media/_mvhelp/a/a/a/a/a/a 126 afcd Created dir /private/var/mobile/Media/_mvhelp/a/a/a/a/a/a/a 126 afcd Created dir /private/var/mobile/Media/_mvhelp/private 126 afcd Created dir /private/var/mobile/Media/_mvhelp/private/var 126 afcd Created /private/var/mobile/Media/_mvhelp/private/var/run 126 afcd Created /private/var/mobile/Media/_mvhelp/a/a/a/a/a/a/a/c (symlink) -- BackupAgent wakes up 279 BackupAgent Chowned /private/var/MobileDevice/ProvisioningProfiles Some events dropped *** Warning: Some events may be lost 279 BackupAgent Created dir /private/var/.backup.i/var/MobileDevice 279 BackupAgent Created dir /private/var/.backup.i/var/MobileDevice/ProvisioningProfiles 279 BackupAgent Chowned /private/var/.backup.i/var/MobileDevice/ProvisioningProfiles 279 BackupAgent Created dir /private/var/.backup.i/var/mobile/Media 279 BackupAgent Created dir /private/var/.backup.i/var/mobile/Media/PhotoData 279 BackupAgent Renamed /private/var/mobile/Media/_mvhelp/a/a/a/a/a/a/a/c /private/var/.backup.i/var/mobile/Media/PhotoData/c 279 BackupAgent Chowned /private/var/run 279 BackupAgent Chowned /private/var/run 279 BackupAgent Renamed /private/var/mobile/Media/_exhelp/a/a/a/c /private/var/run/mobile_image_mounter 279 BackupAgent Chowned /private/var/mobile/Media/Books/Purchases/mload -- # Done - so can remove this 126 afcd Deleted /private/var/mobile/Media/_mvhelp/a/a/a/a/a/a/a 126 afcd Deleted /private/var/mobile/Media/_mvhelp/a/a/a/a/a/a 126 afcd Deleted /private/var/mobile/Media/_mvhelp/a/a/a/a/a 126 afcd Deleted /private/var/mobile/Media/_mvhelp/a/a/a/a 126 afcd Deleted /private/var/mobile/Media/_mvhelp/a/a/a 126 afcd Deleted /private/var/mobile/Media/_mvhelp/a/a 126 afcd Deleted /private/var/mobile/Media/_mvhelp/a 126 afcd Deleted /private/var/mobile/Media/_mvhelp/private/var/run 126 afcd Deleted /private/var/mobile/Media/_mvhelp/private/var 126 afcd Deleted /private/var/mobile/Media/_mvhelp/private 126 afcd Deleted /private/var/mobile/Media/_mvhelp 126 afcd Deleted /private/var/mobile/Media/_exhelp/a/a/a 126 afcd Deleted /private/var/mobile/Media/_exhelp/a/a 126 afcd Deleted /private/var/mobile/Media/_exhelp/a 126 afcd Deleted /private/var/mobile/Media/_exhelp/var/mobile/Media/Books/Purchases/mload 126 afcd Deleted /private/var/mobile/Media/_exhelp/var/mobile/Media/Books/Purchases 126 afcd Deleted /private/var/mobile/Media/_exhelp/var/mobile/Media/Books 126 afcd Deleted /private/var/mobile/Media/_exhelp/var/mobile/Media 126 afcd Deleted /private/var/mobile/Media/_exhelp/var/mobile 126 afcd Deleted /private/var/mobile/Media/_exhelp/var 126 afcd Deleted /private/var/mobile/Media/_exhelp

so at the end of it we have:

/private/var/run/mobile_image_mounter -> ../../../var/mobile/Media/Books/Purchases/mload

But why all this trouble? And why mobile_image_mounter? Well, AFCD provides the "entry point" that TaiG uses into the device, but only one of two "footholds" it requires - the other being iOS's DeveloperDiskImage support. The latter is required when attaching a device and using it with XCode - the DDI is a part of the SDK, and contains a bunch of tools and frameworks. When mounted (using IOHDIX) under /Developer , these libraries are magically "merged" so that /Developer/Library/Frameworks can be searched along with /System/Library/Frameworks ,etc. This isn't unique in that Apple does that also for /AppleInternal as well (nudge, nudge, wink, wink). So if one can provide a fake DeveloperDiskImage - its contents would be mounted, and actually supersede those of the OS itself. HMM.

Ib: The race condition

Ok. It's not THAT simple. The DDI is signed - Otherwise, it's trivial to upload your own DDI and get the mobile storage proxy (also another abject minion) and the MobileStorageMounter.app (in CoreServices) to mount your image, and effectively replace system binaries. But here comes an age old challenge - TOCTOU. If one can get in between the time of check (verifying the signature) and the time of use (mounting), an old bait and switch can get MSP to mount the wrong image (I say here "old" because it's been used before, but never really documented, with only an obiter dictum by iH8sn0w*).

TaiG therefore does that - in between the "manipulating data" (30% or so) and "checking manipulate result" (40%), it uploads a carefully crated DMG called input (found here), along with a benign (and valid) DeveloperDiskImage called input2 . It then repeatedly tries to get MSP to mount the crafted DMG, by submitting the benign DMG and switching it. This can be seen clearly in the output of FileMon (fse), below:

# Create the crafted DMG: 126 afcd Created /private/var/mobile/Media/Books/Purchases/mload/input 126 afcd Modified /private/var/mobile/Media/Books/Purchases/mload/input # Submit to MSP: Note that MSP is redirected (via symlink) to directories under AFC control! 6362 mobile_storage_p Created /private/var/mobile/Media/Books/Purchases/mload/6d55c2edf0583c63adc540dbe8bf8547b49d54957 ce9dc8032d1a9f9ad759e2b1fe99fcb2baeb3db5348ab322cb65c7fc38b59cb75697cbc29221dce1ecd120d/909b75240921fc3f2d96ff08d317e199e0 33a7f8a8ff430b0c97bf3c6210fc39f35e1c239d1bf7d568be613aafef53104f3bc1801eda87ef963a7abeb57b8369/37kpPQ.dmg 6362 mobile_storage_p Modified /private/var/mobile/Media/Books/Purchases/mload/6d55c2edf0583c63adc540dbe8bf8547b49d54957 ce9dc8032d1a9f9ad759e2b1fe99fcb2baeb3db5348ab322cb65c7fc38b59cb75697cbc29221dce1ecd120d/909b75240921fc3f2d96ff08d317e199e0 33a7f8a8ff430b0c97bf3c6210fc39f35e1c239d1bf7d568be613aafef53104f3bc1801eda87ef963a7abeb57b8369/37kpPQ.dmg # Bait - move MSP's DMG to input2 126 afcd Renamed /private/var/mobile/Media/Books/Purchases/mload/6d55c2edf0583c63adc540dbe8bf8547b49d54957ce9dc803 2d1a9f9ad759e2b1fe99fcb2baeb3db5348ab322cb65c7fc38b59cb75697cbc29221dce1ecd120d/909b75240921fc3f2d96ff08d317e199e033a7f8a8 ff430b0c97bf3c6210fc39f35e1c239d1bf7d568be613aafef53104f3bc1801eda87ef963a7abeb57b8369/37kpPQ.dmg to /private/var/mobile/Media/Books/Purchases/mload/input2 # Switch - put the crafted one instead 126 afcd Renamed /private/var/mobile/Media/Books/Purchases/mload/input /private/var/mobile/Media/Books/Purchases/ mload/6d55c2edf0583c63adc540dbe8bf8547b49d54957ce9dc8032d1a9f9ad759e2b1fe99fcb2baeb3db5348ab322cb65c7fc38b59cb75697cbc2922 1dce1ecd120d/909b75240921fc3f2d96ff08d317e199e033a7f8a8ff430b0c97bf3c6210fc39f35e1c239d1bf7d568be613aafef53104f3bc1801eda8 7ef963a7abeb57b8369/37kpPQ.dmg # Doesn't always work, though - MSM isn't (usually that) stupid 6347 MobileStorageMou Deleted /private/var/mobile/Media/Books/Purchases/mload/6d55c2edf0583c63adc540dbe8bf8547b49d54957 ce9dc8032d1a9f9ad759e2b1fe99fcb2baeb3db5348ab322cb65c7fc38b59cb75697cbc29221dce1ecd120d/909b75240921fc3f2d96ff08d317e199e0 33a7f8a8ff430b0c97bf3c6210fc39f35e1c239d1bf7d568be613aafef53104f3bc1801eda87ef963a7abeb57b8369/37kpPQ.dmg # MSP complains.. 6362 Modified /private/var/mobile/Library/Logs/Device-O-Matic/com.apple.mobile.storage_proxy.log.0 # Curses! Foiled again! 126 afcd Deleted /private/var/mobile/Media/Books/Purchases/mload/input2 # But if you don't succeed at first, try, try again...

Race conditions don't always work the first time, so MSP begrudges, as if anyone's listening:

Pademonium-II:~ root# cat /private/var/mobile/Library/Logs/Device-O-Matic/com.apple.mobile.storage_proxy.log.0 Sun Feb 8 05:19:14 2015 [604] (0x19b626310) handle_mount_image: Could not mount the disk image Sun Feb 8 05:19:14 2015 [604] (0x19b626310) main: Could not mount the image .. # Many more messages..

But after a while (usually not more than 30 seconds), the race succeeds, and MSP doesn't log anymore. That's when no news is bad news - you're in trouble.

Ic: The disk image

By grabbing the input dmg in time, it's easy to inspect it on OS X, as shown in the following figure (which I put in as a screen capture because it beats color coding everything in HTML. I have to find a better editor than vi..)

Notice /Volumes/DeveloperDiskImage is empty. That's irrelevant, really. What's more interesting is /Volumes/DeveloperLib - which gets mounted over/along /usr/lib ! Likewise, /Volumes/DeveloperCaches goes over /System/Library/Caches , and contains apticket.der (likely a leftover), and - com.apple.dyld/enable-dylibs-to-override-cache - a file used more times than I can recount to force the system to bypass the shared library cache (where all key libraries and frameworks, including those overridden here, are prelinked). So -- we now have the ability to force two important libraries - XPCD's cache support and libmis - the perennial favorite which provides the "brains" for the ogre that is amfid - which you may recall from evasi0n's brilliant exploit - wherein an empty (and therefore, at the time, non code signed lib) redirected all of the code signature checks to a single, very affirmative kCFBooleanTrue . AppleMobileFileIntegrity.kext , when faced with an unknown (non adhoc) code signature, would summon (via the host special Mach port) /usr/libexec/amfid , which in turn would load the library (because it is *snicker* modular to support provisioning profiles). Replace the check with something that says "yeah, whatever, ok, I know this", and you've defeated code signing.

But.. we still have to defeat code signing at an earlier stage, because libmis.dylib itself will absolutely not be loaded by AMFId as it doesn't have a code signature. (Note it's part of the shared cache, but we got over that with enable-dylibs-to-override-cache. But AMFId is __restrict ed, so DYLD_INSERT_LIBRARIES won't work anymore..). So even mounting replacement binaries or libraries will prove useless if AMFI will kill any non-codesigned binary before it gets a chance to run even a single opcode. Or.. will it?

II: DYLD (CVE-2014-4455)

The advisory lists a "Mach-O Overlapping segments" issue as an issue that was resolved in dyld. It's (shamefully) not the first time Mach-O had issues. Apple clings to this decades old legacy of NeXT (unlike other UN*X, which adopted ELF), and overlapping segments were also an issue in iOS7.

The DMG mounted as the fake developer image (input) contains the two libraries, which look like just your average trojan dylibs, but are not.

Running jtool on these actually crashed the tool. I thought it's just a(nother) bug I have in my code, but then I used otool , and it just blatantly refused to execute. So I looked again, added a boundary check, and saw this:

morpheus@Zephyr (~/Documents/iOS/JB/TaiG) % jtool -l /Volumes/DeveloperLib/libmis.dylib Fat binary, big-endian, 3 architectures: armv7, armv7s, armv8 Specify one of these architectures with -arch switch, or export the ARCH environment variable # variation of the same evasi0n trick morpheus@Zephyr (~/Documents/iOS/JB/TaiG) % ARCH=armv7 jtool -S /Volumes/DeveloperLib/libmis.dylib I _MISValidateSignature (indirect for _CFEqual) I _kMISValidationInfoEntitlements (indirect for _kCFUserNotificationTokenKey) I _kMISValidationInfoSignerCertificate (indirect for _kCFUserNotificationTokenKey) I _kMISValidationInfoSigningID (indirect for _kCFUserNotificationTokenKey) I _kMISValidationInfoValidatedByProfile (indirect for _kCFUserNotificationTokenKey) I _kMISValidationOptionAllowAdHocSigning (indirect for _kCFUserNotificationTokenKey) I _kMISValidationOptionExpectedHash (indirect for _kCFUserNotificationTimeoutKey) I _kMISValidationOptionLogResourceErrors (indirect for _kCFUserNotificationTokenKey) I _kMISValidationOptionUniversalFileOffset (indirect for _kCFUserNotificationTokenKey) I _kMISValidationOptionValidateSignatureOnly (indirect for _kCFUserNotificationTokenKey) U _CFEqual U _kCFUserNotificationTimeoutKey U _kCFUserNotificationTokenKey U dyld_stub_binder # but what's THAT? morpheus@Zephyr (~/Documents/iOS/JB/TaiG) % ARCH=armv7 jtool -l /Volumes/DeveloperLib/libmis.dylib LC 00: LC_SEGMENT Mem: 0x00000000-0x00001000 __TEXT Mem: 0x00001000-0x00001000 __TEXT.__text (Normal) # Look Ma, no code! LC 01: LC_SEGMENT Mem: 0x00001000-0x00002000 __LINKEDIT LC 02: LC_ID_DYLIB /usr/lib/libmis.dylib .. LC 15: LC_CODE_SIGNATURE Offset: 38576, Size: 752 (0x96b0-0x99a0) LC 16: LC_SEGMENT Mem: 0xfffff000-0x1ffff000 __DATA # And in 64-bit: morpheus@Zephyr (~/Documents/iOS/JB/TaiG) % ARCH=armv8 jtool -l /Volumes/DeveloperLib/libmis.dylib LC 00: LC_SEGMENT_64 Mem: 0x000000000-0x4000 __TEXT Mem: 0x000004000-0x000004000 __TEXT.__text (Normal) LC 01: LC_SEGMENT_64 Mem: 0x000004000-0x8000 __LINKEDIT LC 02: LC_ID_DYLIB /usr/lib/libmis.dylib .. LC 16: LC_SEGMENT_64 Mem: 0xffffffffffffc000-0x1fffc000 __DATA

And there's your "overlapping segments", yet again.

{"app_name":"amfid","app_version":"","os_version":"iPhone OS 8.1.2 (12B440)", "slice_uuid":"b99c5334-10f8-3014-865b-b0977d6f1a45","share_with_app_devs":false, "build_version":"","is_first_party":true,"bug_type":"109","name":"amfid"} Incident Identifier: 59E17AA8-469A-4395-AC6B-53C1F2B9657B (yep, Apple, that was me :-) CrashReporter Key: a72d111b6b52f7c1ae1360e923e7c0da675b9261 Hardware Model: iPhone7,2 Process: amfid [22] Path: /usr/libexec/amfid Identifier: amfid Version: ??? Code Type: ARM-64 (Native) Parent Process: launchd [1] Date/Time: 2015-05-21 08:13:39.385 -0400 Launch Time: 2015-05-21 08:13:21.101 -0400 OS Version: iOS 8.1.2 (12B440) Report Version: 105 Exception Type: EXC_BREAKPOINT (SIGTRAP) Exception Codes: 0x0000000000000001, 0x00000001200fd088 Triggered by Thread: 2 Dyld Error Message: Symbol not found: _MISCopyInstalledProvisioningProfiles Referenced from: /usr/libexec/amfid Expected in: /usr/lib/libmis.dylib Dyld Version: 353.6 Note: because TaiG's libmis doesn't bother to provide all symbols, your amfid may occasionally crash. By 'occasionally' I mean whenever it checks for provisioning profiles:

xpcd_cache follows the same idea - You can find libmis.dylib and xpcd_cache.dylib here , but they're also in the input.dmg. If you run otool, it will cowardly refuse to deal with the malformed Load commands. The present version of jtool will crash (alas!), but I'll upload the fixed version (which also has plenty of other features) soon.

The deed done, it is now possible to inject the binary that will untether all this in the future - /taig/taig , run it, and restart the device. The binary will be used to effectuate the changes (remounting root, moving the libraries to their permanent home on the file system, adding a " /DeveloperPatch " containing AFC2, and a couple more things, described later). It also leaves one major last task - last, but not least - patching the kernel.

* - Hi Dude!