forked from axi0mX/ipwndfu
-
Notifications
You must be signed in to change notification settings - Fork 1
/
ipwndfu
executable file
·415 lines (358 loc) · 18.4 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
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
#!/usr/bin/python
# 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 ' --boot\t\t\tboot device'
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', 'boot', '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.'
raw_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),
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(' ')[2][:-1]
kind = securerom[0x240:0x280].split('\0')[0]
version = securerom[0x280:0x2C0].split('\0')[0][6:]
filename = '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.'
raw_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.'
raw_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)
if opt == '--boot':
device = dfu.acquire_device()
serial_number = device.serial_number
dfu.release_device(device)
if 'CPID:8015' not in serial_number or 'PWND:[checkm8]' not in serial_number:
print serial_number
print 'ERROR: Option --boot is currently only supported on iPhone X pwned with checkm8.'
else:
HEAP_BASE = 0x1801E8000
HEAP_WRITE_OFFSET = 0x5000
HEAP_WRITE_HASH = 0x10000D4EC
HEAP_CHECK_ALL = 0x10000DB98
HEAP_STATE = 0x1800086A0
NAND_BOOT_JUMP = 0x10000188C
BOOTSTRAP_TASK_LR = 0x180015F88
DFU_BOOL = 0x1800085B0
DFU_NOTIFY = 0x1000098B4
DFU_STATE = 0x1800085E0
TRAMPOLINE = 0x180018000
block1 = struct.pack('<8Q', 0, 0, 0, HEAP_STATE, 2, 132, 128, 0)
block2 = struct.pack('<8Q', 0, 0, 0, HEAP_STATE, 2, 8, 128, 0)
device = usbexec.PwnedUSBDevice()
device.write_memory(HEAP_BASE + HEAP_WRITE_OFFSET , block1)
device.write_memory(HEAP_BASE + HEAP_WRITE_OFFSET + 0x80, block2)
device.write_memory(HEAP_BASE + HEAP_WRITE_OFFSET + 0x100, block2)
device.write_memory(HEAP_BASE + HEAP_WRITE_OFFSET + 0x180, block2)
device.execute(0, HEAP_WRITE_HASH, HEAP_BASE + HEAP_WRITE_OFFSET )
device.execute(0, HEAP_WRITE_HASH, HEAP_BASE + HEAP_WRITE_OFFSET + 0x80)
device.execute(0, HEAP_WRITE_HASH, HEAP_BASE + HEAP_WRITE_OFFSET + 0x100)
device.execute(0, HEAP_WRITE_HASH, HEAP_BASE + HEAP_WRITE_OFFSET + 0x180)
device.execute(0, HEAP_CHECK_ALL)
print 'Heap repaired.'
device.write_memory(TRAMPOLINE, checkm8.asm_arm64_branch(TRAMPOLINE, TRAMPOLINE + 0x400))
device.write_memory(TRAMPOLINE + 0x400, open('bin/t8015_shellcode_arm64.bin').read())
device.write_memory_ptr(BOOTSTRAP_TASK_LR, NAND_BOOT_JUMP)
device.write_memory(DFU_BOOL, '\x01')
device.execute(0, DFU_NOTIFY, DFU_STATE)
print 'Booted.'