pymobiledevice3 4.14.6__py3-none-any.whl → 7.0.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- misc/plist_sniffer.py +15 -15
- misc/remotexpc_sniffer.py +29 -28
- misc/understanding_idevice_protocol_layers.md +15 -10
- pymobiledevice3/__main__.py +317 -127
- pymobiledevice3/_version.py +22 -4
- pymobiledevice3/bonjour.py +358 -113
- pymobiledevice3/ca.py +253 -16
- pymobiledevice3/cli/activation.py +31 -23
- pymobiledevice3/cli/afc.py +49 -40
- pymobiledevice3/cli/amfi.py +16 -21
- pymobiledevice3/cli/apps.py +87 -42
- pymobiledevice3/cli/backup.py +160 -90
- pymobiledevice3/cli/bonjour.py +44 -40
- pymobiledevice3/cli/cli_common.py +204 -198
- pymobiledevice3/cli/companion_proxy.py +14 -14
- pymobiledevice3/cli/crash.py +105 -56
- pymobiledevice3/cli/developer/__init__.py +62 -0
- pymobiledevice3/cli/developer/accessibility/__init__.py +65 -0
- pymobiledevice3/cli/developer/accessibility/settings.py +43 -0
- pymobiledevice3/cli/developer/arbitration.py +50 -0
- pymobiledevice3/cli/developer/condition.py +33 -0
- pymobiledevice3/cli/developer/core_device.py +294 -0
- pymobiledevice3/cli/developer/debugserver.py +244 -0
- pymobiledevice3/cli/developer/dvt/__init__.py +438 -0
- pymobiledevice3/cli/developer/dvt/core_profile_session.py +295 -0
- pymobiledevice3/cli/developer/dvt/simulate_location.py +56 -0
- pymobiledevice3/cli/developer/dvt/sysmon/__init__.py +69 -0
- pymobiledevice3/cli/developer/dvt/sysmon/process.py +188 -0
- pymobiledevice3/cli/developer/fetch_symbols.py +108 -0
- pymobiledevice3/cli/developer/simulate_location.py +51 -0
- pymobiledevice3/cli/diagnostics/__init__.py +75 -0
- pymobiledevice3/cli/diagnostics/battery.py +47 -0
- pymobiledevice3/cli/idam.py +42 -0
- pymobiledevice3/cli/lockdown.py +108 -103
- pymobiledevice3/cli/mounter.py +158 -99
- pymobiledevice3/cli/notification.py +38 -26
- pymobiledevice3/cli/pcap.py +45 -24
- pymobiledevice3/cli/power_assertion.py +18 -17
- pymobiledevice3/cli/processes.py +17 -23
- pymobiledevice3/cli/profile.py +165 -109
- pymobiledevice3/cli/provision.py +35 -34
- pymobiledevice3/cli/remote.py +217 -129
- pymobiledevice3/cli/restore.py +159 -143
- pymobiledevice3/cli/springboard.py +63 -53
- pymobiledevice3/cli/syslog.py +193 -86
- pymobiledevice3/cli/usbmux.py +73 -33
- pymobiledevice3/cli/version.py +5 -7
- pymobiledevice3/cli/webinspector.py +376 -214
- pymobiledevice3/common.py +3 -1
- pymobiledevice3/exceptions.py +182 -58
- pymobiledevice3/irecv.py +52 -53
- pymobiledevice3/irecv_devices.py +1489 -464
- pymobiledevice3/lockdown.py +473 -275
- pymobiledevice3/lockdown_service_provider.py +15 -8
- pymobiledevice3/osu/os_utils.py +27 -9
- pymobiledevice3/osu/posix_util.py +34 -15
- pymobiledevice3/osu/win_util.py +14 -8
- pymobiledevice3/pair_records.py +102 -21
- pymobiledevice3/remote/common.py +8 -4
- pymobiledevice3/remote/core_device/app_service.py +94 -67
- pymobiledevice3/remote/core_device/core_device_service.py +17 -14
- pymobiledevice3/remote/core_device/device_info.py +5 -5
- pymobiledevice3/remote/core_device/diagnostics_service.py +19 -4
- pymobiledevice3/remote/core_device/file_service.py +53 -23
- pymobiledevice3/remote/remote_service_discovery.py +79 -45
- pymobiledevice3/remote/remotexpc.py +73 -44
- pymobiledevice3/remote/tunnel_service.py +442 -317
- pymobiledevice3/remote/utils.py +14 -13
- pymobiledevice3/remote/xpc_message.py +145 -125
- pymobiledevice3/resources/dsc_uuid_map.py +19 -19
- pymobiledevice3/resources/firmware_notifications.py +20 -16
- pymobiledevice3/resources/notifications.txt +144 -0
- pymobiledevice3/restore/asr.py +27 -27
- pymobiledevice3/restore/base_restore.py +110 -21
- pymobiledevice3/restore/consts.py +87 -66
- pymobiledevice3/restore/device.py +59 -12
- pymobiledevice3/restore/fdr.py +46 -48
- pymobiledevice3/restore/ftab.py +19 -19
- pymobiledevice3/restore/img4.py +163 -0
- pymobiledevice3/restore/mbn.py +587 -0
- pymobiledevice3/restore/recovery.py +151 -151
- pymobiledevice3/restore/restore.py +562 -544
- pymobiledevice3/restore/restore_options.py +131 -110
- pymobiledevice3/restore/restored_client.py +51 -31
- pymobiledevice3/restore/tss.py +385 -267
- pymobiledevice3/service_connection.py +252 -59
- pymobiledevice3/services/accessibilityaudit.py +202 -120
- pymobiledevice3/services/afc.py +962 -365
- pymobiledevice3/services/amfi.py +24 -30
- pymobiledevice3/services/companion.py +23 -19
- pymobiledevice3/services/crash_reports.py +71 -47
- pymobiledevice3/services/debugserver_applist.py +3 -3
- pymobiledevice3/services/device_arbitration.py +8 -8
- pymobiledevice3/services/device_link.py +101 -79
- pymobiledevice3/services/diagnostics.py +973 -967
- pymobiledevice3/services/dtfetchsymbols.py +8 -8
- pymobiledevice3/services/dvt/dvt_secure_socket_proxy.py +4 -4
- pymobiledevice3/services/dvt/dvt_testmanaged_proxy.py +4 -4
- pymobiledevice3/services/dvt/instruments/activity_trace_tap.py +85 -74
- pymobiledevice3/services/dvt/instruments/application_listing.py +2 -3
- pymobiledevice3/services/dvt/instruments/condition_inducer.py +7 -6
- pymobiledevice3/services/dvt/instruments/core_profile_session_tap.py +466 -384
- pymobiledevice3/services/dvt/instruments/device_info.py +20 -11
- pymobiledevice3/services/dvt/instruments/energy_monitor.py +1 -1
- pymobiledevice3/services/dvt/instruments/graphics.py +1 -1
- pymobiledevice3/services/dvt/instruments/location_simulation.py +1 -1
- pymobiledevice3/services/dvt/instruments/location_simulation_base.py +10 -10
- pymobiledevice3/services/dvt/instruments/network_monitor.py +17 -17
- pymobiledevice3/services/dvt/instruments/notifications.py +1 -1
- pymobiledevice3/services/dvt/instruments/process_control.py +35 -10
- pymobiledevice3/services/dvt/instruments/screenshot.py +2 -2
- pymobiledevice3/services/dvt/instruments/sysmontap.py +15 -15
- pymobiledevice3/services/dvt/testmanaged/xcuitest.py +42 -52
- pymobiledevice3/services/file_relay.py +10 -10
- pymobiledevice3/services/heartbeat.py +9 -8
- pymobiledevice3/services/house_arrest.py +16 -15
- pymobiledevice3/services/idam.py +20 -0
- pymobiledevice3/services/installation_proxy.py +173 -81
- pymobiledevice3/services/lockdown_service.py +20 -10
- pymobiledevice3/services/misagent.py +22 -19
- pymobiledevice3/services/mobile_activation.py +147 -64
- pymobiledevice3/services/mobile_config.py +331 -294
- pymobiledevice3/services/mobile_image_mounter.py +141 -113
- pymobiledevice3/services/mobilebackup2.py +203 -145
- pymobiledevice3/services/notification_proxy.py +11 -11
- pymobiledevice3/services/os_trace.py +134 -74
- pymobiledevice3/services/pcapd.py +314 -302
- pymobiledevice3/services/power_assertion.py +10 -9
- pymobiledevice3/services/preboard.py +4 -4
- pymobiledevice3/services/remote_fetch_symbols.py +21 -14
- pymobiledevice3/services/remote_server.py +176 -146
- pymobiledevice3/services/restore_service.py +16 -16
- pymobiledevice3/services/screenshot.py +15 -12
- pymobiledevice3/services/simulate_location.py +7 -7
- pymobiledevice3/services/springboard.py +15 -15
- pymobiledevice3/services/syslog.py +5 -5
- pymobiledevice3/services/web_protocol/alert.py +11 -11
- pymobiledevice3/services/web_protocol/automation_session.py +251 -239
- pymobiledevice3/services/web_protocol/cdp_screencast.py +46 -37
- pymobiledevice3/services/web_protocol/cdp_server.py +19 -19
- pymobiledevice3/services/web_protocol/cdp_target.py +411 -373
- pymobiledevice3/services/web_protocol/driver.py +114 -111
- pymobiledevice3/services/web_protocol/element.py +124 -111
- pymobiledevice3/services/web_protocol/inspector_session.py +106 -102
- pymobiledevice3/services/web_protocol/selenium_api.py +49 -49
- pymobiledevice3/services/web_protocol/session_protocol.py +18 -12
- pymobiledevice3/services/web_protocol/switch_to.py +30 -27
- pymobiledevice3/services/webinspector.py +189 -155
- pymobiledevice3/tcp_forwarder.py +87 -69
- pymobiledevice3/tunneld/__init__.py +0 -0
- pymobiledevice3/tunneld/api.py +63 -0
- pymobiledevice3/tunneld/server.py +603 -0
- pymobiledevice3/usbmux.py +198 -147
- pymobiledevice3/utils.py +14 -11
- {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info}/METADATA +55 -28
- pymobiledevice3-7.0.6.dist-info/RECORD +188 -0
- {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info}/WHEEL +1 -1
- pymobiledevice3/cli/developer.py +0 -1215
- pymobiledevice3/cli/diagnostics.py +0 -99
- pymobiledevice3/tunneld.py +0 -524
- pymobiledevice3-4.14.6.dist-info/RECORD +0 -168
- {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info}/entry_points.txt +0 -0
- {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info/licenses}/LICENSE +0 -0
- {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info}/top_level.txt +0 -0
pymobiledevice3/restore/fdr.py
CHANGED
|
@@ -10,14 +10,14 @@ from pymobiledevice3 import usbmux
|
|
|
10
10
|
from pymobiledevice3.exceptions import ConnectionFailedError, NoDeviceConnectedError, PyMobileDevice3Exception
|
|
11
11
|
from pymobiledevice3.service_connection import ServiceConnection
|
|
12
12
|
|
|
13
|
-
CTRL_PORT =
|
|
14
|
-
CTRLCMD = b
|
|
15
|
-
HELLOCTRLCMD = b
|
|
16
|
-
HELLOCMD = b
|
|
13
|
+
CTRL_PORT = 0x43A # 1082
|
|
14
|
+
CTRLCMD = b"BeginCtrl\0"
|
|
15
|
+
HELLOCTRLCMD = b"HelloCtrl\0"
|
|
16
|
+
HELLOCMD = b"HelloConn\0"
|
|
17
17
|
|
|
18
18
|
FDR_SYNC_MSG = 0x1
|
|
19
19
|
FDR_PROXY_MSG = 0x105
|
|
20
|
-
FDR_PLIST_MSG =
|
|
20
|
+
FDR_PLIST_MSG = 0xBBAA
|
|
21
21
|
CHUNK_SIZE = 1048576
|
|
22
22
|
|
|
23
23
|
conn_port = None
|
|
@@ -36,8 +36,6 @@ class FDRClient:
|
|
|
36
36
|
ctrlprotoversion = 2
|
|
37
37
|
|
|
38
38
|
def __init__(self, type_: fdr_type, udid=None):
|
|
39
|
-
global conn_port
|
|
40
|
-
|
|
41
39
|
device = usbmux.select_device(udid)
|
|
42
40
|
if device is None:
|
|
43
41
|
if udid:
|
|
@@ -45,77 +43,77 @@ class FDRClient:
|
|
|
45
43
|
else:
|
|
46
44
|
raise NoDeviceConnectedError()
|
|
47
45
|
|
|
48
|
-
logger.debug(
|
|
46
|
+
logger.debug("connecting to FDR")
|
|
49
47
|
|
|
50
48
|
if type_ == fdr_type.FDR_CTRL:
|
|
51
49
|
self.service = ServiceConnection.create_using_usbmux(
|
|
52
|
-
device.serial, self.SERVICE_PORT, connection_type=
|
|
50
|
+
device.serial, self.SERVICE_PORT, connection_type="USB"
|
|
53
51
|
)
|
|
54
52
|
self.ctrl_handshake()
|
|
55
53
|
else:
|
|
56
|
-
self.service = ServiceConnection.create_using_usbmux(device.serial, conn_port, connection_type=
|
|
54
|
+
self.service = ServiceConnection.create_using_usbmux(device.serial, conn_port, connection_type="USB")
|
|
57
55
|
self.sync_handshake()
|
|
58
56
|
|
|
59
|
-
logger.debug(
|
|
57
|
+
logger.debug("FDR connected")
|
|
60
58
|
|
|
61
59
|
def recv_plist(self):
|
|
62
|
-
return self.service.recv_plist(endianity=
|
|
60
|
+
return self.service.recv_plist(endianity="<")
|
|
63
61
|
|
|
64
62
|
def send_recv_plist(self, plist):
|
|
65
|
-
return self.service.send_recv_plist(plist, endianity=
|
|
63
|
+
return self.service.send_recv_plist(plist, endianity="<", fmt=plistlib.FMT_BINARY)
|
|
66
64
|
|
|
67
65
|
def ctrl_handshake(self):
|
|
68
66
|
global conn_port
|
|
69
67
|
|
|
70
|
-
logger.debug(
|
|
68
|
+
logger.debug("About to do ctrl handshake")
|
|
71
69
|
|
|
72
70
|
self.service.sendall(CTRLCMD)
|
|
73
71
|
|
|
74
72
|
if self.ctrlprotoversion != 2:
|
|
75
|
-
raise NotImplementedError(
|
|
73
|
+
raise NotImplementedError("TODO")
|
|
76
74
|
|
|
77
75
|
req = {
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
"Command": CTRLCMD,
|
|
77
|
+
"CtrlProtoVersion": self.ctrlprotoversion,
|
|
80
78
|
}
|
|
81
79
|
resp = self.send_recv_plist(req)
|
|
82
|
-
conn_port = resp[
|
|
80
|
+
conn_port = resp["ConnPort"]
|
|
83
81
|
|
|
84
|
-
logger.debug(f
|
|
82
|
+
logger.debug(f"Ctrl handshake done (ConnPort = {conn_port})")
|
|
85
83
|
|
|
86
84
|
def sync_handshake(self):
|
|
87
85
|
self.service.sendall(HELLOCMD)
|
|
88
86
|
|
|
89
87
|
if self.ctrlprotoversion != 2:
|
|
90
|
-
raise NotImplementedError(
|
|
88
|
+
raise NotImplementedError("TODO")
|
|
91
89
|
|
|
92
90
|
reply = self.recv_plist()
|
|
93
|
-
cmd = reply[
|
|
94
|
-
identifier = reply[
|
|
91
|
+
cmd = reply["Command"]
|
|
92
|
+
identifier = reply["Identifier"]
|
|
95
93
|
|
|
96
|
-
if cmd !=
|
|
97
|
-
raise PyMobileDevice3Exception(
|
|
94
|
+
if cmd != "HelloConn":
|
|
95
|
+
raise PyMobileDevice3Exception("Did not receive HelloConn reply...")
|
|
98
96
|
|
|
99
97
|
if identifier:
|
|
100
|
-
logger.debug(f
|
|
98
|
+
logger.debug(f"got device identifier: {identifier}")
|
|
101
99
|
|
|
102
100
|
def handle_sync_cmd(self):
|
|
103
101
|
self.service.recvall(2)
|
|
104
102
|
|
|
105
103
|
# Open a new connection and wait for messages on it
|
|
106
|
-
logger.debug(
|
|
104
|
+
logger.debug("FDR connected in reply to sync message, starting command thread")
|
|
107
105
|
start_fdr_thread(fdr_type.FDR_CONN)
|
|
108
106
|
|
|
109
107
|
def handle_proxy_cmd(self):
|
|
110
108
|
buf = self.service.recv(1048576)
|
|
111
|
-
logger.debug(f
|
|
109
|
+
logger.debug(f"got proxy command with {len(buf)} bytes")
|
|
112
110
|
|
|
113
111
|
# Just return success here unconditionally because we don't know
|
|
114
112
|
# anything else, and we will eventually abort on failure anyway
|
|
115
|
-
self.service.sendall(struct.pack(
|
|
113
|
+
self.service.sendall(struct.pack("<H", 5))
|
|
116
114
|
|
|
117
115
|
if len(buf) < 3:
|
|
118
|
-
logger.debug(f
|
|
116
|
+
logger.debug(f"FDR {self} proxy command data too short, retrying")
|
|
119
117
|
return self.poll_and_handle_message()
|
|
120
118
|
|
|
121
119
|
# ack command data too
|
|
@@ -127,11 +125,11 @@ class FDRClient:
|
|
|
127
125
|
# Now try to handle actual messages
|
|
128
126
|
# Connect: 0 3 hostlen <host> <port>
|
|
129
127
|
if buf[0] == 0 and buf[1] == 3:
|
|
130
|
-
port = struct.unpack(
|
|
128
|
+
port = struct.unpack(">H", buf[-2:])[0]
|
|
131
129
|
hostlen = buf[2]
|
|
132
|
-
host = buf[3:3 + hostlen]
|
|
130
|
+
host = buf[3 : 3 + hostlen]
|
|
133
131
|
|
|
134
|
-
logger.debug(f
|
|
132
|
+
logger.debug(f"FDR {self} Proxy connect request to {host}:{port}")
|
|
135
133
|
|
|
136
134
|
if host is None:
|
|
137
135
|
# missing or zero length host name
|
|
@@ -141,28 +139,28 @@ class FDRClient:
|
|
|
141
139
|
sockfd.connect((host, port))
|
|
142
140
|
|
|
143
141
|
while True:
|
|
144
|
-
readable,
|
|
145
|
-
|
|
146
|
-
|
|
142
|
+
readable, _writable, exceptional = select.select(
|
|
143
|
+
[sockfd, self.service.socket], [], [sockfd, self.service.socket]
|
|
144
|
+
)
|
|
147
145
|
|
|
148
146
|
for current_sock in readable:
|
|
149
147
|
if current_sock == self.service.socket:
|
|
150
148
|
buf = self.service.recv(CHUNK_SIZE)
|
|
151
149
|
|
|
152
|
-
logger.debug(f
|
|
153
|
-
logger.debug(f
|
|
150
|
+
logger.debug(f"FDR {self} got payload of {len(buf)} bytes, now try to proxy it")
|
|
151
|
+
logger.debug(f"Sending {len(buf)} bytes of data")
|
|
154
152
|
|
|
155
153
|
sockfd.sendall(buf)
|
|
156
154
|
else:
|
|
157
155
|
buf = sockfd.recv(CHUNK_SIZE)
|
|
158
|
-
logger.debug(f
|
|
156
|
+
logger.debug(f"Received {len(buf)} bytes")
|
|
159
157
|
self.service.sendall(buf)
|
|
160
158
|
|
|
161
159
|
if exceptional:
|
|
162
160
|
if exceptional[0] == sockfd:
|
|
163
|
-
logger.debug(
|
|
161
|
+
logger.debug("Remote closed the connection")
|
|
164
162
|
else:
|
|
165
|
-
logger.debug(
|
|
163
|
+
logger.debug("Local service closed the connection")
|
|
166
164
|
break
|
|
167
165
|
|
|
168
166
|
sockfd.close()
|
|
@@ -170,16 +168,16 @@ class FDRClient:
|
|
|
170
168
|
|
|
171
169
|
def handle_plist_cmd(self):
|
|
172
170
|
d = self.recv_plist()
|
|
173
|
-
command = d[
|
|
171
|
+
command = d["Command"]
|
|
174
172
|
|
|
175
|
-
if command ==
|
|
176
|
-
self.send_recv_plist({
|
|
173
|
+
if command == "Ping":
|
|
174
|
+
self.send_recv_plist({"Pong": True})
|
|
177
175
|
else:
|
|
178
|
-
logger.warning(f
|
|
176
|
+
logger.warning(f"FDR {self} received unknown plist command: {command}")
|
|
179
177
|
|
|
180
178
|
def poll_and_handle_message(self):
|
|
181
179
|
# TODO: is it okay?
|
|
182
|
-
cmd = struct.unpack(
|
|
180
|
+
cmd = struct.unpack("<H", self.service.recvall(2))[0]
|
|
183
181
|
|
|
184
182
|
handlers = {
|
|
185
183
|
FDR_SYNC_MSG: self.handle_sync_cmd,
|
|
@@ -190,7 +188,7 @@ class FDRClient:
|
|
|
190
188
|
if cmd in handlers:
|
|
191
189
|
handlers[cmd]()
|
|
192
190
|
else:
|
|
193
|
-
logger.warning(f
|
|
191
|
+
logger.warning(f"ignoring FDR message: {cmd}")
|
|
194
192
|
|
|
195
193
|
|
|
196
194
|
def fdr_listener_thread(type_: fdr_type):
|
|
@@ -198,14 +196,14 @@ def fdr_listener_thread(type_: fdr_type):
|
|
|
198
196
|
try:
|
|
199
197
|
client = FDRClient(type_)
|
|
200
198
|
|
|
201
|
-
logger.debug(f
|
|
199
|
+
logger.debug(f"FDR {client} waiting for message...")
|
|
202
200
|
|
|
203
201
|
while True:
|
|
204
202
|
client.poll_and_handle_message()
|
|
205
203
|
except ConnectionAbortedError:
|
|
206
204
|
pass
|
|
207
205
|
|
|
208
|
-
logger.debug(f
|
|
206
|
+
logger.debug(f"FDR {client} terminating...")
|
|
209
207
|
|
|
210
208
|
|
|
211
209
|
def start_fdr_thread(type_: fdr_type):
|
pymobiledevice3/restore/ftab.py
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
from construct import Array, Bytes, Const, Default, Int32ub, Int32ul, Pointer, Struct, this
|
|
2
2
|
|
|
3
3
|
ftab_entry = Struct(
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
"tag" / Bytes(4),
|
|
5
|
+
"offset" / Int32ul,
|
|
6
|
+
"size" / Int32ul,
|
|
7
|
+
"pad_0x0C" / Default(Int32ul, 0),
|
|
8
|
+
"data" / Pointer(this.offset, Bytes(this.size)),
|
|
9
9
|
)
|
|
10
10
|
|
|
11
11
|
ftab_header = Struct(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
12
|
+
"always_01" / Int32ul, # 1
|
|
13
|
+
"always_ff" / Int32ul, # 0xFFFFFFFF
|
|
14
|
+
"unk_0x08" / Int32ub, # 0
|
|
15
|
+
"unk_0x0C" / Int32ub, # 0
|
|
16
|
+
"unk_0x10" / Int32ub, # 0
|
|
17
|
+
"unk_0x14" / Int32ub, # 0
|
|
18
|
+
"unk_0x18" / Int32ub, # 0
|
|
19
|
+
"unk_0x1C" / Int32ub, # 0
|
|
20
|
+
"tag" / Bytes(4), # e.g. 'rkos'
|
|
21
|
+
"magic" / Const(b"ftab"), # 'ftab' magic
|
|
22
|
+
"num_entries" / Int32ul,
|
|
23
|
+
"pad_0x2C" / Int32ub,
|
|
24
|
+
"entries" / Array(this.num_entries, ftab_entry),
|
|
25
25
|
)
|
|
26
26
|
|
|
27
27
|
|
|
@@ -41,7 +41,7 @@ class Ftab:
|
|
|
41
41
|
|
|
42
42
|
def add_entry(self, tag: bytes, data: bytes):
|
|
43
43
|
new_offset = self.parsed.entries[-1].offset + self.parsed.entries[-1].size
|
|
44
|
-
new_entry = {
|
|
44
|
+
new_entry = {"tag": tag, "offset": new_offset, "size": len(data), "data": data}
|
|
45
45
|
|
|
46
46
|
self.parsed.num_entries += 1
|
|
47
47
|
self.parsed.entries.append(new_entry)
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
from ipsw_parser.build_identity import BuildIdentity
|
|
4
|
+
from pyimg4 import IM4P, IM4R, IMG4, RestoreProperty
|
|
5
|
+
|
|
6
|
+
logger = logging.getLogger(__name__)
|
|
7
|
+
|
|
8
|
+
COMPONENT_FOURCC = {
|
|
9
|
+
"ACIBT": "acib",
|
|
10
|
+
"ACIBTLPEM": "lpbt",
|
|
11
|
+
"ACIWIFI": "aciw",
|
|
12
|
+
"ANE": "anef",
|
|
13
|
+
"ANS": "ansf",
|
|
14
|
+
"AOP": "aopf",
|
|
15
|
+
"AVE": "avef",
|
|
16
|
+
"Alamo": "almo",
|
|
17
|
+
"Ap,ANE1": "ane1",
|
|
18
|
+
"Ap,ANE2": "ane2",
|
|
19
|
+
"Ap,ANE3": "ane3",
|
|
20
|
+
"Ap,AudioAccessibilityBootChime": "auac",
|
|
21
|
+
"Ap,AudioBootChime": "aubt",
|
|
22
|
+
"Ap,AudioPowerAttachChime": "aupr",
|
|
23
|
+
"Ap,BootabilityBrainTrustCache": "trbb",
|
|
24
|
+
"Ap,CIO": "ciof",
|
|
25
|
+
"Ap,HapticAssets": "hpas",
|
|
26
|
+
"Ap,LocalBoot": "lobo",
|
|
27
|
+
"Ap,LocalPolicy": "lpol",
|
|
28
|
+
"Ap,NextStageIM4MHash": "nsih",
|
|
29
|
+
"Ap,RecoveryOSPolicyNonceHash": "ronh",
|
|
30
|
+
"Ap,RestoreANE1": "ran1",
|
|
31
|
+
"Ap,RestoreANE2": "ran2",
|
|
32
|
+
"Ap,RestoreANE3": "ran3",
|
|
33
|
+
"Ap,RestoreCIO": "rcio",
|
|
34
|
+
"Ap,RestoreDCP2": "rdc2",
|
|
35
|
+
"Ap,RestoreTMU": "rtmu",
|
|
36
|
+
"Ap,Scorpius": "scpf",
|
|
37
|
+
"Ap,SystemVolumeCanonicalMetadata": "msys",
|
|
38
|
+
"Ap,TMU": "tmuf",
|
|
39
|
+
"Ap,VolumeUUID": "vuid",
|
|
40
|
+
"Ap,rOSLogo1": "rlg1",
|
|
41
|
+
"Ap,rOSLogo2": "rlg2",
|
|
42
|
+
"AppleLogo": "logo",
|
|
43
|
+
"AudioCodecFirmware": "acfw",
|
|
44
|
+
"BatteryCharging": "glyC",
|
|
45
|
+
"BatteryCharging0": "chg0",
|
|
46
|
+
"BatteryCharging1": "chg1",
|
|
47
|
+
"BatteryFull": "batF",
|
|
48
|
+
"BatteryLow0": "bat0",
|
|
49
|
+
"BatteryLow1": "bat1",
|
|
50
|
+
"BatteryPlugin": "glyP",
|
|
51
|
+
"CFELoader": "cfel",
|
|
52
|
+
"CrownFirmware": "crwn",
|
|
53
|
+
"DCP": "dcpf",
|
|
54
|
+
"Dali": "dali",
|
|
55
|
+
"DeviceTree": "dtre",
|
|
56
|
+
"Diags": "diag",
|
|
57
|
+
"EngineeringTrustCache": "dtrs",
|
|
58
|
+
"ExtDCP": "edcp",
|
|
59
|
+
"GFX": "gfxf",
|
|
60
|
+
"Hamm": "hamf",
|
|
61
|
+
"Homer": "homr",
|
|
62
|
+
"ISP": "ispf",
|
|
63
|
+
"InputDevice": "ipdf",
|
|
64
|
+
"KernelCache": "krnl",
|
|
65
|
+
"LLB": "illb",
|
|
66
|
+
"LeapHaptics": "lphp",
|
|
67
|
+
"Liquid": "liqd",
|
|
68
|
+
"LoadableTrustCache": "ltrs",
|
|
69
|
+
"LowPowerWallet0": "lpw0",
|
|
70
|
+
"LowPowerWallet1": "lpw1",
|
|
71
|
+
"LowPowerWallet2": "lpw2",
|
|
72
|
+
"MacEFI": "mefi",
|
|
73
|
+
"MtpFirmware": "mtpf",
|
|
74
|
+
"Multitouch": "mtfw",
|
|
75
|
+
"NeedService": "nsrv",
|
|
76
|
+
"OS": "OS\0\0",
|
|
77
|
+
"OSRamdisk": "osrd",
|
|
78
|
+
"PEHammer": "hmmr",
|
|
79
|
+
"PERTOS": "pert",
|
|
80
|
+
"PHLEET": "phlt",
|
|
81
|
+
"PMP": "pmpf",
|
|
82
|
+
"PersonalizedDMG": "pdmg",
|
|
83
|
+
"RBM": "rmbt",
|
|
84
|
+
"RTP": "rtpf",
|
|
85
|
+
"Rap,SoftwareBinaryDsp1": "sbd1",
|
|
86
|
+
"Rap,RTKitOS": "rkos",
|
|
87
|
+
"Rap,RestoreRTKitOS": "rrko",
|
|
88
|
+
"RecoveryMode": "recm",
|
|
89
|
+
"RestoreANS": "rans",
|
|
90
|
+
"RestoreDCP": "rdcp",
|
|
91
|
+
"RestoreDeviceTree": "rdtr",
|
|
92
|
+
"RestoreExtDCP": "recp",
|
|
93
|
+
"RestoreKernelCache": "rkrn",
|
|
94
|
+
"RestoreLogo": "rlgo",
|
|
95
|
+
"RestoreRTP": "rrtp",
|
|
96
|
+
"RestoreRamDisk": "rdsk",
|
|
97
|
+
"RestoreSEP": "rsep",
|
|
98
|
+
"RestoreTrustCache": "rtsc",
|
|
99
|
+
"SCE": "scef",
|
|
100
|
+
"SCE1Firmware": "sc1f",
|
|
101
|
+
"SEP": "sepi",
|
|
102
|
+
"SIO": "siof",
|
|
103
|
+
"StaticTrustCache": "trst",
|
|
104
|
+
"SystemLocker": "lckr",
|
|
105
|
+
"SystemVolume": "isys",
|
|
106
|
+
"WCHFirmwareUpdater": "wchf",
|
|
107
|
+
"ftap": "ftap",
|
|
108
|
+
"ftsp": "ftsp",
|
|
109
|
+
"iBEC": "ibec",
|
|
110
|
+
"iBSS": "ibss",
|
|
111
|
+
"iBoot": "ibot",
|
|
112
|
+
"iBootData": "ibdt",
|
|
113
|
+
"iBootDataStage1": "ibd1",
|
|
114
|
+
"iBootTest": "itst",
|
|
115
|
+
"rfta": "rfta",
|
|
116
|
+
"rfts": "rfts",
|
|
117
|
+
"Ap,DCP2": "dcp2",
|
|
118
|
+
"Ap,RestoreSecureM3Firmware": "rsm3",
|
|
119
|
+
"Ap,RestoreSecurePageTableMonitor": "rspt",
|
|
120
|
+
"Ap,RestoreTrustedExecutionMonitor": "rtrx",
|
|
121
|
+
"Ap,RestorecL4": "rxcl",
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def stitch_component(
|
|
126
|
+
name: str, im4p_data: bytes, tss: dict, build_identity: BuildIdentity, ap_parameters: dict
|
|
127
|
+
) -> bytes:
|
|
128
|
+
logger.info(f"Personalizing IMG4 component {name}...")
|
|
129
|
+
|
|
130
|
+
im4p = IM4P(data=im4p_data)
|
|
131
|
+
|
|
132
|
+
# patch fourcc
|
|
133
|
+
fourcc = COMPONENT_FOURCC.get(name)
|
|
134
|
+
if fourcc is not None:
|
|
135
|
+
im4p.fourcc = fourcc
|
|
136
|
+
|
|
137
|
+
# check if we have a *-TBM entry for the given component
|
|
138
|
+
tbm_dict = tss.get(f"{name}-TBM")
|
|
139
|
+
|
|
140
|
+
info = build_identity["Info"]
|
|
141
|
+
nonce_slot_required = info.get("RequiresNonceSlot", False) and name in ("SEP", "SepStage1", "LLB")
|
|
142
|
+
|
|
143
|
+
im4r = None
|
|
144
|
+
if tbm_dict is not None or nonce_slot_required:
|
|
145
|
+
im4r = IM4R()
|
|
146
|
+
|
|
147
|
+
if nonce_slot_required:
|
|
148
|
+
logger.debug(f"{name}: RequiresNonceSlot for {name}")
|
|
149
|
+
if name in ("SEP", "SepStage1"):
|
|
150
|
+
snid = ap_parameters.get("SepNonceSlotID", info.get("SepNonceSlotID", 2))
|
|
151
|
+
logger.debug(f"snid: {snid}")
|
|
152
|
+
im4r.add_property(RestoreProperty(fourcc="snid", value=snid))
|
|
153
|
+
else:
|
|
154
|
+
anid = ap_parameters.get("ApNonceSlotID", info.get("ApNonceSlotID", 0))
|
|
155
|
+
logger.debug(f"anid: {anid}")
|
|
156
|
+
im4r.add_property(RestoreProperty(fourcc="anid", value=anid))
|
|
157
|
+
|
|
158
|
+
if tbm_dict is not None:
|
|
159
|
+
for key in tbm_dict:
|
|
160
|
+
logger.debug(f"{name}: Adding property {key}")
|
|
161
|
+
im4r.add_property(RestoreProperty(fourcc=key, value=tbm_dict[key]))
|
|
162
|
+
|
|
163
|
+
return IMG4(im4p=im4p, im4m=tss.ap_img4_ticket, im4r=im4r).output()
|