├── 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 |
--------------------------------------------------------------------------------