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/cli/mounter.py
CHANGED
|
@@ -2,17 +2,26 @@ import asyncio
|
|
|
2
2
|
import logging
|
|
3
3
|
from functools import update_wrapper
|
|
4
4
|
from pathlib import Path
|
|
5
|
+
from typing import Annotated, Optional
|
|
5
6
|
from urllib.error import URLError
|
|
6
7
|
|
|
7
|
-
import
|
|
8
|
+
import typer
|
|
9
|
+
from typer_injector import InjectingTyper
|
|
8
10
|
|
|
9
|
-
from pymobiledevice3.cli.cli_common import
|
|
10
|
-
from pymobiledevice3.exceptions import
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
from pymobiledevice3.cli.cli_common import ServiceProviderDep, print_json
|
|
12
|
+
from pymobiledevice3.exceptions import (
|
|
13
|
+
AlreadyMountedError,
|
|
14
|
+
DeveloperDiskImageNotFoundError,
|
|
15
|
+
NotMountedError,
|
|
16
|
+
UnsupportedCommandError,
|
|
17
|
+
)
|
|
13
18
|
from pymobiledevice3.lockdown_service_provider import LockdownServiceProvider
|
|
14
|
-
from pymobiledevice3.services.mobile_image_mounter import
|
|
15
|
-
|
|
19
|
+
from pymobiledevice3.services.mobile_image_mounter import (
|
|
20
|
+
DeveloperDiskImageMounter,
|
|
21
|
+
MobileImageMounterService,
|
|
22
|
+
PersonalizedImageMounter,
|
|
23
|
+
auto_mount,
|
|
24
|
+
)
|
|
16
25
|
|
|
17
26
|
logger = logging.getLogger(__name__)
|
|
18
27
|
|
|
@@ -22,161 +31,211 @@ def catch_errors(func):
|
|
|
22
31
|
try:
|
|
23
32
|
return func(*args, **kwargs)
|
|
24
33
|
except AlreadyMountedError:
|
|
25
|
-
logger.error(
|
|
34
|
+
logger.error("Given image was already mounted")
|
|
26
35
|
except UnsupportedCommandError:
|
|
27
|
-
logger.error(
|
|
36
|
+
logger.error("Your iOS version doesn't support this command")
|
|
28
37
|
|
|
29
38
|
return update_wrapper(catch_function, func)
|
|
30
39
|
|
|
31
40
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
41
|
+
cli = InjectingTyper(
|
|
42
|
+
name="mounter",
|
|
43
|
+
help="Mount/Umount DeveloperDiskImage or query related info",
|
|
44
|
+
no_args_is_help=True,
|
|
45
|
+
)
|
|
35
46
|
|
|
36
47
|
|
|
37
|
-
@cli.
|
|
38
|
-
def
|
|
39
|
-
"""
|
|
40
|
-
pass
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
@mounter.command('list', cls=Command)
|
|
44
|
-
def mounter_list(service_provider: LockdownClient):
|
|
45
|
-
""" list all mounted images """
|
|
48
|
+
@cli.command("list")
|
|
49
|
+
def mounter_list(service_provider: ServiceProviderDep) -> None:
|
|
50
|
+
"""list all mounted images"""
|
|
46
51
|
output = []
|
|
47
52
|
|
|
48
53
|
images = MobileImageMounterService(lockdown=service_provider).copy_devices()
|
|
49
54
|
for image in images:
|
|
50
|
-
image_signature = image.get(
|
|
55
|
+
image_signature = image.get("ImageSignature")
|
|
51
56
|
if image_signature is not None:
|
|
52
|
-
image[
|
|
57
|
+
image["ImageSignature"] = image_signature.hex()
|
|
53
58
|
output.append(image)
|
|
54
59
|
|
|
55
60
|
print_json(output)
|
|
56
61
|
|
|
57
62
|
|
|
58
|
-
@
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
""" lookup mounter image type """
|
|
63
|
+
@cli.command("lookup")
|
|
64
|
+
def mounter_lookup(service_provider: ServiceProviderDep, image_type: str) -> None:
|
|
65
|
+
"""lookup mounter image type"""
|
|
62
66
|
try:
|
|
63
67
|
signature = MobileImageMounterService(lockdown=service_provider).lookup_image(image_type)
|
|
64
68
|
print_json(signature)
|
|
65
69
|
except NotMountedError:
|
|
66
|
-
logger.error(f
|
|
70
|
+
logger.error(f"Disk image of type: {image_type} is not mounted")
|
|
67
71
|
|
|
68
72
|
|
|
69
|
-
@
|
|
73
|
+
@cli.command("umount-developer")
|
|
70
74
|
@catch_errors
|
|
71
|
-
def mounter_umount_developer(service_provider:
|
|
72
|
-
"""
|
|
75
|
+
def mounter_umount_developer(service_provider: ServiceProviderDep) -> None:
|
|
76
|
+
"""unmount Developer image"""
|
|
73
77
|
try:
|
|
74
78
|
DeveloperDiskImageMounter(lockdown=service_provider).umount()
|
|
75
|
-
logger.info(
|
|
79
|
+
logger.info("Developer image unmounted successfully")
|
|
76
80
|
except NotMountedError:
|
|
77
|
-
logger.error(
|
|
81
|
+
logger.error("Developer image isn't currently mounted")
|
|
78
82
|
|
|
79
83
|
|
|
80
|
-
@
|
|
84
|
+
@cli.command("umount-personalized")
|
|
81
85
|
@catch_errors
|
|
82
|
-
def mounter_umount_personalized(service_provider:
|
|
83
|
-
"""
|
|
86
|
+
def mounter_umount_personalized(service_provider: ServiceProviderDep) -> None:
|
|
87
|
+
"""unmount Personalized image"""
|
|
84
88
|
try:
|
|
85
89
|
PersonalizedImageMounter(lockdown=service_provider).umount()
|
|
86
|
-
logger.info(
|
|
90
|
+
logger.info("Personalized image unmounted successfully")
|
|
87
91
|
except NotMountedError:
|
|
88
|
-
logger.error(
|
|
92
|
+
logger.error("Personalized image isn't currently mounted")
|
|
89
93
|
|
|
90
94
|
|
|
91
|
-
@
|
|
92
|
-
@click.argument('image', type=click.Path(exists=True, file_okay=True, dir_okay=False))
|
|
93
|
-
@click.argument('signature', type=click.Path(exists=True, file_okay=True, dir_okay=False))
|
|
95
|
+
@cli.command("mount-developer")
|
|
94
96
|
@catch_errors
|
|
95
|
-
def mounter_mount_developer(
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
97
|
+
def mounter_mount_developer(
|
|
98
|
+
service_provider: ServiceProviderDep,
|
|
99
|
+
image: Annotated[
|
|
100
|
+
Path,
|
|
101
|
+
typer.Argument(
|
|
102
|
+
exists=True,
|
|
103
|
+
file_okay=True,
|
|
104
|
+
dir_okay=False,
|
|
105
|
+
),
|
|
106
|
+
],
|
|
107
|
+
signature: Annotated[
|
|
108
|
+
Path,
|
|
109
|
+
typer.Argument(
|
|
110
|
+
exists=True,
|
|
111
|
+
file_okay=True,
|
|
112
|
+
dir_okay=False,
|
|
113
|
+
),
|
|
114
|
+
],
|
|
115
|
+
) -> None:
|
|
116
|
+
"""mount developer image"""
|
|
117
|
+
DeveloperDiskImageMounter(lockdown=service_provider).mount(image, signature)
|
|
118
|
+
logger.info("Developer image mounted successfully")
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
async def mounter_mount_personalized_task(
|
|
122
|
+
service_provider: LockdownServiceProvider, image: str, trust_cache: str, build_manifest: str
|
|
123
|
+
) -> None:
|
|
124
|
+
await PersonalizedImageMounter(lockdown=service_provider).mount(
|
|
125
|
+
Path(image), Path(build_manifest), Path(trust_cache)
|
|
126
|
+
)
|
|
127
|
+
logger.info("Personalized image mounted successfully")
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
@cli.command("mount-personalized")
|
|
112
131
|
@catch_errors
|
|
113
|
-
def mounter_mount_personalized(
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
132
|
+
def mounter_mount_personalized(
|
|
133
|
+
service_provider: ServiceProviderDep,
|
|
134
|
+
image: Annotated[
|
|
135
|
+
Path,
|
|
136
|
+
typer.Argument(
|
|
137
|
+
exists=True,
|
|
138
|
+
file_okay=True,
|
|
139
|
+
dir_okay=False,
|
|
140
|
+
),
|
|
141
|
+
],
|
|
142
|
+
trust_cache: Annotated[
|
|
143
|
+
Path,
|
|
144
|
+
typer.Argument(
|
|
145
|
+
exists=True,
|
|
146
|
+
file_okay=True,
|
|
147
|
+
dir_okay=False,
|
|
148
|
+
),
|
|
149
|
+
],
|
|
150
|
+
build_manifest: Annotated[
|
|
151
|
+
Path,
|
|
152
|
+
typer.Argument(
|
|
153
|
+
exists=True,
|
|
154
|
+
file_okay=True,
|
|
155
|
+
dir_okay=False,
|
|
156
|
+
),
|
|
157
|
+
],
|
|
158
|
+
) -> None:
|
|
159
|
+
"""mount personalized image"""
|
|
160
|
+
asyncio.run(
|
|
161
|
+
mounter_mount_personalized_task(service_provider, str(image), str(trust_cache), str(build_manifest)), debug=True
|
|
162
|
+
)
|
|
117
163
|
|
|
118
164
|
|
|
119
165
|
async def mounter_auto_mount_task(service_provider: LockdownServiceProvider, xcode: str, version: str) -> None:
|
|
120
166
|
try:
|
|
121
167
|
await auto_mount(service_provider, xcode=xcode, version=version)
|
|
122
|
-
logger.info(
|
|
168
|
+
logger.info("DeveloperDiskImage mounted successfully")
|
|
123
169
|
except URLError:
|
|
124
|
-
logger.warning(
|
|
170
|
+
logger.warning("failed to query DeveloperDiskImage versions")
|
|
125
171
|
except DeveloperDiskImageNotFoundError:
|
|
126
|
-
logger.error(
|
|
172
|
+
logger.error("Unable to find the correct DeveloperDiskImage")
|
|
127
173
|
except AlreadyMountedError:
|
|
128
|
-
logger.error(
|
|
174
|
+
logger.error("DeveloperDiskImage already mounted")
|
|
129
175
|
except PermissionError as e:
|
|
130
176
|
logger.error(
|
|
131
|
-
f
|
|
132
|
-
f
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
@
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
177
|
+
f"DeveloperDiskImage could not be saved to Xcode default path ({e.filename}). "
|
|
178
|
+
f"Please make sure your user has the necessary permissions"
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
@cli.command("auto-mount")
|
|
183
|
+
def mounter_auto_mount(
|
|
184
|
+
service_provider: ServiceProviderDep,
|
|
185
|
+
xcode: Annotated[
|
|
186
|
+
Optional[Path],
|
|
187
|
+
typer.Option(
|
|
188
|
+
"--xcode",
|
|
189
|
+
"-x",
|
|
190
|
+
exists=True,
|
|
191
|
+
file_okay=True,
|
|
192
|
+
dir_okay=False,
|
|
193
|
+
help="Xcode application path used to figure out automatically the DeveloperDiskImage path",
|
|
194
|
+
),
|
|
195
|
+
] = None,
|
|
196
|
+
version: Annotated[
|
|
197
|
+
Optional[str],
|
|
198
|
+
typer.Option(help="Use a different DeveloperDiskImage version from the one retrieved by lockdownconnection"),
|
|
199
|
+
] = None,
|
|
200
|
+
) -> None:
|
|
201
|
+
"""auto-detect correct DeveloperDiskImage and mount it"""
|
|
202
|
+
asyncio.run(mounter_auto_mount_task(service_provider, str(xcode), version), debug=True)
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
@cli.command("query-developer-mode-status")
|
|
206
|
+
def mounter_query_developer_mode_status(service_provider: ServiceProviderDep) -> None:
|
|
207
|
+
"""Query developer mode status"""
|
|
148
208
|
print_json(MobileImageMounterService(lockdown=service_provider).query_developer_mode_status())
|
|
149
209
|
|
|
150
210
|
|
|
151
|
-
@
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
""" Query nonce """
|
|
211
|
+
@cli.command("query-nonce")
|
|
212
|
+
def mounter_query_nonce(service_provider: ServiceProviderDep, image_type: Annotated[str, typer.Option()]) -> None:
|
|
213
|
+
"""Query nonce"""
|
|
155
214
|
print_json(MobileImageMounterService(lockdown=service_provider).query_nonce(image_type))
|
|
156
215
|
|
|
157
216
|
|
|
158
|
-
@
|
|
159
|
-
def mounter_query_personalization_identifiers(service_provider:
|
|
160
|
-
"""
|
|
217
|
+
@cli.command("query-personalization-identifiers")
|
|
218
|
+
def mounter_query_personalization_identifiers(service_provider: ServiceProviderDep) -> None:
|
|
219
|
+
"""Query personalization identifiers"""
|
|
161
220
|
print_json(MobileImageMounterService(lockdown=service_provider).query_personalization_identifiers())
|
|
162
221
|
|
|
163
222
|
|
|
164
|
-
@
|
|
165
|
-
def mounter_query_personalization_manifest(service_provider:
|
|
166
|
-
"""
|
|
223
|
+
@cli.command("query-personalization-manifest")
|
|
224
|
+
def mounter_query_personalization_manifest(service_provider: ServiceProviderDep) -> None:
|
|
225
|
+
"""Query personalization manifest"""
|
|
167
226
|
result = []
|
|
168
227
|
mounter = MobileImageMounterService(lockdown=service_provider)
|
|
169
228
|
for device in mounter.copy_devices():
|
|
170
|
-
result.append(mounter.query_personalization_manifest(device[
|
|
229
|
+
result.append(mounter.query_personalization_manifest(device["PersonalizedImageType"], device["ImageSignature"]))
|
|
171
230
|
print_json(result)
|
|
172
231
|
|
|
173
232
|
|
|
174
|
-
@
|
|
175
|
-
def mounter_roll_personalization_nonce(service_provider:
|
|
233
|
+
@cli.command("roll-personalization-nonce")
|
|
234
|
+
def mounter_roll_personalization_nonce(service_provider: ServiceProviderDep) -> None:
|
|
176
235
|
MobileImageMounterService(lockdown=service_provider).roll_personalization_nonce()
|
|
177
236
|
|
|
178
237
|
|
|
179
|
-
@
|
|
180
|
-
def mounter_roll_cryptex_nonce(service_provider:
|
|
181
|
-
"""
|
|
238
|
+
@cli.command("roll-cryptex-nonce")
|
|
239
|
+
def mounter_roll_cryptex_nonce(service_provider: ServiceProviderDep) -> None:
|
|
240
|
+
"""Roll cryptex nonce (will reboot)"""
|
|
182
241
|
MobileImageMounterService(lockdown=service_provider).roll_cryptex_nonce()
|
|
@@ -1,41 +1,48 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
from typing import Annotated
|
|
2
3
|
|
|
3
|
-
import
|
|
4
|
+
import typer
|
|
5
|
+
from typer_injector import InjectingTyper
|
|
4
6
|
|
|
5
|
-
from pymobiledevice3.cli.cli_common import
|
|
6
|
-
from pymobiledevice3.lockdown import LockdownClient
|
|
7
|
+
from pymobiledevice3.cli.cli_common import ServiceProviderDep
|
|
7
8
|
from pymobiledevice3.resources.firmware_notifications import get_notifications
|
|
8
9
|
from pymobiledevice3.services.notification_proxy import NotificationProxyService
|
|
9
10
|
|
|
10
11
|
logger = logging.getLogger(__name__)
|
|
11
12
|
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
cli = InjectingTyper(
|
|
15
|
+
name="notifications",
|
|
16
|
+
help="Post or observe Darwin notifications via notification_proxy.",
|
|
17
|
+
no_args_is_help=True,
|
|
18
|
+
)
|
|
16
19
|
|
|
17
20
|
|
|
18
|
-
@cli.
|
|
19
|
-
def
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
""" API for notify_post(). """
|
|
21
|
+
@cli.command()
|
|
22
|
+
def post(
|
|
23
|
+
service_provider: ServiceProviderDep,
|
|
24
|
+
names: list[str],
|
|
25
|
+
insecure: Annotated[
|
|
26
|
+
bool,
|
|
27
|
+
typer.Option(help="Use the insecure relay meant for untrusted clients instead of the trusted channel."),
|
|
28
|
+
],
|
|
29
|
+
) -> None:
|
|
30
|
+
"""Post one or more Darwin notifications (notify_post)."""
|
|
29
31
|
service = NotificationProxyService(lockdown=service_provider, insecure=insecure)
|
|
30
32
|
for name in names:
|
|
31
33
|
service.notify_post(name)
|
|
32
34
|
|
|
33
35
|
|
|
34
|
-
@
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
@cli.command()
|
|
37
|
+
def observe(
|
|
38
|
+
service_provider: ServiceProviderDep,
|
|
39
|
+
names: list[str],
|
|
40
|
+
insecure: Annotated[
|
|
41
|
+
bool,
|
|
42
|
+
typer.Option(help="Use the insecure relay meant for untrusted clients instead of the trusted channel."),
|
|
43
|
+
],
|
|
44
|
+
) -> None:
|
|
45
|
+
"""Subscribe and stream notifications (notify_register_dispatch)."""
|
|
39
46
|
service = NotificationProxyService(lockdown=service_provider, insecure=insecure)
|
|
40
47
|
for name in names:
|
|
41
48
|
service.notify_register_dispatch(name)
|
|
@@ -44,10 +51,15 @@ def observe(service_provider: LockdownClient, names, insecure):
|
|
|
44
51
|
logger.info(event)
|
|
45
52
|
|
|
46
53
|
|
|
47
|
-
@
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
54
|
+
@cli.command("observe-all")
|
|
55
|
+
def observe_all(
|
|
56
|
+
service_provider: ServiceProviderDep,
|
|
57
|
+
insecure: Annotated[
|
|
58
|
+
bool,
|
|
59
|
+
typer.Option(help="Use the insecure relay meant for untrusted clients instead of the trusted channel."),
|
|
60
|
+
],
|
|
61
|
+
) -> None:
|
|
62
|
+
"""Subscribe to all known firmware notifications and stream events."""
|
|
51
63
|
service = NotificationProxyService(lockdown=service_provider, insecure=insecure)
|
|
52
64
|
for notification in get_notifications():
|
|
53
65
|
service.notify_register_dispatch(notification)
|
pymobiledevice3/cli/pcap.py
CHANGED
|
@@ -1,35 +1,37 @@
|
|
|
1
1
|
from datetime import datetime
|
|
2
|
-
from
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Annotated, Optional
|
|
3
4
|
|
|
4
|
-
import
|
|
5
|
+
import typer
|
|
5
6
|
from pygments import formatters, highlight, lexers
|
|
7
|
+
from typer_injector import InjectingTyper
|
|
6
8
|
|
|
7
|
-
from pymobiledevice3.cli.cli_common import
|
|
8
|
-
from pymobiledevice3.lockdown_service_provider import LockdownServiceProvider
|
|
9
|
+
from pymobiledevice3.cli.cli_common import ServiceProviderDep, print_hex, user_requested_colored_output
|
|
9
10
|
from pymobiledevice3.services.pcapd import PcapdService
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
cli = InjectingTyper(
|
|
13
|
+
name="pcap",
|
|
14
|
+
help="Sniff device traffic via pcapd and optionally save to a .pcap file.",
|
|
15
|
+
no_args_is_help=True,
|
|
16
|
+
)
|
|
15
17
|
|
|
16
18
|
|
|
17
19
|
def print_packet_header(packet, color: bool) -> None:
|
|
18
20
|
date = datetime.fromtimestamp(packet.seconds + (packet.microseconds / 1000000))
|
|
19
21
|
data = (
|
|
20
|
-
f
|
|
21
|
-
f
|
|
22
|
-
f
|
|
23
|
-
f
|
|
22
|
+
f"{date}: "
|
|
23
|
+
f"Process {packet.comm} ({packet.pid}), "
|
|
24
|
+
f"Interface: {packet.interface_name} ({packet.interface_type.name}), "
|
|
25
|
+
f"Family: {packet.protocol_family.name}"
|
|
24
26
|
)
|
|
25
27
|
if not color:
|
|
26
28
|
print(data)
|
|
27
29
|
else:
|
|
28
|
-
print(highlight(data, lexers.HspecLexer(), formatters.Terminal256Formatter(style=
|
|
30
|
+
print(highlight(data, lexers.HspecLexer(), formatters.Terminal256Formatter(style="native")), end="")
|
|
29
31
|
|
|
30
32
|
|
|
31
33
|
def print_packet(packet, color: Optional[bool] = None):
|
|
32
|
-
"""
|
|
34
|
+
"""Return the packet, so it can be chained in a generator"""
|
|
33
35
|
if color is None:
|
|
34
36
|
color = user_requested_colored_output()
|
|
35
37
|
print_packet_header(packet, color)
|
|
@@ -37,20 +39,39 @@ def print_packet(packet, color: Optional[bool] = None):
|
|
|
37
39
|
return packet
|
|
38
40
|
|
|
39
41
|
|
|
40
|
-
@cli.command(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
@cli.command()
|
|
43
|
+
def pcap(
|
|
44
|
+
service_provider: ServiceProviderDep,
|
|
45
|
+
out: Optional[Path] = None,
|
|
46
|
+
count: Annotated[
|
|
47
|
+
int,
|
|
48
|
+
typer.Option(
|
|
49
|
+
"--count",
|
|
50
|
+
"-c",
|
|
51
|
+
help="Number of packets to sniff. Omit to endless sniff.",
|
|
52
|
+
),
|
|
53
|
+
] = -1,
|
|
54
|
+
process: Annotated[
|
|
55
|
+
Optional[str],
|
|
56
|
+
typer.Option(help="Process to filter. Omit for all."),
|
|
57
|
+
] = None,
|
|
58
|
+
interface: Annotated[
|
|
59
|
+
Optional[str],
|
|
60
|
+
typer.Option(
|
|
61
|
+
"--interface",
|
|
62
|
+
"-i",
|
|
63
|
+
help="Interface name to filter. Omit for all.",
|
|
64
|
+
),
|
|
65
|
+
] = None,
|
|
66
|
+
) -> None:
|
|
67
|
+
"""Sniff device traffic."""
|
|
48
68
|
service = PcapdService(lockdown=service_provider)
|
|
49
69
|
packets_generator = service.watch(packets_count=count, process=process, interface_name=interface)
|
|
50
70
|
|
|
51
71
|
if out is not None:
|
|
52
|
-
packets_generator_with_print =
|
|
53
|
-
|
|
72
|
+
packets_generator_with_print = (print_packet(p) for p in packets_generator)
|
|
73
|
+
with out.open("wb") as out_file:
|
|
74
|
+
service.write_to_pcap(out_file, packets_generator_with_print)
|
|
54
75
|
return
|
|
55
76
|
|
|
56
77
|
for packet in packets_generator:
|
|
@@ -1,25 +1,26 @@
|
|
|
1
1
|
import time
|
|
2
|
+
from typing import Literal, Optional
|
|
2
3
|
|
|
3
|
-
import
|
|
4
|
+
from typer_injector import InjectingTyper
|
|
4
5
|
|
|
5
|
-
from pymobiledevice3.cli.cli_common import
|
|
6
|
-
from pymobiledevice3.lockdown_service_provider import LockdownServiceProvider
|
|
6
|
+
from pymobiledevice3.cli.cli_common import ServiceProviderDep
|
|
7
7
|
from pymobiledevice3.services.power_assertion import PowerAssertionService
|
|
8
8
|
|
|
9
|
+
cli = InjectingTyper(
|
|
10
|
+
name="power-assertion",
|
|
11
|
+
no_args_is_help=True,
|
|
12
|
+
)
|
|
9
13
|
|
|
10
|
-
@click.group()
|
|
11
|
-
def cli() -> None:
|
|
12
|
-
pass
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
[
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
"""
|
|
23
|
-
with PowerAssertionService(service_provider).create_power_assertion(
|
|
24
|
-
print(
|
|
15
|
+
@cli.command("power-assertion")
|
|
16
|
+
def power_assertion(
|
|
17
|
+
service_provider: ServiceProviderDep,
|
|
18
|
+
assertion_type: Literal["AMDPowerAssertionTypeWirelessSync", "PreventUserIdleSystemSleep", "PreventSystemSleep"],
|
|
19
|
+
name: str,
|
|
20
|
+
timeout: int,
|
|
21
|
+
details: Optional[str] = None,
|
|
22
|
+
) -> None:
|
|
23
|
+
"""Create a power assertion"""
|
|
24
|
+
with PowerAssertionService(service_provider).create_power_assertion(assertion_type, name, timeout, details):
|
|
25
|
+
print("> Hit Ctrl+C to exit")
|
|
25
26
|
time.sleep(timeout)
|
pymobiledevice3/cli/processes.py
CHANGED
|
@@ -1,37 +1,31 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
from typer_injector import InjectingTyper
|
|
4
4
|
|
|
5
|
-
from pymobiledevice3.cli.cli_common import
|
|
6
|
-
from pymobiledevice3.lockdown import LockdownClient
|
|
5
|
+
from pymobiledevice3.cli.cli_common import ServiceProviderDep, print_json
|
|
7
6
|
from pymobiledevice3.services.os_trace import OsTraceService
|
|
8
7
|
|
|
9
8
|
logger = logging.getLogger(__name__)
|
|
10
9
|
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
cli = InjectingTyper(
|
|
12
|
+
name="processes",
|
|
13
|
+
help="View process list using diagnosticsd API",
|
|
14
|
+
no_args_is_help=True,
|
|
15
|
+
)
|
|
15
16
|
|
|
16
17
|
|
|
17
|
-
@cli.
|
|
18
|
-
def
|
|
19
|
-
"""
|
|
20
|
-
|
|
18
|
+
@cli.command("ps")
|
|
19
|
+
def processes_ps(service_provider: ServiceProviderDep) -> None:
|
|
20
|
+
"""show process list"""
|
|
21
|
+
print_json(OsTraceService(lockdown=service_provider).get_pid_list().get("Payload"))
|
|
21
22
|
|
|
22
23
|
|
|
23
|
-
@
|
|
24
|
-
def
|
|
25
|
-
"""
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
@processes.command('pgrep', cls=Command)
|
|
30
|
-
@click.argument('expression')
|
|
31
|
-
def processes_pgrep(service_provider: LockdownClient, expression):
|
|
32
|
-
""" try to match processes pid by given expression (like pgrep) """
|
|
33
|
-
processes_list = OsTraceService(lockdown=service_provider).get_pid_list().get('Payload')
|
|
24
|
+
@cli.command("pgrep")
|
|
25
|
+
def processes_pgrep(service_provider: ServiceProviderDep, expression: str) -> None:
|
|
26
|
+
"""try to match processes pid by given expression (like pgrep)"""
|
|
27
|
+
processes_list = OsTraceService(lockdown=service_provider).get_pid_list().get("Payload")
|
|
34
28
|
for pid, process_info in processes_list.items():
|
|
35
|
-
process_name = process_info.get(
|
|
29
|
+
process_name = process_info.get("ProcessName")
|
|
36
30
|
if expression in process_name:
|
|
37
|
-
logger.info(f
|
|
31
|
+
logger.info(f"{pid} {process_name}")
|