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.
Files changed (164) hide show
  1. misc/plist_sniffer.py +15 -15
  2. misc/remotexpc_sniffer.py +29 -28
  3. misc/understanding_idevice_protocol_layers.md +15 -10
  4. pymobiledevice3/__main__.py +317 -127
  5. pymobiledevice3/_version.py +22 -4
  6. pymobiledevice3/bonjour.py +358 -113
  7. pymobiledevice3/ca.py +253 -16
  8. pymobiledevice3/cli/activation.py +31 -23
  9. pymobiledevice3/cli/afc.py +49 -40
  10. pymobiledevice3/cli/amfi.py +16 -21
  11. pymobiledevice3/cli/apps.py +87 -42
  12. pymobiledevice3/cli/backup.py +160 -90
  13. pymobiledevice3/cli/bonjour.py +44 -40
  14. pymobiledevice3/cli/cli_common.py +204 -198
  15. pymobiledevice3/cli/companion_proxy.py +14 -14
  16. pymobiledevice3/cli/crash.py +105 -56
  17. pymobiledevice3/cli/developer/__init__.py +62 -0
  18. pymobiledevice3/cli/developer/accessibility/__init__.py +65 -0
  19. pymobiledevice3/cli/developer/accessibility/settings.py +43 -0
  20. pymobiledevice3/cli/developer/arbitration.py +50 -0
  21. pymobiledevice3/cli/developer/condition.py +33 -0
  22. pymobiledevice3/cli/developer/core_device.py +294 -0
  23. pymobiledevice3/cli/developer/debugserver.py +244 -0
  24. pymobiledevice3/cli/developer/dvt/__init__.py +438 -0
  25. pymobiledevice3/cli/developer/dvt/core_profile_session.py +295 -0
  26. pymobiledevice3/cli/developer/dvt/simulate_location.py +56 -0
  27. pymobiledevice3/cli/developer/dvt/sysmon/__init__.py +69 -0
  28. pymobiledevice3/cli/developer/dvt/sysmon/process.py +188 -0
  29. pymobiledevice3/cli/developer/fetch_symbols.py +108 -0
  30. pymobiledevice3/cli/developer/simulate_location.py +51 -0
  31. pymobiledevice3/cli/diagnostics/__init__.py +75 -0
  32. pymobiledevice3/cli/diagnostics/battery.py +47 -0
  33. pymobiledevice3/cli/idam.py +42 -0
  34. pymobiledevice3/cli/lockdown.py +108 -103
  35. pymobiledevice3/cli/mounter.py +158 -99
  36. pymobiledevice3/cli/notification.py +38 -26
  37. pymobiledevice3/cli/pcap.py +45 -24
  38. pymobiledevice3/cli/power_assertion.py +18 -17
  39. pymobiledevice3/cli/processes.py +17 -23
  40. pymobiledevice3/cli/profile.py +165 -109
  41. pymobiledevice3/cli/provision.py +35 -34
  42. pymobiledevice3/cli/remote.py +217 -129
  43. pymobiledevice3/cli/restore.py +159 -143
  44. pymobiledevice3/cli/springboard.py +63 -53
  45. pymobiledevice3/cli/syslog.py +193 -86
  46. pymobiledevice3/cli/usbmux.py +73 -33
  47. pymobiledevice3/cli/version.py +5 -7
  48. pymobiledevice3/cli/webinspector.py +376 -214
  49. pymobiledevice3/common.py +3 -1
  50. pymobiledevice3/exceptions.py +182 -58
  51. pymobiledevice3/irecv.py +52 -53
  52. pymobiledevice3/irecv_devices.py +1489 -464
  53. pymobiledevice3/lockdown.py +473 -275
  54. pymobiledevice3/lockdown_service_provider.py +15 -8
  55. pymobiledevice3/osu/os_utils.py +27 -9
  56. pymobiledevice3/osu/posix_util.py +34 -15
  57. pymobiledevice3/osu/win_util.py +14 -8
  58. pymobiledevice3/pair_records.py +102 -21
  59. pymobiledevice3/remote/common.py +8 -4
  60. pymobiledevice3/remote/core_device/app_service.py +94 -67
  61. pymobiledevice3/remote/core_device/core_device_service.py +17 -14
  62. pymobiledevice3/remote/core_device/device_info.py +5 -5
  63. pymobiledevice3/remote/core_device/diagnostics_service.py +19 -4
  64. pymobiledevice3/remote/core_device/file_service.py +53 -23
  65. pymobiledevice3/remote/remote_service_discovery.py +79 -45
  66. pymobiledevice3/remote/remotexpc.py +73 -44
  67. pymobiledevice3/remote/tunnel_service.py +442 -317
  68. pymobiledevice3/remote/utils.py +14 -13
  69. pymobiledevice3/remote/xpc_message.py +145 -125
  70. pymobiledevice3/resources/dsc_uuid_map.py +19 -19
  71. pymobiledevice3/resources/firmware_notifications.py +20 -16
  72. pymobiledevice3/resources/notifications.txt +144 -0
  73. pymobiledevice3/restore/asr.py +27 -27
  74. pymobiledevice3/restore/base_restore.py +110 -21
  75. pymobiledevice3/restore/consts.py +87 -66
  76. pymobiledevice3/restore/device.py +59 -12
  77. pymobiledevice3/restore/fdr.py +46 -48
  78. pymobiledevice3/restore/ftab.py +19 -19
  79. pymobiledevice3/restore/img4.py +163 -0
  80. pymobiledevice3/restore/mbn.py +587 -0
  81. pymobiledevice3/restore/recovery.py +151 -151
  82. pymobiledevice3/restore/restore.py +562 -544
  83. pymobiledevice3/restore/restore_options.py +131 -110
  84. pymobiledevice3/restore/restored_client.py +51 -31
  85. pymobiledevice3/restore/tss.py +385 -267
  86. pymobiledevice3/service_connection.py +252 -59
  87. pymobiledevice3/services/accessibilityaudit.py +202 -120
  88. pymobiledevice3/services/afc.py +962 -365
  89. pymobiledevice3/services/amfi.py +24 -30
  90. pymobiledevice3/services/companion.py +23 -19
  91. pymobiledevice3/services/crash_reports.py +71 -47
  92. pymobiledevice3/services/debugserver_applist.py +3 -3
  93. pymobiledevice3/services/device_arbitration.py +8 -8
  94. pymobiledevice3/services/device_link.py +101 -79
  95. pymobiledevice3/services/diagnostics.py +973 -967
  96. pymobiledevice3/services/dtfetchsymbols.py +8 -8
  97. pymobiledevice3/services/dvt/dvt_secure_socket_proxy.py +4 -4
  98. pymobiledevice3/services/dvt/dvt_testmanaged_proxy.py +4 -4
  99. pymobiledevice3/services/dvt/instruments/activity_trace_tap.py +85 -74
  100. pymobiledevice3/services/dvt/instruments/application_listing.py +2 -3
  101. pymobiledevice3/services/dvt/instruments/condition_inducer.py +7 -6
  102. pymobiledevice3/services/dvt/instruments/core_profile_session_tap.py +466 -384
  103. pymobiledevice3/services/dvt/instruments/device_info.py +20 -11
  104. pymobiledevice3/services/dvt/instruments/energy_monitor.py +1 -1
  105. pymobiledevice3/services/dvt/instruments/graphics.py +1 -1
  106. pymobiledevice3/services/dvt/instruments/location_simulation.py +1 -1
  107. pymobiledevice3/services/dvt/instruments/location_simulation_base.py +10 -10
  108. pymobiledevice3/services/dvt/instruments/network_monitor.py +17 -17
  109. pymobiledevice3/services/dvt/instruments/notifications.py +1 -1
  110. pymobiledevice3/services/dvt/instruments/process_control.py +35 -10
  111. pymobiledevice3/services/dvt/instruments/screenshot.py +2 -2
  112. pymobiledevice3/services/dvt/instruments/sysmontap.py +15 -15
  113. pymobiledevice3/services/dvt/testmanaged/xcuitest.py +42 -52
  114. pymobiledevice3/services/file_relay.py +10 -10
  115. pymobiledevice3/services/heartbeat.py +9 -8
  116. pymobiledevice3/services/house_arrest.py +16 -15
  117. pymobiledevice3/services/idam.py +20 -0
  118. pymobiledevice3/services/installation_proxy.py +173 -81
  119. pymobiledevice3/services/lockdown_service.py +20 -10
  120. pymobiledevice3/services/misagent.py +22 -19
  121. pymobiledevice3/services/mobile_activation.py +147 -64
  122. pymobiledevice3/services/mobile_config.py +331 -294
  123. pymobiledevice3/services/mobile_image_mounter.py +141 -113
  124. pymobiledevice3/services/mobilebackup2.py +203 -145
  125. pymobiledevice3/services/notification_proxy.py +11 -11
  126. pymobiledevice3/services/os_trace.py +134 -74
  127. pymobiledevice3/services/pcapd.py +314 -302
  128. pymobiledevice3/services/power_assertion.py +10 -9
  129. pymobiledevice3/services/preboard.py +4 -4
  130. pymobiledevice3/services/remote_fetch_symbols.py +21 -14
  131. pymobiledevice3/services/remote_server.py +176 -146
  132. pymobiledevice3/services/restore_service.py +16 -16
  133. pymobiledevice3/services/screenshot.py +15 -12
  134. pymobiledevice3/services/simulate_location.py +7 -7
  135. pymobiledevice3/services/springboard.py +15 -15
  136. pymobiledevice3/services/syslog.py +5 -5
  137. pymobiledevice3/services/web_protocol/alert.py +11 -11
  138. pymobiledevice3/services/web_protocol/automation_session.py +251 -239
  139. pymobiledevice3/services/web_protocol/cdp_screencast.py +46 -37
  140. pymobiledevice3/services/web_protocol/cdp_server.py +19 -19
  141. pymobiledevice3/services/web_protocol/cdp_target.py +411 -373
  142. pymobiledevice3/services/web_protocol/driver.py +114 -111
  143. pymobiledevice3/services/web_protocol/element.py +124 -111
  144. pymobiledevice3/services/web_protocol/inspector_session.py +106 -102
  145. pymobiledevice3/services/web_protocol/selenium_api.py +49 -49
  146. pymobiledevice3/services/web_protocol/session_protocol.py +18 -12
  147. pymobiledevice3/services/web_protocol/switch_to.py +30 -27
  148. pymobiledevice3/services/webinspector.py +189 -155
  149. pymobiledevice3/tcp_forwarder.py +87 -69
  150. pymobiledevice3/tunneld/__init__.py +0 -0
  151. pymobiledevice3/tunneld/api.py +63 -0
  152. pymobiledevice3/tunneld/server.py +603 -0
  153. pymobiledevice3/usbmux.py +198 -147
  154. pymobiledevice3/utils.py +14 -11
  155. {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info}/METADATA +55 -28
  156. pymobiledevice3-7.0.6.dist-info/RECORD +188 -0
  157. {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info}/WHEEL +1 -1
  158. pymobiledevice3/cli/developer.py +0 -1215
  159. pymobiledevice3/cli/diagnostics.py +0 -99
  160. pymobiledevice3/tunneld.py +0 -524
  161. pymobiledevice3-4.14.6.dist-info/RECORD +0 -168
  162. {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info}/entry_points.txt +0 -0
  163. {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info/licenses}/LICENSE +0 -0
  164. {pymobiledevice3-4.14.6.dist-info → pymobiledevice3-7.0.6.dist-info}/top_level.txt +0 -0
@@ -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 = 0x43a # 1082
14
- CTRLCMD = b'BeginCtrl\0'
15
- HELLOCTRLCMD = b'HelloCtrl\0'
16
- HELLOCMD = b'HelloConn\0'
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 = 0xbbaa
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('connecting to FDR')
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='USB'
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='USB')
54
+ self.service = ServiceConnection.create_using_usbmux(device.serial, conn_port, connection_type="USB")
57
55
  self.sync_handshake()
58
56
 
59
- logger.debug('FDR connected')
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='<', fmt=plistlib.FMT_BINARY)
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('About to do ctrl handshake')
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('TODO')
73
+ raise NotImplementedError("TODO")
76
74
 
77
75
  req = {
78
- 'Command': CTRLCMD,
79
- 'CtrlProtoVersion': self.ctrlprotoversion,
76
+ "Command": CTRLCMD,
77
+ "CtrlProtoVersion": self.ctrlprotoversion,
80
78
  }
81
79
  resp = self.send_recv_plist(req)
82
- conn_port = resp['ConnPort']
80
+ conn_port = resp["ConnPort"]
83
81
 
84
- logger.debug(f'Ctrl handshake done (ConnPort = {conn_port})')
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('TODO')
88
+ raise NotImplementedError("TODO")
91
89
 
92
90
  reply = self.recv_plist()
93
- cmd = reply['Command']
94
- identifier = reply['Identifier']
91
+ cmd = reply["Command"]
92
+ identifier = reply["Identifier"]
95
93
 
96
- if cmd != 'HelloConn':
97
- raise PyMobileDevice3Exception('Did not receive HelloConn reply...')
94
+ if cmd != "HelloConn":
95
+ raise PyMobileDevice3Exception("Did not receive HelloConn reply...")
98
96
 
99
97
  if identifier:
100
- logger.debug(f'got device identifier: {identifier}')
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('FDR connected in reply to sync message, starting command thread')
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'got proxy command with {len(buf)} bytes')
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('<H', 5))
113
+ self.service.sendall(struct.pack("<H", 5))
116
114
 
117
115
  if len(buf) < 3:
118
- logger.debug(f'FDR {self} proxy command data too short, retrying')
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('>H', buf[-2:])[0]
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'FDR {self} Proxy connect request to {host}:{port}')
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, writable, exceptional = select.select([sockfd, self.service.socket],
145
- [],
146
- [sockfd, self.service.socket])
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'FDR {self} got payload of {len(buf)} bytes, now try to proxy it')
153
- logger.debug(f'Sending {len(buf)} bytes of data')
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'Received {len(buf)} bytes')
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('Remote closed the connection')
161
+ logger.debug("Remote closed the connection")
164
162
  else:
165
- logger.debug('Local service closed the connection')
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['Command']
171
+ command = d["Command"]
174
172
 
175
- if command == 'Ping':
176
- self.send_recv_plist({'Pong': True})
173
+ if command == "Ping":
174
+ self.send_recv_plist({"Pong": True})
177
175
  else:
178
- logger.warning(f'FDR {self} received unknown plist command: {command}')
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('<H', self.service.recvall(2))[0]
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'ignoring FDR message: {cmd}')
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'FDR {client} waiting for message...')
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'FDR {client} terminating...')
206
+ logger.debug(f"FDR {client} terminating...")
209
207
 
210
208
 
211
209
  def start_fdr_thread(type_: fdr_type):
@@ -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
- 'tag' / Bytes(4),
5
- 'offset' / Int32ul,
6
- 'size' / Int32ul,
7
- 'pad_0x0C' / Default(Int32ul, 0),
8
- 'data' / Pointer(this.offset, Bytes(this.size))
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
- '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)
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 = {'tag': tag, 'offset': new_offset, 'size': len(data), 'data': data}
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()