Hi, I'm on a plane from SFO to New York, and made something for you. Not even a rap song.



******* geohot(@tomcr00se) presents an evasi0n7 writeup *******



== Intro ==



I was bored, reversed, wrote this write-up, and wanted to do something with it. I tried to sell it to the Chinese for $7 and a trip to the Pizza Hut salad bar, but it turns out all the Pizza Huts in China don't have salad bars anymore, so the deal was called off.



This writeup takes place from the perspective of evasi0n7. Fuck secrets. Note that this writeup doesn't help Apple, I got this by reversing the public evasi0n binary, which they can, and do do. Also note, I found nothing sketchy in my reversing, your phones most likely aren't being backdoored by Chinese. If I ever touch jailbreaking again, which is unlikely(until ARM128 comes out, I only touched the game again for the love of ARM64), no more secrets. Full disclosure time, I was working on a public, free of charge, china not involved, old school jailbreak with a few others. evad3rs released first. That jailbreak overlapped this one 80%, partly due to leaks, but mainly due to the exploits and methodology being the obvious choice(great minds, well you know), meaning the exploits won't be usable next time. No more jailbreaks ever?



Also, for the hell of it, check out the sha hash of "http://geohot.com/mt.jpg" and @tomcr00se. Ok, let's begin, changing voice to ./evasi0n7



== Yay, you clicked on me ==



Hi, first I am going to check if you already jailbroke your device. I'm looking for the file ".evasi0n7_installed" using afc. Recall that afc runs in the "/var/mobile/Media" directory, so the full path is "/var/mobile/Media/.evasi0n7_installed"



Okay, please click "Jailbreak" to begin our journey to root. This journey stops at root for now, since the /evasi0n7 binary is supa obfuscated good.



== Retrieving remote package ==



I need a real codesigned app, for reasons that'll be apparent later. To figure out where to get one, let me grab "http://evasi0n.com/apple-ipa-info.plist", ahh nice, a URL and some cookies. To play at home, run:



curl -b "downloadKey=expires=1387947603~access=/us/r1000/098/Purple/v4/c3/4e/98/c34e989a-8522-fde0-db2d-884dd3b1302d/mzps6036043982514941651.D2.pd.ipa*~md5=dc91b9d5599eb2e135bddbec3ad5dbc2" http://a396.phobos.apple.com/us/r1000/098/Purple/v4/c3/4e/98/c34e989a-8522-fde0-db2d-884dd3b1302d/mzps6036043982514941651.D2.pd.ipa -o wwdc.ipa



This is an app for people at WWDC I assume, I don't know since I just do what the plist says. What I care about is that it's signed.



== Uploading jailbreak data ==



Well, I need something to install. Namely cydia, or, you know, that other app store. Let me push a few files through afc for untarring later. Remember still in "/var/mobile/Media"

"evasi0n-install/packagelist.tar"

"evasi0n-install/Cydia.tar"

"evasi0n-install/extras.tar"



== Injecting evasi0n app (1/2) ==



Okay, so I'm not really going to really install the app yet, but I will upload an unzipped copy to "/var/mobile/Media/Downloads/WWDC.app" through afc. Note that the main app("/var/mobile/Media/Downloads/WWDC.app/WWDC") is not chmodded +x, since afc creates new files 644.



== Injecting evasi0n app (2/2) ==



Let me modify the real app host side a little now, give Info.plist a new ExecutableFile "../../../../../../var/mobile/Media/Downloads/WWDC.app/WWDC". Get it? When the code signature is checked, it passes because that's a real copy of the app. Upload pkg.ipa, run com.apple.mobile.installation_proxy on the ipa, also change the picture to the official evad3rs logo thing. And yay, installd chmods the app +x, and makes a pretty icon appear.



Now the fun begins, I push two more files over afc.

"Downloads/WWDC.app/WWDC" with contents "#!/usr/libexec/afcd -S -d / -p 8888" (the chmod +x stays)

"Downloads/WWDC.app/gameover.dylib"



Get it, the app is just a shebang to run afcd. "-S" so I can access special files, "-d /" so afcd runs in the root, and "-p 8888" to run on port 8888.



Ahh, but afcd has a sandbox profile, how can it access anything cool? By injecting gameover.dylib of course



geohot@comet:~/iphone/evasi0n2/extract$ dyldinfo -export gameover.dylib

for arch armv7:

export information (from trie):

[re-export] _SANDBOX_CHECK_NO_REPORT (_kCFBooleanTrue from CoreFoundation)

[re-export] _sandbox_check (_sync from libSystem)

[re-export] _sandbox_extension_consume (_sync from libSystem)

[re-export] _sandbox_extension_issue_file (_sync from libSystem)

[re-export] _sandbox_free_error (_sync from libSystem)

[re-export] _sandbox_init (_sync from libSystem)

[re-export] _sandbox_init_with_parameters (_sync from libSystem)



Hmm, but who signed that dylib. Nobody, absolutely nobody. Exploit, if S_ATTR_LOC_RELOC is set on all the executable sections, the +x is removed from the sections after the header is +x checked, but before +x pages are mapped, to pass the check but avoid triggering codesign.



afcd inits the sandbox from inside the binary, so by overriding the dylib (note that LC_ID_DYLIB of gameover is "/usr/lib/system/libsystem_sandbox.dylib"), the sandbox is never initted and afcd is free to write anywhere.



But how do I convince the dylib to load? Let us configure the system a little, together.



== Configuring system (1/2) ==



Ahh, the first of a needlessly burned exploit. But cute anyway. From afc, remember, this is still a sandboxed afc, I want to access "/tmp", so let's create a symlink. But you see, afc is clever enough to make sure I don't symlink out of it's directory. Never fear.



symlink("../../../../../tmp", "Downloads/a/a/a/a/a/link")



That's cool, right? Still in the sandbox, count the ../



rename("Downloads/a/a/a/a/a/link", "tmp")



Oh snap, it's a relative symlink, let me traverse from "/var/mobile/Media/tmp" like "../(Media)../(mobile)../(var)../(private)../tmp"



So I can access "/tmp", ballin.



== Configuring system (2/2) ==



Let me grab all your cache files, one sec. I'll use "com.apple.mobile.file_relay" and request "Caches". It's a big ass cpio file.



To "/var/mobile/Library/Caches/com.apple.mobile.installation.plist" I'll add the "EnvironmentVariables" to the developer.apple.wwdc-Release app. You know, the most awesome one ever, "DYLD_INSERT_LIBRARIES -> /private/var/mobile/Media/Downloads/WWDC.app/gameover.dylib" Now when the afcd app shebang runs, gameover.dylib is injected.



And now for the second exploit that I could have used mobilebackup for. Apple, want to do a solid and not patch? Don't you think that's fair?



I need to push files elsewhere in /var, but I can't because afc is still in the sandbox. Good thing I have a race condition in installd, exploitable since I can modify "/tmp", as shown before.



For each file in "/var/mobile/Library/Caches/com.apple.mobile.installation.plist", "/var/mobile/Library/Caches/com.apple.LaunchServices-054.csstore" which I zero to force a rebuild, and "/var/mobile/Library/Preferences/com.apple.backboardd.plist", where I add "BKNoWatchdogs"="Yes" to remove the 30 second app startup timeout, I create a "pkg.zip", which I upload to "/var/mobile/Media" with afc.



Then I command installd to install it, which creates a "/tmp/install_staging.XXXXXX/foo_extracted" where I extract the zip. But now fast fast race condition fast fast



symlink("../../..//var/mobile/Library/Caches/", "tmp/install_staging.XXXXXX/foo_extracted.new")

move("tmp/install_staging.XXXXXX/foo_extracted", "tmp/install_staging.XXXXXX/foo_extracted.old")

move("tmp/install_staging.XXXXXX/foo_extracted.new", "tmp/install_staging.XXXXXX/foo_extracted")

installd_extract("/var/mobile/Media/pkg.zip", "tmp/install_staging.XXXXXX/foo_extracted")



Get it? Now when the extract happens to "tmp/install_staging.XXXXXX/foo_extracted", the files go in "/var/mobile/Library/Caches/". Which is cool since installd isn't sandboxed.



== Rebooting ==



Count the reboots, this is 1. Used to get com.apple.mobile.installation.plist to be reloaded.



== To continue, please unlock your device and tap the new 'evasi0n 7' icon. ==



Finally, when you click the app I run "#!/usr/libexec/afcd -S -d / -p 8888" with gameover.dylib killing the afc sandbox, but still as mobile. Let me just do two quick things in var, as mobile, outside the sandbox.



symlink("../../../../../dev/rdisk0s1s1", "/var/mobile/Library/Logs/AppleSupport")



Leaving "/var/mobile/Library/Logs/AppleSupport" -> "../../../../../dev/rdisk0s1s1". Exploit, this file is chowned mobile:mobile on reboot by CrashHousekeeping, and since chown goes through symlinks...



And tell "/var/mobile/Library/BackBoard/applicationState.plist" to restart the evasi0n app automatically on next reboot, which I'll do now.



== Rebooting ==



This is 2. "/dev/rdisk0s1s1" is being chowned to mobile:mobile as we speak.



== Modifying rootfs... ==



afc is running, outside the sandbox. "/dev/rdisk0s1s1" is mobile:mobile, time to write the block device.



Note that the kernel no longer allows the rootfs to be remounted rw. So I just write directly to the underlying block device. haxx. This is cool since afcd has the "-S" option.



Files written:

"/evasi0n7" -- the main binary which does the kernel exploit.

"/evasi0n7-installed" -- just a blank file

"/System/Library/LaunchDaemons/com.evad3rs.evasi0n7.untether.plist" -- touched to make launchd load this

"/System/Library/Caches/com.apple.xpcd/xpcd_cache.dylib" -- the new home of the LaunchDaemons, codesign haxx

"/System/Library/Caches/com.apple.dyld/enable-dylibs-to-override-cache" -- convinces the system to look on the filesystem before the dyld_cache

"/usr/lib/libmis.dylib" -- overrides the symbols in amfid to make the signature check return 0, with above codesign trick

You know, [re-export] _MISValidateSignature (_CFEqual from CoreFoundation)



"xpcd_cache.dylib" contains a plist with just two launchdaemons, com.apple.MobileFileIntegrity, which starts with the signature free libmis.dylib, and com.evad3rs.evasi0n7.untether, which is the unsigned untether.



Note that DYLD_INSERT_LIBRARIES won't work on amfid, since it has a "__RESTRICT" segment. Hence the above trick. Replacing the real library.



== Rebooting ==



This is 3. Need to flush the changes I made in the block device to the filesystem.



== Running /evasi0n7, as root, on the device ==



Now you see the splash screen. Away into obfuscation land of kernels and untarring. Who wants to write up that part?



***************



With transparency, love, and rap songs from

~geohot

