A few weeks back a friend ran into a strange little bug that ended up corrupting some relatively unimportant system files on their phone. Those files were important enough that iOS wouldn't boot as long as the files remained corrupted, but unimportant enough that simply deleting them would cause iOS to generate them anew. The problem was, the phone wouldn't boot, so we couldn't access those files to delete them. So begins our journey.
One of my first thoughts when I realized what had happened was of this little project called ssh-rd by msftguy. For those who might not know, it was a really useful tool back in the day for essentially live-booting a small OS that you could SSH into (using limera1n). Offline filesystem access would be a perfect fix for this scenario.
I googled and found two similar projects that appear to work with checkm8 devices. We have SSH-Ramdisk-Maker-and-Loader by Ralph0045, and telnetd_ramdisk by danieltroger. Neither project worked for me out of the box (I'll spare the details, see issues page on both projects). I also found this somewhat related guide. While neither project worked for me, they proved the idea was possible and the source code pointed me in the right direction.
Rather than develop and release another tool, I'll try to walk through the steps for doing this manually and provide a couple of scripts that will help you along the way. This isn't really for the faint of heart. You will need to compile a lot of tools, and what worked for me may not work for you. This guide assumes a 64-bit device, though it could be modified to work for 32-bit.
At the end of this guide, I'll also provide a few scripts that can be used as a quick-start point that will hopefully save someone a bit of time.
My setup:
- Mac running 10.15 (Catalina)
- iPhone 8 running 13.5
Dependencies
- A device vulnerable to checkm8 (A11 processor or earlier)
- Your IPSW
- While it will need to be for the correct device, this doesn't need to be the version you have installed. This is the IPSW we will use as a base image to boot. I used 13.5, I've heard it works well for other people too. iOS 14 may not work for you here. You might need to try multiple versions and see what works.
- An APTicket for your device.
- This does not need to be for any specific version. I used a 13.7 ticket.
- You can extract one from a saved SHSH2 blob.
- Some keys from theiphonewiki.
- These should match the firmware of your IPSW.
- XCode command line tools
- xcode-select --install
- The iPhone SDK for your firmware
- We need this to compile restored_external
- You don't need to be a developer to download the SDKs anymore
- Drop it in /Library/Developer/CommandLineTools/SDKs/
- If you can't compile it you can try my binary, but it probably won't work
- img4 via img4lib
- kairos
- Kernel64Patcher
- irecovery via libirecovery
- compareFiles.py
- curl 'https://raw.githubusercontent.com/dualbootfun/dualbootfun.github.io/d947e2c9b6090a1e65a46ea6a58cd840986ff9d9/source/compareFiles.py' | sed -n '3,$p' > ./bin/compareFiles.py
- ldid2 via xerub's ldid fork
- iproxy via libusbmuxd
- PyBoot - An easy way to pwn DFU, though not the only way
- Something that can extract a deb file (I use 7zip)
- Some dropbear resources
- A launch daemon
- A host key
- Note: normally it's a bad idea to reuse host keys, but in this case, it's not going to be a problem since the interface will only ever be accessible over USB. If you want to generate your own dropbear host key, though, that's not a problem.
- restored_external.c
- We'll use a modified version of the one helpfully created by danieltroger
- A couple more things we'll wget along the way
Setting up
- Extract your IPSW and put the relevant contents into a folder called "resources". You will know which resources are relevant because they will be listed for your device / firmware in theiphonewiki. Not all the files in your ipsw will be relevant.
 7z x ./iPhone_4.7_P3_13.5_17F75_Restore.ipsw
- Restore ramdisk (you don't need the update ramdisk or root filesystem)
- Restore ramdisk trustcache
- DeviceTree
- applelogo
- iBEC
- iBSS
- kernelcache
- Add your SHSH2 blob to the "resources" folder
Building the bootchain
- Decrypt - We'll store the decrypted files in the "decrypted" folder. Be sure to use IVs and keys from theiphonewiki as necessary.mkdir ./decrypted/
 img4 -i ./resources/iBSS* -o ./decrypted/iBSS.dec -k IV+KEY
 img4 -i ./resources/iBEC* -o ./decrypted/iBEC.dec -k IV+KEY
 img4 -i ./resources/applelogo* -o ./decrypted/applelogo.dec
 img4 -i ./resources/DeviceTree* -o ./decrypted/devicetree.dec
 img4 -i ./resources/kernelcache* -o ./decrypted/kernelcache.dec
 img4 -i ./resources/*dmg -o ./decrypted/ramdisk.dec.dmg
- Patch - Patch a few things and put them in the "patched" folder. We generate a binary patch for the kernelcache to use later.mkdir ./patched/
 kairos ./decrypted/iBSS.dec ./patched/iBSS.patched
 kairos ./decrypted/iBEC.dec ./patched/iBEC.patched -b "rd=md0 -v"
 Kernel64Patcher ./decrypted/kernelcache.dec ./patched/kernelcache.patched -a
 ./bin/compareFiles.py ./decrypted/kernelcache.dec ./patched/kernelcache.patched # > ./kc.bpatch
- Sign - Extract the apticket from the shsh2 file, and then use it to sign everything.mkdir ./rd_image/
 plutil -extract ApImg4Ticket xml1 -o - ./resources/*.shsh2 | xmllint -xpath '/plist/data/text()' - | base64 -D > ./apticket.der
 img4 -i ./patched/iBSS.patched -o ./rd_image/iBSS.img4 -T ibss -A -M ./apticket.der
 img4 -i ./patched/iBEC.patched -o ./rd_image/iBEC.img4 -T ibec -A -M ./apticket.der
 img4 -i ./decrypted/applelogo.dec -o ./rd_image/applelogo.img4 -T logo -A -M ./apticket.der
 img4 -i ./decrypted/devicetree.dec -o ./rd_image/devicetree.img4 -T rdtr -A -M ./apticket.der
 img4 -i ./resources/kernelcache* -o ./rd_image/kernelcache.img4 -T rkrn -P ./kc.bpatch -J -M ./apticket.der
 img4 -i ./resources/*trustcache -o ./rd_image/trustcache -M ./apticket.der
Build the ramdisk
- Create ramdisk skel, populate it with some binaries and pathsmkdir ./rd_skel/
 cd ./rd_skel/
 wget -q 'http://newosxbook.com/tools/binpack64-256.tar.gz'
 tar xzf ./binpack64-256.tar.gz
 rm -f ./binpack64-256.tar.gz
 mkdir -p ./var/root/
 chmod +x ./usr/bin/*
- Install ncurses libswget -q 'https://apt.bingner.com/debs/1443.00/ncurses_6.1+20181013-1_iphoneos-arm.deb'
 7z x ./ncurses*.deb > /dev/null
 rm ./ncurses*.deb
 tar xf ./data.tar 'usr/lib/'
 rm ./data.tar
 cd ./usr/lib/
 ln -s ./libncurses.6.dylib libncurses.5.4.dylib
 cd ../../../
- Add dropbear resourcesmkdir -p ./rd_skel/System/Library/LaunchDaemons/
 mkdir -p ./rd_skel/etc/dropbear/
 wget -q 'https://gist.githubusercontent.com/compilingEntropy/60e84d15bc274f88b6f53e6c3788e8e9/raw/597355e51831cafef8751b598c15832bac5fdd9d/dropbear.plist' -O ./rd_skel/System/Library/LaunchDaemons/dropbear.plist
 wget -q 'https://gist.githubusercontent.com/compilingEntropy/f7042cfb1f402c6eff0afb14014cefe1/raw/c7d73ad466a3e8af7828a58a5be0c6f490b68f3e/id_rsa' -O - | base64 -d > ./rd_skel/etc/dropbear/id_rsa
 wget -q 'https://gist.githubusercontent.com/compilingEntropy/ff0a80f156a135f7c386598a44ba8bb3/raw/bd594fcb4d252de3c41a25a267c4350cb70078b9/motd' -O ./rd_skel/etc/motd
- Resize and create ramdiskcp -a ./decrypted/*.dec.dmg ./ramdisk.dmg
 hdiutil resize -size 150MB ./ramdisk.dmg
 mkdir ./mnt/
 hdiutil attach -mountpoint ./mnt/ ./ramdisk.dmg
- Build / sign restored_external, add it to ramdiskmv ./mnt/usr/local/bin/restored_external{,_original}
 wget -q 'https://gist.githubusercontent.com/compilingEntropy/3c6f19f85cdce53fdf44b7b84005023d/raw/c0057abfe00eba3971a9c0a1d296e07dde23467c/restored_external.c' -O ./resources/restored_external.c
 xcrun -sdk iphoneos clang -arch arm64 ./resources/restored_external.c -o ./mnt/usr/local/bin/restored_external
 ldid2 -S ./mnt/usr/local/bin/restored_external
- Apply our modificationsrsync --ignore-existing -ahuK ./rd_skel/ ./mnt/
- Sign and pack the ramdiskhdiutil unmount ./mnt/
 rmdir ./mnt/
 img4 -i ./ramdisk.dmg -o ./rd_image/ramdisk -T rdsk -A -M ./apticket.der
- Cleanuprm ./ramdisk.dmg
 rm -rf ./rd_skel/
Booting the ramdisk
- Enter DFU mode
- pwn DFUcd ./bin/PyBoot/
 ./pyboot.py -p
- Send the files / commands with irecovery. Sometimes it helps to wait a second or two between sending images to give the device a chance to finish loading them.echo 'sending ibss (to jump to recovery mode)'
 irecovery -f ./iBSS.img4
 echo 'sending ibss again'
 irecovery -f ./iBSS.img4
 echo 'sending ibec'
 irecovery -f ./iBEC.img4
 echo 'loading ibec'
 irecovery -c go
 echo 'sending ramdisk'
 irecovery -f ./ramdisk
 echo 'loading ramdisk'
 irecovery -c ramdisk
 echo 'sending logo'
 irecovery -f ./applelogo.img4
 echo 'loading logo'
 irecovery -c 'setpicture 5'
 echo 'sending devicetree'
 irecovery -f ./devicetree.img4
 echo 'loading devicetree'
 irecovery -c devicetree
 echo 'sending trustcache'
 irecovery -f ./trustcache
 echo 'validating firmware against trustcache'
 irecovery -c firmware
 echo 'sending kernel'
 irecovery -f ./kernelcache.img4
 echo 'booting now'
 irecovery -c bootx
Connecting
- iproxyiproxy 2222:22 &
- SSH - password is alpinessh root@127.0.0.1 -p 2222
- When you're done, simply:reboot
Wrapping up
While there are some limitations to what we can do while connected to a device with an SSH ramdisk, this can be extremely useful for resolving certain issues. In the case of my friend, deleting a few corrupt files was all that was needed for the device to boot right up again!
I do want to mention that this process is untested on iOS 14. iOS 14 introduced a "feature" where the phone is able to detect whether a device was booted from DFU or not, and if it finds that it has been, the device will reboot. If you test this with iOS 14, please report your findings in the comments or let me know on twitter and I'll update this post.
Lastly, I'll include a few scripts you can use as a template to speed this process along. If they don't say "done" after running them, something has failed along the way and you'll have to debug that. These scripts aren't necessarily "out of the box"—you will have to modify them to fit your setup. With those caveats in mind, this should be a good starting point if you want to automate this process.
- build_bootchain.sh - don't forget to add the IV+KEY!
- make_rd.sh
- boot.sh
 











