-
Notifications
You must be signed in to change notification settings - Fork 17
/
ipwndfu
372 lines (319 loc) · 16.1 KB
/
ipwndfu
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
#!/usr/bin/python3
# ipwndfu: open-source jailbreaking tool for older iOS devices
# Author: axi0mX
import binascii, datetime, getopt, hashlib, struct, sys, time
import dfu, nor, utilities
import alloc8, checkm8, image3_24Kpwn, limera1n, SHAtter, steaks4uce, usbexec
from dfuexec import *
def print_help():
print('USAGE: ipwndfu [options]')
print('Interact with an iOS device in DFU Mode.\n')
print('Basic options:')
print(' -p\t\t\t\tUSB exploit for pwned DFU Mode')
print(' -x\t\t\t\tinstall alloc8 exploit to NOR')
print(' -f file\t\t\tsend file to device in DFU Mode')
print('Advanced options:')
print(' --demote\t\t\tdemote device to enable JTAG')
print(' --dump=address,length\t\tdump memory to stdout')
print(' --hexdump=address,length\thexdump memory to stdout')
print(' --dump-rom\t\t\tdump SecureROM')
print(' --dump-nor=file\t\tdump NOR to file')
print(' --flash-nor=file\t\tflash NOR (header and firmware only) from file')
print(' --24kpwn\t\t\tinstall 24Kpwn exploit to NOR')
print(' --remove-24kpwn\t\tremove 24Kpwn exploit from NOR')
print(' --remove-alloc8\t\tremove alloc8 exploit from NOR')
print(' --decrypt-gid=hexdata\t\tAES decrypt with GID key')
print(' --encrypt-gid=hexdata\t\tAES encrypt with GID key')
print(' --decrypt-uid=hexdata\t\tAES decrypt with UID key')
print(' --encrypt-uid=hexdata\t\tAES encrypt with UID key')
if __name__ == '__main__':
try:
advanced = ['demote', 'dump=', 'hexdump=', 'dump-rom', 'dump-nor=', 'flash-nor=', '24kpwn', 'remove-24kpwn', 'remove-alloc8', 'decrypt-gid=', 'encrypt-gid=', 'decrypt-uid=', 'encrypt-uid=']
opts, args = getopt.getopt(sys.argv[1:], 'pxf:', advanced)
except getopt.GetoptError:
print('ERROR: Invalid arguments provided.')
print_help()
sys.exit(2)
if len(opts) == 0:
print_help()
sys.exit(2)
for opt, arg in opts:
if opt == '-p':
device = dfu.acquire_device()
serial_number = device.serial_number
dfu.release_device(device)
if 'CPID:8720' in serial_number:
steaks4uce.exploit()
elif 'CPID:8920' in serial_number:
limera1n.exploit()
elif 'CPID:8922' in serial_number:
limera1n.exploit()
elif 'CPID:8930' in serial_number:
SHAtter.exploit()
elif 'CPID:8947' in serial_number:
checkm8.exploit()
elif 'CPID:8950' in serial_number:
checkm8.exploit()
elif 'CPID:8955' in serial_number:
checkm8.exploit()
elif 'CPID:8960' in serial_number:
checkm8.exploit()
elif 'CPID:8002' in serial_number:
checkm8.exploit()
elif 'CPID:8004' in serial_number:
checkm8.exploit()
elif 'CPID:8010' in serial_number:
checkm8.exploit()
elif 'CPID:8011' in serial_number:
checkm8.exploit()
elif 'CPID:8015' in serial_number:
checkm8.exploit()
else:
print('Found:', serial_number)
print('ERROR: This device is not supported.')
sys.exit(1)
if opt == '-x':
device = PwnedDFUDevice()
if device.config.cpid != '8920':
print('This is not a compatible device. alloc8 exploit is for iPhone 3GS only.')
sys.exit(1)
if device.config.version == '359.3':
print('WARNING: iPhone 3GS (old bootrom) was detected. Use 24Kpwn exploit for faster boots, alloc8 exploit is for testing purposes only.')
input("Press ENTER to continue.")
print('Installing alloc8 exploit to NOR.')
dump = device.nor_dump(saveBackup=True)
nor = nor.NorData(dump)
for byte in nor.parts[1]:
if byte != '\x00':
print('ERROR: Bytes following IMG2 header in NOR are not zero. alloc8 exploit was likely previously installed. Exiting.')
sys.exit(1)
if len(nor.images) == 0 or len(nor.images[0]) < 0x24000:
print('ERROR: 24Kpwn LLB was not found. You must restore a custom 24Kpwn IPSW before using this exploit.')
sys.exit(1)
print('Preparing modified NOR with alloc8 exploit.')
# Remove 24Kpwn first.
nor.images[0] = image3_24Kpwn.remove_exploit(nor.images[0])
new_nor = alloc8.exploit(nor, device.config.version)
device.flash_nor(new_nor.dump())
if opt == '-f':
try:
with open(arg, 'rb') as f:
data = f.read()
except IOError:
print('ERROR: Could not read file:', arg)
sys.exit(1)
device = dfu.acquire_device()
dfu.reset_counters(device)
dfu.send_data(device, data)
dfu.request_image_validation(device)
dfu.release_device(device)
if opt == '--demote':
device = dfu.acquire_device()
serial_number = device.serial_number
dfu.release_device(device)
if 'PWND:[checkm8]' in serial_number:
pwned = usbexec.PwnedUSBDevice()
old_value = pwned.read_memory_uint32(pwned.platform.demotion_reg)
print('Demotion register: 0x%x' % old_value)
if old_value & 1:
print('Attempting to demote device.')
pwned.write_memory_uint32(pwned.platform.demotion_reg, old_value & 0xFFFFFFFE)
new_value = pwned.read_memory_uint32(pwned.platform.demotion_reg)
print('Demotion register: 0x%x' % new_value)
if old_value != new_value:
print('Success!')
else:
print('Failed.')
else:
print('WARNING: Device is already demoted.')
else:
print('ERROR: Demotion is only supported on devices pwned with checkm8 exploit.')
sys.exit(1)
if opt == '--dump':
if arg.count(',') != 1:
print('ERROR: You must provide exactly 2 comma separated values: address,length')
sys.exit(1)
raw_address, raw_length = arg.split(',')
address = int(raw_address, 16) if raw_address.startswith('0x') else int(raw_address, 10)
length = int(raw_length, 16) if raw_length.startswith('0x') else int(raw_length, 10)
device = dfu.acquire_device()
serial_number = device.serial_number
dfu.release_device(device)
if 'PWND:[checkm8]' in serial_number:
device = usbexec.PwnedUSBDevice()
sys.stdout.write(device.read_memory(address, length))
else:
device = PwnedDFUDevice()
print(device.read_memory(address, length))
if opt == '--hexdump':
if arg.count(',') != 1:
print('ERROR: You must provide exactly 2 comma separated values: address,length')
sys.exit(1)
raw_address, raw_length = arg.split(',')
address = int(raw_address, 16) if raw_address.startswith('0x') else int(raw_address, 10)
length = int(raw_length, 16) if raw_length.startswith('0x') else int(raw_length, 10)
device = dfu.acquire_device()
serial_number = device.serial_number
dfu.release_device(device)
if 'PWND:[checkm8]' in serial_number:
device = usbexec.PwnedUSBDevice()
dump = device.read_memory(address, length)
for line in utilities.hex_dump(dump, address).splitlines():
print('%x: %s' % (address, line[10:]))
address += 16
else:
device = PwnedDFUDevice()
dump = device.read_memory(address, length)
print(utilities.hex_dump(dump, address), end=' ')
if opt == '--dump-rom':
device = dfu.acquire_device()
serial_number = device.serial_number
dfu.release_device(device)
if 'PWND:[checkm8]' in serial_number:
pwned = usbexec.PwnedUSBDevice()
securerom = pwned.read_memory(pwned.platform.rom_base, pwned.platform.rom_size)
if hashlib.sha1(securerom).hexdigest() != pwned.platform.rom_sha1:
print(hashlib.sha1(securerom).hexdigest())
print('ERROR: SecureROM was dumped, but the SHA1 hash does not match. Exiting.')
sys.exit(1)
chip = securerom[0x200:0x240].split(b' ')[2][:-1]
kind = securerom[0x240:0x280].split(b'\0')[0]
version = securerom[0x280:0x2C0].split(b'\0')[0][6:]
filename = b'SecureROM-%s-%s-%s.dump' % (chip, version, kind)
with open(filename, 'wb') as f:
f.write(securerom)
print('Saved:', filename)
else:
device = PwnedDFUDevice()
securerom = device.securerom_dump()
filename = 'SecureROM-%s-RELEASE.dump' % device.config.version
f = open(filename, 'wb')
f.write(securerom)
f.close()
print('SecureROM dumped to file:', filename)
if opt == '--dump-nor':
device = PwnedDFUDevice()
if device.config.cpid != '8920':
print('This is not a compatible device. Dumping NOR is only supported on iPhone 3GS.')
sys.exit(1)
nor = device.nor_dump(saveBackup=False)
f = open(arg, 'wb')
f.write(nor)
f.close()
print('NOR dumped to file: %s' % arg)
if opt == '--flash-nor':
print('Flashing NOR from file:', arg)
f = open(arg, 'rb')
new_nor = f.read()
f.close()
if new_nor[:4] != 'IMG2'[::-1]:
print('ERROR: Bad IMG2 header magic. This is not a valid NOR. Exiting.')
sys.exit(1)
device = PwnedDFUDevice()
if device.config.cpid != '8920':
print('This is not a compatible device. Flashing NOR is only supported on iPhone 3GS.')
sys.exit(1)
device.nor_dump(saveBackup=True)
device.flash_nor(new_nor)
if opt == '--24kpwn':
print('*** based on 24Kpwn exploit (segment overflow) by chronic, CPICH, ius, MuscleNerd, Planetbeing, pod2g, posixninja, et al. ***')
device = PwnedDFUDevice()
if device.config.version != '359.3':
print('Only iPhone 3GS (old bootrom) is supported.')
sys.exit(1)
dump = device.nor_dump(saveBackup=True)
print('Preparing modified NOR with 24Kpwn exploit.')
nor = nor.NorData(dump)
for byte in nor.parts[1]:
if byte != '\x00':
print('ERROR: Bytes following IMG2 header in NOR are not zero. alloc8 exploit was likely previously installed. Exiting.')
sys.exit(1)
if len(nor.images) == 0:
print('ERROR: 24Kpwn exploit cannot be installed, because NOR has no valid LLB. Exiting.')
sys.exit(1)
# Remove existing 24Kpwn exploit.
if len(nor.images[0]) > 0x24000:
nor.images[0] = image3_24Kpwn.remove_exploit(nor.images[0])
nor.images[0] = image3_24Kpwn.exploit(nor.images[0], device.securerom_dump())
device.flash_nor(nor.dump())
if opt == '--remove-24kpwn':
device = PwnedDFUDevice()
if device.config.cpid != '8920':
print('This is not a compatible device. 24Kpwn exploit is only supported on iPhone 3GS.')
sys.exit(1)
print('WARNING: This feature is for researchers only. Device will probably not boot into iOS until it is restored in iTunes.')
input("Press ENTER to continue.")
dump = device.nor_dump(saveBackup=True)
nor = nor.NorData(dump)
if len(nor.images) == 0:
print('ERROR: NOR has no valid LLB. It seems that 24Kpwn exploit is not installed. Exiting.')
sys.exit(1)
if len(nor.images[0]) <= 0x24000:
print('ERROR: LLB is not oversized. It seems that 24Kpwn exploit is not installed. Exiting.')
sys.exit(1)
print('Preparing modified NOR without 24Kpwn exploit.')
nor.images[0] = image3_24Kpwn.remove_exploit(nor.images[0])
device.flash_nor(nor.dump())
if opt == '--remove-alloc8':
device = PwnedDFUDevice()
if device.config.cpid != '8920':
print('This is not a compatible device. alloc8 exploit is for iPhone 3GS only.')
sys.exit(1)
print('WARNING: This feature is for researchers only. Device will probably not boot into iOS until it is restored in iTunes.')
input("Press ENTER to continue.")
dump = device.nor_dump(saveBackup=True)
nor = nor.NorData(dump)
if len(nor.images) < 700:
print('ERROR: It seems that alloc8 exploit is not installed. There are less than 700 images in NOR. Exiting.')
sys.exit(1)
print('Preparing modified NOR without alloc8 exploit.')
new_nor = alloc8.remove_exploit(nor)
device.flash_nor(new_nor.dump())
if opt == '--decrypt-gid':
device = dfu.acquire_device()
serial_number = device.serial_number
dfu.release_device(device)
if 'PWND:[checkm8]' in serial_number:
pwned = usbexec.PwnedUSBDevice()
print('Decrypting with %s GID key.' % pwned.platform.name())
print(pwned.aes(arg.decode('hex'), usbexec.AES_DECRYPT, usbexec.AES_GID_KEY).encode('hex'))
else:
device = PwnedDFUDevice()
print('Decrypting with S5L%s GID key.' % device.config.cpid)
print(device.aes_hex(arg, AES_DECRYPT, AES_GID_KEY))
if opt == '--encrypt-gid':
device = dfu.acquire_device()
serial_number = device.serial_number
dfu.release_device(device)
if 'PWND:[checkm8]' in serial_number:
pwned = usbexec.PwnedUSBDevice()
print('Encrypting with %s GID key.' % pwned.platform.name())
print(pwned.aes(arg.decode('hex'), usbexec.AES_ENCRYPT, usbexec.AES_GID_KEY).encode('hex'))
else:
device = PwnedDFUDevice()
print('Encrypting with S5L%s GID key.' % device.config.cpid)
print(device.aes_hex(arg, AES_ENCRYPT, AES_GID_KEY))
if opt == '--decrypt-uid':
device = dfu.acquire_device()
serial_number = device.serial_number
dfu.release_device(device)
if 'PWND:[checkm8]' in serial_number:
pwned = usbexec.PwnedUSBDevice()
print('Decrypting with %s device-specific UID key.' % pwned.platform.name())
print(pwned.aes(arg.decode('hex'), usbexec.AES_DECRYPT, usbexec.AES_UID_KEY).encode('hex'))
else:
device = PwnedDFUDevice()
print('Decrypting with device-specific UID key.')
print(device.aes_hex(arg, AES_DECRYPT, AES_UID_KEY))
if opt == '--encrypt-uid':
device = dfu.acquire_device()
serial_number = device.serial_number
dfu.release_device(device)
if 'PWND:[checkm8]' in serial_number:
pwned = usbexec.PwnedUSBDevice()
print('Encrypting with %s device-specific UID key.' % pwned.platform.name())
print(pwned.aes(arg.decode('hex'), usbexec.AES_ENCRYPT, usbexec.AES_UID_KEY).encode('hex'))
else:
device = PwnedDFUDevice()
print('Encrypting with device-specific UID key.')
print(device.aes_hex(arg, AES_ENCRYPT, AES_UID_KEY))