forked from m1stadev/Inferius
-
Notifications
You must be signed in to change notification settings - Fork 0
/
inferius
executable file
·150 lines (114 loc) · 5.74 KB
/
inferius
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
#!/usr/bin/env python3
from utils.api import API
from utils.bundle import Bundle
from utils.dependencies import Checks
from utils.device import Device
from utils.ipsw import IPSW
from utils.manifest import Manifest, RestoreManifest
from utils.restore import Restore
import argparse
import platform
import os
import sys
import tempfile
def create_ipsw(api, buildmanifest, ipsw_path, tmpdir, bundle_path):
print('Creating custom IPSW')
bundle = Bundle()
ipsw = IPSW(ipsw_path)
print('[1] Grabbing Firmware Bundle...')
if bundle_path is not None:
print('Note: Using user provided Firmware Bundle.')
if bundle.verify_bundle(bundle_path, tmpdir, api.api, buildmanifest.buildid, api.board) == False:
sys.exit(f"[ERROR] Bundle '{bundle_path}' is invalid. Exiting.")
else:
bundle.fetch_bundle(api.device, buildmanifest.version, buildmanifest.buildid, tmpdir)
print('[2] Verifying IPSW...')
ipsw.verify_ipsw(api.fetch_sha1(buildmanifest.buildid))
print('[3] Extracting IPSW...')
extracted_ipsw = f'{tmpdir}/ipsw'
os.mkdir(extracted_ipsw)
ipsw.extract_ipsw(extracted_ipsw)
print('[4] Patching components...')
bundle.apply_patches(extracted_ipsw)
buildid = api.api['firmwares'][0]['buildid']
latest_manifest = Manifest(api.partialzip_read(buildid, 'BuildManifest.plist'))
api.partialzip_extract(buildid, latest_manifest.fetch_component_path(api.board, 'LLB'), extracted_ipsw)
bootloader_ver = api.partialzip_extract(buildid, latest_manifest.fetch_component_path(api.board, 'iBoot'), extracted_ipsw)
print('[5] Repacking IPSW...')
custom_ipsw = ipsw.create_ipsw(extracted_ipsw, f"{ipsw_path.split('/')[-1].rsplit('.', 1)[0]}_custom.ipsw", bundle.check_update_support(), bootloader_ver)
print(f"Finished creating custom IPSW: '{custom_ipsw}'.")
return custom_ipsw
def restore_ipsw(api, buildmanifest, ipsw_path, updating, tmpdir):
print('Restoring custom IPSW')
Checks()
device = Device(api.device)
ipsw = IPSW(ipsw_path)
restore = Restore(api.device, device.platform)
print('[1] Verifying custom IPSW...')
ipsw.verify_custom_ipsw(api.device, updating)
print('[2] Checking for device in pwned DFU...')
device.check_pwndfu()
print('[3] Extracting bootchain...')
ibss = buildmanifest.fetch_component_path(device.board, 'iBSS')
ipsw.extract_file(ibss, f'{tmpdir}/ibss.im4p')
ibec = buildmanifest.fetch_component_path(device.board, 'iBEC')
ipsw.extract_file(ibec, f'{tmpdir}/ibec.im4p')
print('[4] Signing bootchain...')
restore.save_blobs(device.ecid, device.board, tmpdir)
restore.sign_component(f'{tmpdir}/ibss.im4p', f'{tmpdir}/ibss.img4')
restore.sign_component(f'{tmpdir}/ibec.im4p', f'{tmpdir}/ibec.img4')
print('[5] Sending bootchain...')
restore.send_component(f'{tmpdir}/ibss.img4', 'iBSS')
restore.send_component(f'{tmpdir}/ibec.img4', 'iBEC')
print('[6] Saving SHSH blobs...')
restore.save_blobs(device.ecid, device.board, tmpdir, device.fetch_apnonce())
print('[7] Restoring...')
restore.restore(ipsw_path, device.baseband, updating)
print(f'Finished restoring pwned iOS {buildmanifest.version} IPSW to your device. Please boot your iOS device using one of the tools listed in the README.')
def main():
parser = argparse.ArgumentParser(description='Inferius - Create & Restore 64-bit custom IPSWs', usage="inferius -d 'identifier' -f 'IPSW' [-c/-r] [-b 'BUNDLE']")
parser.add_argument('-d', '--device', help='Device identifier', nargs=1)
parser.add_argument('-f', '--ipsw', help='Path to IPSW', nargs=1)
parser.add_argument('-c', '--create', help='Create custom IPSW', action='store_true')
parser.add_argument('-r', '--restore', help='Restore custom IPSW', action='store_true')
parser.add_argument('-b', '--bundle', help='(Optional) Path to local Firmware Bundle', nargs=1)
parser.add_argument('-u', '--update', help='Keep data while restoring custom IPSW', action='store_true')
args = parser.parse_args()
if (not args.device or not args.ipsw) or \
(not args.create and not args.restore) or \
(args.update and not args.restore) or \
(args.bundle and not args.create):
sys.exit(parser.print_help(sys.stderr))
if platform.system() == 'Windows':
sys.exit('[ERROR] Inferius does not support Windows. Exiting.')
identifier = args.device[0]
ipsw_path = args.ipsw[0]
api = API()
api.check_device(identifier)
api.fetch_api()
api.get_board()
ipsw = IPSW(ipsw_path)
restoremanifest = RestoreManifest(ipsw.read_file('Restore.plist'), api.board)
if restoremanifest.platform not in (0x8960, 0x7000, 0x7001, 0x8000, 0x8001, 0x8003, 0x8010, 0x8011, 0x8015):
sys.exit(f"[ERROR] '{identifier}' is not supported by Inferius. Exiting.")
buildmanifest = Manifest(ipsw.read_file('BuildManifest.plist'))
ver_major = int(buildmanifest.version.split('.')[0])
if ver_major == 10 and restoremanifest.platform != 0x8960:
sys.exit(f'[ERROR] iOS 10 downgrades are only supported on A7 devices. Exiting.')
elif not 11 <= ver_major <= 14:
sys.exit(f'[ERROR] iOS {buildmanifest.version} is not supported by Inferius. Exiting.')
if identifier not in buildmanifest.supported_devices:
sys.exit(f"[ERROR] IPSW '{ipsw_path}' does not support {identifier}. Exiting.")
if args.bundle:
bundle = args.bundle[0]
else:
bundle = None
with tempfile.TemporaryDirectory() as tmpdir:
if args.create:
custom_ipsw = create_ipsw(api, buildmanifest, ipsw_path, tmpdir, bundle)
else:
custom_ipsw = ipsw_path
if args.restore:
restore_ipsw(api, buildmanifest, custom_ipsw, args.update, tmpdir)
if __name__ == '__main__':
main()