├── enter_recovery.app ├── Icon_ └── Contents │ ├── PkgInfo │ ├── MacOS │ └── RecBoot │ ├── Resources │ ├── Icon.icns │ ├── irecovery │ └── English.lproj │ │ ├── MainMenu.nib │ │ └── InfoPlist.strings │ └── Info.plist ├── exit_recovery.app └── Contents │ ├── PkgInfo │ ├── Resources │ ├── Icon.icns │ ├── irecovery │ └── English.lproj │ │ ├── MainMenu.nib │ │ └── InfoPlist.strings │ ├── MacOS │ └── RecBoot Exit Only │ └── Info.plist ├── greenpois0n.app └── Contents │ ├── PkgInfo │ ├── MacOS │ ├── greenpois0n │ └── iBSS.k48ap │ ├── Frameworks │ └── libusb-1.0.dylib │ ├── Resources │ ├── greenpois0n.icns │ └── Credits.rtfd │ │ ├── TXT.rtf │ │ └── btn_donateCC_LG.gif │ └── Info.plist ├── 7za ├── genpass ├── xpwntool ├── irecovery-entropy ├── libusb-1.0.dylib ├── libusb-1.0.0.dylib ├── TODO ├── README.md └── keylimepie.sh /enter_recovery.app/Icon_: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /enter_recovery.app/Contents/PkgInfo: -------------------------------------------------------------------------------- 1 | APPL???? -------------------------------------------------------------------------------- /exit_recovery.app/Contents/PkgInfo: -------------------------------------------------------------------------------- 1 | APPL???? -------------------------------------------------------------------------------- /greenpois0n.app/Contents/PkgInfo: -------------------------------------------------------------------------------- 1 | APPLCDEV -------------------------------------------------------------------------------- /7za: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compilingEntropy/keylimepie/HEAD/7za -------------------------------------------------------------------------------- /genpass: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compilingEntropy/keylimepie/HEAD/genpass -------------------------------------------------------------------------------- /xpwntool: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compilingEntropy/keylimepie/HEAD/xpwntool -------------------------------------------------------------------------------- /irecovery-entropy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compilingEntropy/keylimepie/HEAD/irecovery-entropy -------------------------------------------------------------------------------- /libusb-1.0.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compilingEntropy/keylimepie/HEAD/libusb-1.0.dylib -------------------------------------------------------------------------------- /libusb-1.0.0.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compilingEntropy/keylimepie/HEAD/libusb-1.0.0.dylib -------------------------------------------------------------------------------- /enter_recovery.app/Contents/MacOS/RecBoot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compilingEntropy/keylimepie/HEAD/enter_recovery.app/Contents/MacOS/RecBoot -------------------------------------------------------------------------------- /greenpois0n.app/Contents/MacOS/greenpois0n: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compilingEntropy/keylimepie/HEAD/greenpois0n.app/Contents/MacOS/greenpois0n -------------------------------------------------------------------------------- /greenpois0n.app/Contents/MacOS/iBSS.k48ap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compilingEntropy/keylimepie/HEAD/greenpois0n.app/Contents/MacOS/iBSS.k48ap -------------------------------------------------------------------------------- /enter_recovery.app/Contents/Resources/Icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compilingEntropy/keylimepie/HEAD/enter_recovery.app/Contents/Resources/Icon.icns -------------------------------------------------------------------------------- /enter_recovery.app/Contents/Resources/irecovery: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compilingEntropy/keylimepie/HEAD/enter_recovery.app/Contents/Resources/irecovery -------------------------------------------------------------------------------- /exit_recovery.app/Contents/Resources/Icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compilingEntropy/keylimepie/HEAD/exit_recovery.app/Contents/Resources/Icon.icns -------------------------------------------------------------------------------- /exit_recovery.app/Contents/Resources/irecovery: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compilingEntropy/keylimepie/HEAD/exit_recovery.app/Contents/Resources/irecovery -------------------------------------------------------------------------------- /exit_recovery.app/Contents/MacOS/RecBoot Exit Only: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compilingEntropy/keylimepie/HEAD/exit_recovery.app/Contents/MacOS/RecBoot Exit Only -------------------------------------------------------------------------------- /greenpois0n.app/Contents/Frameworks/libusb-1.0.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compilingEntropy/keylimepie/HEAD/greenpois0n.app/Contents/Frameworks/libusb-1.0.dylib -------------------------------------------------------------------------------- /greenpois0n.app/Contents/Resources/greenpois0n.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compilingEntropy/keylimepie/HEAD/greenpois0n.app/Contents/Resources/greenpois0n.icns -------------------------------------------------------------------------------- /greenpois0n.app/Contents/Resources/Credits.rtfd/TXT.rtf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compilingEntropy/keylimepie/HEAD/greenpois0n.app/Contents/Resources/Credits.rtfd/TXT.rtf -------------------------------------------------------------------------------- /enter_recovery.app/Contents/Resources/English.lproj/MainMenu.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compilingEntropy/keylimepie/HEAD/enter_recovery.app/Contents/Resources/English.lproj/MainMenu.nib -------------------------------------------------------------------------------- /exit_recovery.app/Contents/Resources/English.lproj/MainMenu.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compilingEntropy/keylimepie/HEAD/exit_recovery.app/Contents/Resources/English.lproj/MainMenu.nib -------------------------------------------------------------------------------- /greenpois0n.app/Contents/Resources/Credits.rtfd/btn_donateCC_LG.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compilingEntropy/keylimepie/HEAD/greenpois0n.app/Contents/Resources/Credits.rtfd/btn_donateCC_LG.gif -------------------------------------------------------------------------------- /enter_recovery.app/Contents/Resources/English.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compilingEntropy/keylimepie/HEAD/enter_recovery.app/Contents/Resources/English.lproj/InfoPlist.strings -------------------------------------------------------------------------------- /exit_recovery.app/Contents/Resources/English.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/compilingEntropy/keylimepie/HEAD/exit_recovery.app/Contents/Resources/English.lproj/InfoPlist.strings -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | >Device specific keys for old devices 2 | >Fix the sed pipe madness 3 | >Support 8900 devices, the iPhone3,2, and the iPhone3,3 4 | >Remove Recboot dependency 5 | >Fix the temp files situation 6 | -------------------------------------------------------------------------------- /greenpois0n.app/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | greenpois0n 9 | CFBundleIconFile 10 | greenpois0n 11 | CFBundleIdentifier 12 | org.chronic-dev.greenpois0n 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | greenpois0n 17 | CFBundlePackageType 18 | APPL 19 | CFBundleSignature 20 | CDEV 21 | CFBundleVersion 22 | 1.0 23 | NSPrincipalClass 24 | NSApplication 25 | 26 | 27 | -------------------------------------------------------------------------------- /enter_recovery.app/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | RecBoot 9 | CFBundleIconFile 10 | Icon 11 | CFBundleIdentifier 12 | com.TheCoreDevTeam.RecBoot 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | RecBoot 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0.2 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | 10.5 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /exit_recovery.app/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | RecBoot Exit Only 9 | CFBundleIconFile 10 | Icon 11 | CFBundleIdentifier 12 | com.thecoredevteam.RecBoot-Exit-Only 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | RecBoot Exit Only 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0.2 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | 10.5 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | A tool for Mac that uses your iPhone or iPod Touch's AES engine to calculate keys/ivs for IPSW files. 2 | Written by compilingEntropy 3 | 4 | iRecovery-Entropy is based off of iRecovery by westbaer, which is based off of iRecovery by GreySyntax. Thanks to pod2g, tom3q, planetbeing, geohot, posixninja, ih8sn0w, westbaer, and greysyntax. 5 | 7zip is an open source project that can be found on http://7-zip.org. 6 | Recboot is an open source project by coredevteam that can be found on https://code.google.com/p/coredevteam/wiki/RecBoot. 7 | Genpass is used to generate rootfs keys (formerly known as vfdecrypt passwords), and was made by p0sixninja. It can be found on his github, https://github.com/posixninja/genpass. 8 | xpwntool is part of XPwn, which is a command line implementation of PwnageTool that is being maintained by planetbeing. It can be found on his github, https://github.com/planetbeing/xpwn. 9 | Email compilingEntropy@gmail.com or tweet @compiledEntropy for support, feedback, or bugs. 10 | 11 | usage: ./keylimepie.sh /Users/user/Downloads/iPod4,1_6.1.3_10B329_Restore.ipsw [-t3] 12 | 13 | supported devices: iPhone2,1; iPhone3,1; iPod2,1; iPod3,1; iPod 4,1 14 | 15 | supported firmware: tested on most firmwares between 3.0 and 7.1b5, if you test on firmware outside this window, please report your findings. 16 | -------------------------------------------------------------------------------- /keylimepie.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #Written by compilingEntropy 4 | #Email compilingEntropy@gmail.com or tweet @compiledEntropy for support, feedback, or bugs 5 | #usage: ./keylimepie.sh ./iPod4,1_6.1.3_10B329_Restore.ipsw [-t3] 6 | #supported devices: iPhone2,1; iPhone3,1; iPod2,1; iPod3,1; iPod 4,1 7 | #supported firmware: tested on most firmwares between 3.0 and 7.1b5; if you test on firmware outside this window, please report your findings 8 | #PS, sorry if this code makes your eyes bleed. It makes mine bleed, too. 9 | 10 | cd $(pwd) 11 | firmware=$1 12 | time=$2 13 | usage="usage: ./keylimepie.sh ./iPod4,1_6.1.3_10B329_Restore.ipsw [-t3]" 14 | 15 | #default time is 2, that's what's works for me. 16 | if [[ $time == "" ]]; then 17 | time=2 18 | fi 19 | 20 | #check to see if the time provided is valid, asks for new time if it isn't 21 | if [ $( echo $time | egrep -c "^([-][t]+[0-9][0-9]*)$" ) -ne 1 -a "$2" != "" ]; then 22 | echo "$time is not a supplorted parameter." 23 | echo "you can supply a sleep time like this '-t3'." 24 | echo "$usage" 25 | exit 26 | elif [ $( echo $time | sed 's|-t||g' ) -ge 15 ]; then 27 | echo "using sleep times longer than 15 is guaranteed to fail." 28 | echo "I recommend using 1, 2, 3, or 4." 29 | while ( [[ $( echo $time | egrep -c "^[0-9]{1,2}$" ) -ne 1 || $time -ge 15 ]] ) 30 | do 31 | echo "enter new sleep time:" 32 | read time 33 | if [ $( echo $time | egrep -c "^[0-9]+$" ) -ne 1 ]; then 34 | echo "invalid format, just enter a number like '3'." 35 | elif [ $time -ge 15 ]; then 36 | echo "choose a number less than 15. I recommend using 1, 2, 3, or 4." 37 | fi 38 | done 39 | echo "valid sleep time given, continuing..." 40 | fi 41 | 42 | #checks to see if you've given an ipsw file. 43 | #if you have, extract it and use it. 44 | #if not, it tries to use what's in the ./firmware folder. 45 | if [[ -z "$firmware" ]]; then 46 | echo "$usage" 47 | echo -n "checking to see if whatever's in the ./firmware/ folder can be used..." 48 | if [[ ! -d ./firmware/ ]]; then 49 | echo "" 50 | echo "no ./firmware directory exists, please provide an ipsw next time." 51 | exit 52 | fi 53 | if [ -e ./firmware/Restore.plist -a -e ./firmware/BuildManifest.plist -a $( ls ./firmware | grep -c ".dmg" ) -ge 2 -a $( ls ./firmware/ | wc -l | sed 's| ||g' ) -ge 10 ]; then 54 | echo "files found, i'll do my best." 55 | else 56 | echo "nope, please provide an ipsw next time." 57 | exit 58 | fi 59 | elif [[ -n "$firmware" ]]; then 60 | if [[ $( echo $firmware | grep -c .ipsw ) -ne 1 ]]; then 61 | echo "the supplied parameter was not an .ipsw file! please supply a valid .ipsw file." 62 | echo "$usage" 63 | exit 64 | fi 65 | if [[ -d ./firmware/ ]]; then 66 | if [[ $( ls ./firmware | wc -l ) -ne 0 ]]; then 67 | echo -n "old files found, cleaning..." 68 | rm -rf ./firmware 69 | echo "done." 70 | fi 71 | fi 72 | #count the number of useful files inside the ipsw 73 | let precount=$( ./7za l $firmware | grep -c "\.dfu" )+$( ./7za l $firmware | grep -c "\.img3" )+$( ./7za l $firmware | grep -c "\.dmg" )+$( ./7za l $firmware | grep -c "kernelcache" )+$( ./7za l $firmware | grep -c 'Restore\.plist' )+$( ./7za l $firmware | grep -c "BuildManifest\.plist" ) 74 | #check the ipsw for a restore.plist, at least 2 ramdisks, and more than 10 useful files overall 75 | if [ $( ./7za l $firmware | grep -c "Restore.plist" ) -ne 1 -a $( ./7za l $firmware | grep -c ".dmg" ) -lt 2 -a $precount -le 10 ]; then 76 | echo "this ipsw isn't supported, please contact me and tell me what you're using so I can support it." 77 | echo "I'm on twitter @compiledEntropy." 78 | exit 79 | fi 80 | echo "extracting files..." 81 | ./7za e $firmware -o"./firmware" 82 | #count the number of useful files extracted 83 | let postcount=$( ls ./firmware | grep -c "\.dfu" )+$( ls ./firmware | grep -c "\.img3" )+$( ls ./firmware | grep -c "\.dmg" )+$( ls ./firmware | grep -c "kernelcache" )+$( ls ./firmware | grep -c "Restore\.plist" )+$( ls ./firmware | grep -c "BuildManifest\.plist" ) 84 | #if they aren't the same, bail 85 | if [ $postcount -eq $precount ]; then 86 | echo "extracted successfully!" 87 | else 88 | echo "something went wrong with the extracting process, please try again." 89 | exit 90 | fi 91 | fi 92 | 93 | #set up the output directory 94 | if [[ ! -d ./output/ ]]; then 95 | mkdir ./output/ 96 | fi 97 | 98 | #warn user that root will be required 99 | if [ ! -d /usr/local/lib/ -o ! -e /usr/local/lib/libusb-1.0.dylib -o ! -e /usr/local/lib/libusb-1.0.0.dylib ]; then 100 | echo "setting up libraries (this only happens once), please enter your password." 101 | 102 | #set up the library that irecovery needs 103 | if [[ ! -d /usr/local/lib/ ]]; then 104 | sudo mkdir -p /usr/local/lib/ 105 | fi 106 | if [[ ! -e /usr/local/lib/libusb-1.0.dylib ]]; then 107 | sudo cp ./libusb-1.0.dylib /usr/local/lib/ 108 | fi 109 | if [[ ! -e /usr/local/lib/libusb-1.0.0.dylib ]]; then 110 | sudo cp ./libusb-1.0.0.dylib /usr/local/lib/ 111 | fi 112 | 113 | #check for success 114 | if [ ! -d /usr/local/lib/ -o ! -e /usr/local/lib/libusb-1.0.dylib -o ! -e /usr/local/lib/libusb-1.0.0.dylib ]; then 115 | echo "setting up libraries failed, make sure your username is in the sudoers file." 116 | exit 117 | fi 118 | 119 | fi 120 | 121 | echo -n "grabbing keybags..." 122 | 123 | cd ./firmware/ 124 | 125 | #parse the ./restore.plist file to find out which .dmg file is which, and store them to an array. 126 | #I'm sure this line could be optimized. 127 | dmgfiles=( $( echo "$( cat ./Restore.plist | grep SystemRestoreImages -A 4 | grep .dmg | sed 's|||g' | sed 's|||g' | sed 's/[[:space:]]//g' )" "$( cat ./Restore.plist | grep RestoreRamDisks -A 6 | grep Update -A 1 | grep .dmg | sed 's|||g' | sed 's|||g' | sed 's/[[:space:]]//g' )" "$( cat ./Restore.plist | grep RestoreRamDisks -A 6 | grep User -A 1 | grep .dmg | sed 's|||g' | sed 's|||g' | sed 's/[[:space:]]//g' )" ) ) 128 | #resulting array: 129 | #dmgfiles[0] = rootfs 130 | #dmgfiles[1] = updatedmg 131 | #dmgfiles[2] = restoredmg 132 | 133 | #parse the ./Restore.plist and ./BuildManifest.plist files to find informations and store them to an array. 134 | #longest line of code award 135 | ipsw=( $( echo "$( cat ./Restore.plist | grep 'ProductVersion' -A 1 | grep 'string' | sed 's|||g' | sed 's|||g' | sed 's/[[:space:]]//g' )" "$( cat ./Restore.plist | grep 'ProductBuildVersion' -A 1 | grep 'string' | sed 's|||g' | sed 's|||g' | sed 's/[[:space:]]//g' )" "$( cat ./Restore.plist | grep 'ProductType' -A 1 | grep 'string' | sed 's|||g' | sed 's|||g' | sed 's/[[:space:]]//g' )" "$( cat ./BuildManifest.plist | grep 'Erase' -B 9 | grep 'BuildTrain' -A 1 | grep 'string' | sed 's|||g' | sed 's|||g' | sed 's/[[:space:]]//g' )" "$( cat ./Restore.plist | grep 'BoardConfig' -A 1 | grep 'string' | sed 's|||g' | sed 's|||g' | sed 's/[[:space:]]//g' )" "$( cat ./Restore.plist | grep 'Platform' -A 1 | grep 'string' | sed 's|||g' | sed 's|||g' | sed 's/[[:space:]]//g' )" ) ) 136 | ipsw[6]=$( grep -m 1 "\.bbfw" "./BuildManifest.plist" | egrep -o "(0?[0-9]\.[0-9]{2}\.[0-9]{2})" ) 137 | #resulting array: 138 | #ipsw[0] = version 139 | #ipsw[1] = build 140 | #ipsw[2] = device 141 | #ipsw[3] = codename 142 | #ipsw[4] = deviceclass 143 | #ipsw[5] = platform 144 | #ipsw[6] = baseband 145 | 146 | #get deviceclass prefix by removing 'ap' 147 | classprefix=$( echo "${ipsw[4]}" | sed 's|ap||g' ) 148 | 149 | #get the download url using seejy's api 150 | url=$( curl -s -A "keylimepie" http://api.ios.icj.me/v2/${ipsw[2]}/${ipsw[1]}/url ) 151 | if [[ -z $url ]]; then 152 | echo "couldn't find IPSW download url!" 153 | echo "this is probably a beta IPSW, continuing..." 154 | url="TODO" 155 | fi 156 | 157 | #theiphonewiki wants the device to look like 'iphone31' instead of "iPhone3,1" 158 | #not really sure why, but whatevs. When I support appletv, this will be different. 159 | ipsw[2]=$( echo "${ipsw[2]}" | sed 's|P|p|g' | sed 's|,||g' ) 160 | 161 | #build an index of sorts for the above ipsw array 162 | ipswindex=( "Version" "Build" "Device" "Codename" ) 163 | 164 | #remove all the ipsw's files and folders that we don't care about 165 | rm -rf $( ls | grep -v .img3 | grep -v .dfu | grep -v .dmg | grep -v kernelcache | grep -v Restore.plist | grep -v BuildManifest.plist ) 166 | 167 | #the files need to be in alphabetical order when we output them at the end. 168 | #I used the built in lexicographical ordering in 'ls' to accomplish this. 169 | #in order to order the files correctly, ls needs all the files to be the same case. 170 | #this stores a list of files that aren't lower case. 171 | tmpcapfiles=( "iBSS" "iBEC" "iBoot" "DeviceTree" "LLB" ) 172 | 173 | #turn the partial file names above into full filenames, store to an array 174 | for file in "${tmpcapfiles[@]}"; do 175 | capfiles=( "${capfiles[@]}" "$( ls | grep $file )" ) 176 | done 177 | 178 | #rename the files to a lower case version 179 | for file in "${capfiles[@]}"; do 180 | if [[ -e $file ]]; then 181 | mv ./$file ./$( echo $file | sed 's|iBSS|ibss|g' | sed 's|iBEC|ibec|g' | sed 's|iBoot|iboot|g' | sed 's|DeviceTree|devicetree|g' | sed 's|LLB|llb|g' ) 182 | fi 183 | done 184 | 185 | #when we do 'ls', it already has the files sorted into alphabetical order 186 | files=( $( ls ) ) 187 | #remove the rootfs .dmg file from the array, we'll get that key a different way 188 | files=( ${files[@]/${dmgfiles[0]}/} ) 189 | #remove the restore.plist and build.manifest files from the array, they doesn't have keys/ivs 190 | files=( ${files[@]/Restore.plist/} ) 191 | files=( ${files[@]/BuildManifest.plist/} ) 192 | 193 | cd ../ 194 | 195 | #generate the keybags for each file. we'll need to pipe these into the ithing later. 196 | for file in "${files[@]}"; do 197 | keybags=( "${keybags[@]}" "$( ./xpwntool ./firmware/$file /dev/null | sed 's/[[:space:]]//g' | sed 's/^.*://g' )" ) 198 | done 199 | 200 | #if something went wrong when getting the keybag and one turned up empty, set it to 'none' 201 | #this also happens if apple releases a firmware that has a non-encrypted file (like some of the 5.x betas) 202 | for (( i = 0; i < ${#keybags[@]}; i++ )); do 203 | if [ -z "${keybags[$i]}" ]; then 204 | keybags[$i]='None' 205 | fi 206 | done 207 | 208 | #if a file already exists, delete it. i want to use fewer temporary files, but irecovery sucks. 209 | if [[ -e ./output/keybags.txt ]]; then 210 | rm -rf ./output/keybags.txt 211 | fi 212 | if [[ -e ./aesdec ]]; then 213 | rm -rf ./aesdec 214 | fi 215 | if [[ -e ./setenv ]]; then 216 | rm -rf ./setenv 217 | fi 218 | if [[ -e ./output/keys.txt ]]; then 219 | rm -rf ./output/keys.txt 220 | fi 221 | if [[ -e ./output/wikikeys.txt ]]; then 222 | rm -rf ./output/wikikeys.txt 223 | fi 224 | 225 | echo "done!" 226 | 227 | #generate a file that contains all the keybags, and changes the names back to upper case. 228 | #I'd like to be able to accept these keybags.txt files as input eventually, but I can't figure a way around the need for the restore.plist file. 229 | for (( i = 0; i < ${#files[@]}; i++ )); do 230 | echo "${files[$i]}: ${keybags[$i]}" | sed 's|\./||g' | sed 's|ibss|iBSS|g' | sed 's|ibec|iBEC|g' | sed 's|iboot|iBoot|g' | sed 's|devicetree|DeviceTree|g' | sed 's|llb|LLB|g' >> ./output/keybags.txt 231 | done 232 | 233 | #generate a payload that will run the aes engine a bunch of times. 234 | #irecovery sucks, so we have to do it this way. 235 | for key in "${keybags[@]}"; do 236 | if [ "$key" != "None" ]; then 237 | echo "go aes dec $key" >> ./aesdec 238 | fi 239 | done 240 | 241 | #generate a payload that fixes the resultant white screen at the end 242 | echo "setenv auto-boot false" >> ./fixwhite 243 | echo "saveenv" >> ./fixwhite 244 | echo "reboot" >> ./fixwhite 245 | 246 | #generate a payload that keeps the device from popping back into recovery mode when we run greenpois0n 247 | echo "setenv boot-args 2" >> ./setenv 248 | echo "setenv auto-boot false" >> ./setenv 249 | echo "saveenv" >> ./setenv 250 | 251 | #i'll let you guess what this one does 252 | echo "reboot" > ./reboot 253 | 254 | #go into recovery mode if you aren't already there. 255 | #if you are already there, reboot. 256 | #the timing for this is picky for some reason, so if you don't reboot you can get major problems. 257 | #irecovery sucks. 258 | while (true); 259 | do 260 | echo "is your device currently in recovery mode? (y/n)" 261 | read answer 262 | if [[ $answer == "n" ]]; then 263 | open ./enter_recovery.app #i'd like to move away from recboot, but I can't figure out how to kick a device into recovery mode. go figure. 264 | echo "click 'enter recovery'. when you see the 'connect to itunes' logo, press 'enter'." 265 | read 266 | break 267 | elif [[ $answer == "y" ]]; then 268 | #yeah, so you can't just execute the payload. 269 | #you have to make a file that runs the payload, and run that. 270 | #the file i use for this is ./batch 271 | #irecovery sucks 272 | echo "/batch reboot" > ./batch 273 | ./irecovery-entropy -b ./batch > /dev/null 274 | sleep 7 #wait for device to reboot 275 | break 276 | else 277 | echo "not a valid reponse; valid responses are 'y', or 'n'." 278 | fi 279 | done 280 | 281 | #set up the next payload 282 | echo "/batch setenv" > ./batch 283 | 284 | #kill recboot if it's still open 285 | sleep 2 286 | if [[ $( pgrep RecBoot ) != "" ]]; then 287 | killall RecBoot 288 | fi 289 | 290 | #run the payload ./setenv 291 | ./irecovery-entropy -b ./batch > /dev/null 292 | 293 | echo "put your device in DFU mode, then press 'enter'." 294 | read 295 | 296 | #pois0n stuff 297 | #i write the log file so that I can find out exactly when greenpois0n is done later. 298 | #the timing is important apparently. 299 | sleep 3 300 | ./greenpois0n.app/Contents/MacOS/greenpois0n &> ./gplog.txt & 301 | echo "click 'jailbreak'." 302 | 303 | #parse the log file very inefficiently in order to know the moment greenpois0n finishes 304 | isready=0 305 | while( [[ $isready -lt 1 ]] ); do 306 | isready=$( cat ./gplog.txt | grep -c "Exiting libpois0n" ) 307 | done 308 | 309 | sleep 0.5 310 | kill $( pgrep greenpois0n ) #death 311 | echo "killed. >:D" #tell people we're killing stuff so they don't freak out when they see terminator stuff on their terminal 312 | ################ 313 | sleep $time #this is what you change if something goes horribly wrong. the default is 2, you can change it with -t. use -t3 to change it to 3, for example. 314 | ################ 315 | 316 | #set up the ./aesdec payload 317 | echo "/batch aesdec" > ./batch 318 | #run the payload 319 | ./irecovery-entropy -b ./batch > /dev/null 320 | sleep 3 321 | 322 | ## 323 | #this one is interesting. 324 | #i had to recompile irecovery and break it in order to get the output from the ./aesdec payload. 325 | #apparently, the only way to get the output is to do './irecovery -s'. 326 | #irecovery -s also happens to pull a shell from the device, and i couldn't find a graceful way to exit the shell from this script. 327 | #consequently, I had to modify irecovery and tell it to exit the shell as soon as it was done pulling it up. 328 | #this is also not graceful, but it's much prettier than anything else I could come up with. 329 | #other than that difference, irecovery-entropy is the same as irecovery by westbaer. 330 | ## 331 | ./irecovery-entropy -s > ./output.log #put it in a log file so we can read it later 332 | sleep 3 #i could use a nap too, eh? 333 | 334 | #set up the ./fixwhite payload 335 | echo "/batch fixwhite" > ./batch 336 | #run the ./fixwhite payload 337 | ./irecovery-entropy -b ./batch > /dev/null 338 | 339 | echo "" 340 | 341 | #turn ./output.log into a list of keys 342 | cat ./output.log | grep -a "iv" > ./rawkeys.txt 343 | #get rid of all the crap in between and make an array out of the keys 344 | keys=( `cat "./rawkeys.txt" | sed 's/[[:space:]]//g' | sed 's/-iv//g' | sed 's/-k/ /g' | sed 's/-/ /g' ` ) 345 | #resulting array: 346 | #keys[0] = iv for files[0] 347 | #keys[1] = key for files[0] 348 | #keys[2] = iv for files[1] 349 | #keys[3] = key for files[1] 350 | #etc. 351 | 352 | ##fix for a bizarre case where irecovery tries to print two things at the same time 353 | #keys[5] is always the one affected 354 | #irecovery prints keys[0]-keys[4] with no issue. on keys[5], it prints the first few characters, then part of the word 'action'. 355 | #irecovery later goes on to print all keys, starting with keys[0], without issue. 356 | #the fix for this is to remove the first 6 keys from the array. 357 | if [ $( echo "${keys[5]}" | grep -c "ction" ) -eq 1 -a $( cat ./output.log | grep -c "Greenpois0n initialized" ) -ge 1 -a ${#keys[@]} -eq 40 ]; then 358 | keys=( ${keys[@]:6} ) 359 | fi 360 | 361 | #checks to see if any keys are corrupt. 362 | corrupt=0 363 | #sometimes, all the keys are corrput. in that case, keys are duplicated and repeated throughout the output. 364 | #if any keys are repeated, keys[10] or keys[11] will also be repeated. 365 | #most commonly, the keys will be repeated every 6 places, so keys[10] would be the same as keys[16] 366 | #check that first, then check for any other duplications. 367 | for (( i = 0; i < ${#keys[@]}; i++ )); do 368 | if [ "${keys[10]}" == "${keys[16]}" -o "${keys[11]}" == "${keys[17]}" -o "${keys[10]}" == "${keys[$i]}" -o "${keys[11]}" == "${keys[$i]}" ] && [ $i -ne 10 -a $i -ne 11 ]; then 369 | corrupt=2 #all keys are corrupt, none are valid 370 | fi 371 | done 372 | #sometimes only one key is corrupt. in this case, all other keys could still be valid. 373 | for (( i = 0; i < ${#files[@]}*2+1; i++ )); do 374 | if [[ -z "${keys[$i]}" ]]; then 375 | #if something went wrong and a key is empty, set it as 'TODO' 376 | keys[$i]="TODO" 377 | elif [ $corrupt -eq 2 ]; then 378 | #if all keys are corrupt, replace the text for each key with 'Corrupt!' 379 | keys[$i]="Corrupt!" 380 | elif [ $( echo ${keys[$i]} | egrep -c ^[0-9a-f]+$ ) -ne 1 -o ${#keys[$i]} -gt 65 -o ${#keys[$i]} -lt 31 ] && [ "${keybags[$i]}" != "None" ]; then 381 | #if a key isn't between 32(iv) and 64(key) characters and also hexidecimal, it is corrupt 382 | keys[$i]="Corrupt!" 383 | if [ $corrupt -ne 2 ]; then 384 | corrupt=1 #some keys are corrupt, some could be valid 385 | fi 386 | fi 387 | done 388 | 389 | #removes the file extension from the .dmg files 390 | cleandmg=( $( echo "${dmgfiles[@]}" | sed 's|\.dmg||g' ) ) 391 | 392 | #in order to calculate the rootfskey, you have to decrypt either dmgfiles[1] or dmgfiles[2] using xpwntool. 393 | #I chose to use dmgfiles[1] for no real reason, if dmgfiles[2] is better then feel free to change it. 394 | #here, we find where in files[] dmgfiles[1] is located. 395 | let j=0 396 | for file in "${files[@]}"; do 397 | if [ $( echo "$file" | grep -c ${dmgfiles[1]} ) -eq 1 ]; then 398 | let offset1=$j*2 399 | break 400 | fi 401 | ((j++)) 402 | done 403 | #store the key and iv for the dmgfiles[1] to variables 404 | dmgiv="${keys[$offset1]}" 405 | dmgkey="${keys[$offset1+1]}" 406 | 407 | #find the rootfskey 408 | if [ "$dmgiv" != "TODO" -a "$dmgkey" != "TODO" -a "$dmgiv" != "Corrupt!" -a "$dmgkey" != "Corrupt!" ]; then #if the key and iv for dmgfiles[1] are valid, proceed 409 | ./xpwntool ./firmware/${dmgfiles[1]} ./firmware/dec.dmg -iv $dmgiv -k $dmgkey > /dev/null #cook up a decrypted .dmg file to be used with genpass 410 | rootfskey=$( ./genpass ${ipsw[5]} ./firmware/dec.dmg ./firmware/${dmgfiles[0]} | sed 's/[[:space:]]//g' | sed 's|vfdecryptkey\:||g' ) #use the dec.dmg for decrypting the rootfs, which is dmgfiles[0] 411 | fi 412 | 413 | #delete the dec.dmg file so it doesn't get in the way, and because we no longer need it## 414 | if [[ -e ./firmware/dec.dmg ]]; then 415 | rm -rf ./firmware/dec.dmg 416 | fi 417 | 418 | #if the rootfskey isn't here or if the keys used to make it were corrupt, say so 419 | if [[ -z "$rootfskey" ]]; then 420 | rootfskey="TODO" 421 | elif [ $corrupt -eq 2 ]; then 422 | rootfskey="Corrupt!" 423 | fi 424 | 425 | #output the rootfskey to a file 426 | echo "${dmgfiles[0]}: -k $rootfskey" >> ./output/keys.txt 427 | 428 | #output the rest of the keys to that same file, fixing the lower/upper case issue as we go 429 | let j=0 430 | for (( i = 0; i < ${#files[@]}; i++ )); do 431 | let "j = $i * 2" 432 | echo "${files[$i]}: -iv ${keys[$j]} -k ${keys[$j+1]}" | sed 's|\./||g' | sed 's|ibss|iBSS|g' | sed 's|ibec|iBEC|g' | sed 's|iboot|iBoot|g' | sed 's|devicetree|DeviceTree|g' | sed 's|llb|LLB|g' >> ./output/keys.txt 433 | done 434 | 435 | echo "{{keys" >> ./output/wikikeys.txt 436 | 437 | #print out basic information about the ipsw, like build and version. 438 | for (( i = 0; i < ${#ipswindex[@]}; i++ )); do 439 | let spacing=20-${#ipswindex[$i]} #in order to make the spacing nice and even, do 20-$numberofcharactersinarrayelement and print that many spaces 440 | 441 | info=" | ${ipswindex[$i]}" 442 | for (( j = $spacing; j > 0; j-- )); do 443 | info+=" " 444 | done 445 | info+="= ${ipsw[$i]}" 446 | 447 | echo "$info" >> ./output/wikikeys.txt 448 | done 449 | 450 | #check if there's a baseband, print it if there is 451 | if [[ -n "$ipsw[6]" ]]; then 452 | echo " | Baseband = ${ipsw[6]}" >> ./output/wikikeys.txt 453 | fi 454 | 455 | #give the download url according to seejy's api 456 | echo " | DownloadURL = $url" >> ./output/wikikeys.txt 457 | 458 | #the dmg files need to be output in a static order, not a lexicographical order. 459 | #the order is always dmgfiles[0], dmgfiles[1], then dmgfiles[2] (almost like i planned it that way) 460 | #i feel like something about this for loop could be written better, but i haven't figured out a better way to do it yet 461 | let i=0 462 | for dmgfile in "${cleandmg[@]}"; do 463 | if [[ $i -ne 0 ]]; then 464 | let j=0 465 | for file in "${files[@]}"; do 466 | #find where in the array the file we're looking for is located 467 | if [ $( echo "$file" | grep -c $dmgfile ) -eq 1 ]; then 468 | let offset2=$j*2 469 | break 470 | fi 471 | ((j++)) 472 | done 473 | #store the key and iv for the dmgfiles[$i] to variables 474 | dmgiv="${keys[$offset2]}" 475 | dmgkey="${keys[$offset2+1]}" 476 | fi 477 | 478 | #set the dmgtype depending on which file you're looking at 479 | if [[ $i -eq 0 ]]; then 480 | dmgtype="RootFS" 481 | dmgkey="$rootfskey" 482 | elif [[ $i -eq 1 ]]; then 483 | dmgtype="UpdateRamdisk" 484 | elif [[ $i -eq 2 ]]; then 485 | dmgtype="RestoreRamdisk" 486 | fi 487 | 488 | #in order to make the spacing nice and even, do 17-$numberofcharactersinarrayelement and print that many spaces 489 | let spacing=17-${#dmgtype} 490 | 491 | filedmg=" | $dmgtype" 492 | for (( k = $spacing; k >= 0; k-- )); do 493 | filedmg+=" " 494 | done 495 | filedmg+=" =" 496 | 497 | fileiv=" | $dmgtype" 498 | fileiv+="IV" 499 | for (( k = $spacing; k >= 0; k-- )); do #use >= because 'iv' has one fewer character than 'key' or 'dmg' 500 | fileiv+=" " 501 | done 502 | fileiv+="=" 503 | 504 | filekey=" | $dmgtype" 505 | filekey+="Key" 506 | for (( k = $spacing; k > 0; k-- )); do 507 | filekey+=" " 508 | done 509 | filekey+="=" 510 | 511 | #output the nice and purdy dmg lines to the wikikeys.txt file 512 | echo "" >> ./output/wikikeys.txt 513 | echo "$filedmg $dmgfile" >> ./output/wikikeys.txt 514 | if [ $i -ne 0 ]; then #the rootfs (dmgfiles[0]) doesn't have an iv 515 | echo "$fileiv $dmgiv" >> ./output/wikikeys.txt 516 | fi 517 | echo "$filekey $dmgkey" >> ./output/wikikeys.txt 518 | 519 | ((i++)) 520 | done 521 | 522 | #WOAH UGLY 523 | #longest line ever, fix this someday 524 | #turns './ibss.n90ap.RELEASE.dfu' into 'iBSS' and stuff like that 525 | cleanfiles=( $( echo "${files[@]}" | sed 's|\./||g' | sed 's|\.dfu||g' | sed 's|\.dmg||g' | sed 's|\.img3||g' | sed 's|\.release||g' | sed 's|\.RELEASE||g' | sed 's|~iphone||g' | sed 's|-30pin||g' | sed 's|@2x\.||g' | sed "s|\.${ipsw[4]}||g" | sed "s|${ipsw[5]}||g" | sed 's|applelogo|AppleLogo|g' | sed 's|batterycharging|BatteryCharging|g' | sed 's|batteryfull|BatteryFull|g' | sed 's|batterylow|BatteryLow|g' | sed 's|glyphcharging|GlyphCharging|g' | sed 's|glyphplugin|GlyphPlugin|g' | sed 's|kernelcache\.|Kernelcache|g' | sed "s|$classprefix||g" | sed 's|recoverymode|RecoveryMode|g' | sed 's|ibss|iBSS|g' | sed 's|ibec|iBEC|g' | sed 's|iboot|iBoot|g' | sed 's|devicetree|DeviceTree|g' | sed 's|llb|LLB|g' | sed 's|needservice|NeedService|g' | sed 's|\.||g' ) ) 526 | 527 | #print the results to a beautyful text file 528 | let j=0 529 | for (( i = 0; i < ${#files[@]}; i++ )); do 530 | if [ ! $( echo ${files[$i]} | grep -c .dmg) -eq 1 ]; then 531 | let spacing=17-${#cleanfiles[$i]} #in order to make the spacing nice and even, do 17-$numberofcharactersinarrayelement and print that many spaces 532 | 533 | fileiv=" | ${cleanfiles[$i]}IV" 534 | for (( k = $spacing; k >= 0; k-- )); do 535 | fileiv+=" " 536 | done 537 | fileiv+="=" 538 | 539 | filekey=" | ${cleanfiles[$i]}Key" 540 | for (( k = $spacing; k > 0; k-- )); do 541 | filekey+=" " 542 | done 543 | filekey+="=" 544 | 545 | filename=" | ${cleanfiles[$i]}" 546 | for (( k = $spacing; k >= 0; k-- )); do 547 | filename+=" " 548 | done 549 | filename+=" =" 550 | 551 | #the wikikeys file is oh so growgeous 552 | echo "" >> ./output/wikikeys.txt 553 | echo "$filename ${files[$i]}" | sed 's|ibss|iBSS|g' | sed 's|ibec|iBEC|g' | sed 's|iboot|iBoot|g' | sed 's|devicetree|DeviceTree|g' | sed 's|llb|LLB|g' >> ./output/wikikeys.txt 554 | if [ "${keybags[$i]}" != "None" ]; then 555 | let "j = $i * 2" 556 | echo "$fileiv ${keys[$j]}" >> ./output/wikikeys.txt 557 | echo "$filekey ${keys[$j+1]}" >> ./output/wikikeys.txt 558 | else #in case something doesn't exist 559 | echo "$fileiv None" >> ./output/wikikeys.txt 560 | echo "$filekey None" >> ./output/wikikeys.txt 561 | fi 562 | fi 563 | done 564 | 565 | echo "}}" >> ./output/wikikeys.txt 566 | 567 | #if everything didn't explode, show the results 568 | if [[ $corrupt -ne 2 ]]; then 569 | cat ./output/keys.txt 570 | fi 571 | 572 | #that's a lot of temporary files. make it fewer someday, or put it in a ./tmp folder or something. 573 | rm -rf ./iBSS* ./irecovery.log ./reboot ./setenv ./fixwhite ./aesdec ./batch ./gplog.txt ./rawkeys.txt ./output.log #./tmp 574 | 575 | echo "" 576 | echo "finished!" 577 | if [[ $corrupt -eq 1 ]]; then #some errors, warn the user 578 | echo "WARNING!" 579 | echo "some of the keys were corrupt, you should try this ipsw again to get those keys." 580 | echo "it's very possible that even keys that aren't marked 'corrupt' are incorrect." 581 | elif [[ $corrupt -eq 2 ]]; then #everything is borked 582 | echo "ERROR!" 583 | echo "something went horribly wrong. try the program again on this ipsw to get those keys." 584 | echo "if this happens often, try changing the sleep timer with the -t flag." 585 | echo "do '$usage' to change it to 3, for example." | sed 's|\[||g' | sed 's|\]||g' | sed 's|usage: ||g' 586 | #if this happens >30% of the time, try changing the sleep timer with the -t flag. do -t3 to change it to 3, for example. 587 | fi 588 | 589 | #exits recovery for you if you want to 590 | while (true); 591 | do 592 | echo "would you like to exit recovery? (y/n)" 593 | read answer 594 | if [[ $answer == "n" ]]; then 595 | exit 596 | elif [[ $answer == "y" ]]; then 597 | sleep 3 598 | ./irecovery-entropy -a > /dev/null #kicks you out of recovery mode 599 | exit 600 | else 601 | echo "not a valid reponse; valid responses are 'y', or 'n'." 602 | fi 603 | done 604 | --------------------------------------------------------------------------------