pymobiledevice3 7.0.7__tar.gz → 7.3.0__tar.gz
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.
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/PKG-INFO +1 -1
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/_version.py +3 -3
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/developer/accessibility/settings.py +2 -1
- pymobiledevice3-7.3.0/pymobiledevice3/cli/developer/debugserver.py +286 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/developer/dvt/__init__.py +30 -26
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/lockdown.py +3 -2
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/usbmux.py +8 -2
- pymobiledevice3-7.3.0/pymobiledevice3/services/dvt/instruments/network_monitor.py +158 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/tcp_forwarder.py +1 -1
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/tunneld/server.py +23 -12
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/usbmux.py +40 -23
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3.egg-info/PKG-INFO +1 -1
- pymobiledevice3-7.0.7/pymobiledevice3/cli/developer/debugserver.py +0 -244
- pymobiledevice3-7.0.7/pymobiledevice3/services/dvt/instruments/network_monitor.py +0 -102
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/.gitattributes +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/.github/FUNDING.yml +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/.github/pull_request_template.md +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/.github/workflows/codeql.yml +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/.github/workflows/generate-executable.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/.github/workflows/markdown-lint.yml +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/.github/workflows/python-app.yml +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/.github/workflows/python-publish.yml +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/.gitignore +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/.pre-commit-config.yaml +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/CODE_OF_CONDUCT.md +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/CONTRIBUTING.md +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/LICENSE +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/README.md +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/example.gif +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/markdownlint-config.json +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/misc/DTServices-14.2.txt +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/misc/DTServices-14.5.txt +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/misc/RemoteXPC.md +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/misc/plist_sniffer.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/misc/pyinstaller.md +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/misc/remotexpc_sniffer.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/misc/understanding_idevice_protocol_layers.md +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/misc/usbmux_sniff.sh +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/__init__.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/__main__.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/bonjour.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/ca.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/__init__.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/activation.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/afc.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/amfi.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/apps.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/backup.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/bonjour.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/cli_common.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/companion_proxy.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/crash.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/developer/__init__.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/developer/accessibility/__init__.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/developer/arbitration.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/developer/condition.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/developer/core_device.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/developer/dvt/core_profile_session.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/developer/dvt/simulate_location.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/developer/dvt/sysmon/__init__.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/developer/dvt/sysmon/process.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/developer/fetch_symbols.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/developer/simulate_location.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/diagnostics/__init__.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/diagnostics/battery.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/idam.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/mounter.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/notification.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/pcap.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/power_assertion.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/processes.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/profile.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/provision.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/remote.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/restore.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/springboard.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/syslog.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/version.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/webinspector.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/common.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/exceptions.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/irecv.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/irecv_devices.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/lockdown.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/lockdown_service_provider.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/osu/__init__.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/osu/os_utils.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/osu/posix_util.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/osu/win_util.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/pair_records.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/remote/__init__.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/remote/common.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/remote/core_device/__init__.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/remote/core_device/app_service.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/remote/core_device/core_device_service.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/remote/core_device/device_info.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/remote/core_device/diagnostics_service.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/remote/core_device/file_service.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/remote/module_imports.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/remote/remote_service.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/remote/remote_service_discovery.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/remote/remotexpc.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/remote/tunnel_service.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/remote/utils.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/remote/xpc_message.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/resources/__init__.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/resources/dsc_uuid_map.json +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/resources/dsc_uuid_map.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/resources/firmware_notifications.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/resources/notifications.txt +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/resources/webinspector/element_attribute.js +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/resources/webinspector/element_clear.js +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/resources/webinspector/enter_fullscreen.js +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/resources/webinspector/find_nodes.js +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/resources/webinspector/focus.js +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/resources/webinspector/get_attribute.js +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/resources/webinspector/is_displayed.js +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/resources/webinspector/is_editable.js +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/resources/webinspector/is_enabled.js +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/restore/__init__.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/restore/asr.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/restore/base_restore.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/restore/consts.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/restore/device.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/restore/fdr.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/restore/ftab.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/restore/img4.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/restore/mbn.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/restore/recovery.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/restore/restore.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/restore/restore_options.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/restore/restored_client.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/restore/tss.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/service_connection.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/__init__.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/accessibilityaudit.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/afc.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/amfi.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/companion.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/crash_reports.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/debugserver_applist.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/device_arbitration.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/device_link.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/diagnostics.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dtfetchsymbols.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/__init__.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/dvt_secure_socket_proxy.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/dvt_testmanaged_proxy.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/instruments/__init__.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/instruments/activity_trace_tap.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/instruments/application_listing.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/instruments/condition_inducer.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/instruments/core_profile_session_tap.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/instruments/device_info.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/instruments/energy_monitor.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/instruments/graphics.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/instruments/location_simulation.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/instruments/location_simulation_base.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/instruments/notifications.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/instruments/process_control.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/instruments/screenshot.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/instruments/sysmontap.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/dvt/testmanaged/xcuitest.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/file_relay.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/heartbeat.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/house_arrest.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/idam.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/installation_proxy.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/lockdown_service.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/misagent.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/mobile_activation.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/mobile_config.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/mobile_image_mounter.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/mobilebackup2.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/notification_proxy.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/os_trace.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/pcapd.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/power_assertion.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/preboard.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/remote_fetch_symbols.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/remote_server.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/restore_service.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/screenshot.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/simulate_location.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/springboard.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/syslog.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/web_protocol/__init__.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/web_protocol/alert.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/web_protocol/automation_session.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/web_protocol/cdp_screencast.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/web_protocol/cdp_server.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/web_protocol/cdp_target.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/web_protocol/driver.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/web_protocol/element.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/web_protocol/inspector_session.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/web_protocol/selenium_api.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/web_protocol/session_protocol.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/web_protocol/switch_to.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/services/webinspector.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/tunneld/__init__.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/tunneld/api.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/utils.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3.egg-info/SOURCES.txt +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3.egg-info/dependency_links.txt +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3.egg-info/entry_points.txt +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3.egg-info/requires.txt +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3.egg-info/top_level.txt +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pyproject.toml +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pytest.ini +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/requirements.txt +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/setup.cfg +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/__init__.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/cli/__init__.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/cli/test_cli.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/conftest.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/__init__.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/instruments/__init__.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/instruments/test_core_profile_session.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/instruments/test_dvt_secure_socket_proxy.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/instruments/test_fetch_symbols.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/instruments/test_location.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/instruments/test_screenshot.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_accessibility.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_afc.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_apps.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_backup2.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_bonjour.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_crash_reports.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_house_arrest.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_list_devices.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_lockdown.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_pcapd.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_springboard_services_relay.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_start_tunnel.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_syslog_relay.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_tcp_forwarder.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_web_protocol/__init__.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_web_protocol/common.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_web_protocol/conftest.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_web_protocol/test_driver.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_web_protocol/test_element.py +0 -0
- {pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/tests/services/test_webinspector.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pymobiledevice3
|
|
3
|
-
Version: 7.0
|
|
3
|
+
Version: 7.3.0
|
|
4
4
|
Summary: Pure python3 implementation for working with iDevices (iPhone, etc...)
|
|
5
5
|
Author-email: doronz88 <doron88@gmail.com>, matan <matan1008@gmail.com>
|
|
6
6
|
Maintainer-email: doronz88 <doron88@gmail.com>, matan <matan1008@gmail.com>
|
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '7.0
|
|
32
|
-
__version_tuple__ = version_tuple = (7,
|
|
31
|
+
__version__ = version = '7.3.0'
|
|
32
|
+
__version_tuple__ = version_tuple = (7, 3, 0)
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'gdbcb99cc3'
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import ast
|
|
1
2
|
import logging
|
|
2
3
|
|
|
3
4
|
from typer_injector import InjectingTyper
|
|
@@ -30,7 +31,7 @@ def accessibility_settings_set(service_provider: ServiceProviderDep, setting: st
|
|
|
30
31
|
in order to list all available use the "show" command
|
|
31
32
|
"""
|
|
32
33
|
service = AccessibilityAudit(service_provider)
|
|
33
|
-
service.set_setting(setting,
|
|
34
|
+
service.set_setting(setting, ast.literal_eval(value))
|
|
34
35
|
OSUTILS.wait_return()
|
|
35
36
|
|
|
36
37
|
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
import plistlib
|
|
4
|
+
import signal
|
|
5
|
+
import struct
|
|
6
|
+
import subprocess
|
|
7
|
+
import sys
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from tempfile import TemporaryDirectory
|
|
10
|
+
from typing import Annotated, Optional
|
|
11
|
+
from zipfile import ZipFile
|
|
12
|
+
|
|
13
|
+
import typer
|
|
14
|
+
from packaging.version import Version
|
|
15
|
+
from plumbum import local
|
|
16
|
+
from typer_injector import InjectingTyper
|
|
17
|
+
|
|
18
|
+
from pymobiledevice3.cli.cli_common import RSDServiceProviderDep, ServiceProviderDep, print_json
|
|
19
|
+
from pymobiledevice3.exceptions import RSDRequiredError
|
|
20
|
+
from pymobiledevice3.lockdown import create_using_usbmux
|
|
21
|
+
from pymobiledevice3.remote.remote_service_discovery import RemoteServiceDiscoveryService
|
|
22
|
+
from pymobiledevice3.services.debugserver_applist import DebugServerAppList
|
|
23
|
+
from pymobiledevice3.services.installation_proxy import InstallationProxyService
|
|
24
|
+
from pymobiledevice3.tcp_forwarder import LockdownTcpForwarder
|
|
25
|
+
|
|
26
|
+
DEBUGSERVER_CONNECTION_STEPS = """
|
|
27
|
+
Follow the following connections steps from LLDB:
|
|
28
|
+
|
|
29
|
+
(lldb) platform select remote-ios
|
|
30
|
+
(lldb) target create /path/to/local/application.app
|
|
31
|
+
(lldb) script lldb.target.module[0].SetPlatformFileSpec(lldb.SBFileSpec('/private/var/containers/Bundle/Application/<APP-UUID>/application.app'))
|
|
32
|
+
(lldb) process connect connect://[{host}]:{port} <-- ACTUAL CONNECTION DETAILS!
|
|
33
|
+
(lldb) process launch
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
logger = logging.getLogger(__name__)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
cli = InjectingTyper(
|
|
41
|
+
name="debugserver",
|
|
42
|
+
help="Start and drive debugserver sessions (RSD for iOS 17+, usbmux for older).",
|
|
43
|
+
no_args_is_help=True,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@cli.command("applist")
|
|
48
|
+
def debugserver_applist(service_provider: ServiceProviderDep) -> None:
|
|
49
|
+
"""Print the debugserver applist XML for the device."""
|
|
50
|
+
print_json(DebugServerAppList(service_provider).get())
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@cli.command("start-server")
|
|
54
|
+
def debugserver_start_server(
|
|
55
|
+
service_provider: ServiceProviderDep,
|
|
56
|
+
local_port: Optional[int] = None,
|
|
57
|
+
host: Annotated[
|
|
58
|
+
str,
|
|
59
|
+
typer.Option(help="Address to bind the local port to."),
|
|
60
|
+
] = "127.0.0.1",
|
|
61
|
+
) -> None:
|
|
62
|
+
"""
|
|
63
|
+
Start debugserver and print the LLDB connect string.
|
|
64
|
+
|
|
65
|
+
- For iOS < 17, you must forward to a local port (--local-port).
|
|
66
|
+
- For iOS >= 17, if connected over RSD, the remote host:port is printed for LLDB.
|
|
67
|
+
Connect quickly with your own LLDB client using the printed steps.
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
if Version(service_provider.product_version) < Version("17.0"):
|
|
71
|
+
service_name = "com.apple.debugserver.DVTSecureSocketProxy"
|
|
72
|
+
else:
|
|
73
|
+
service_name = "com.apple.internal.dt.remote.debugproxy"
|
|
74
|
+
|
|
75
|
+
if local_port is not None:
|
|
76
|
+
print(DEBUGSERVER_CONNECTION_STEPS.format(host=host, port=local_port))
|
|
77
|
+
print("Started port forwarding. Press Ctrl-C to close this shell when done")
|
|
78
|
+
sys.stdout.flush()
|
|
79
|
+
LockdownTcpForwarder(service_provider, local_port, service_name).start(address=host)
|
|
80
|
+
elif Version(service_provider.product_version) >= Version("17.0"):
|
|
81
|
+
if not isinstance(service_provider, RemoteServiceDiscoveryService):
|
|
82
|
+
raise RSDRequiredError(service_provider.identifier)
|
|
83
|
+
debugserver_port = service_provider.get_service_port(service_name)
|
|
84
|
+
print(DEBUGSERVER_CONNECTION_STEPS.format(host=service_provider.service.address[0], port=debugserver_port))
|
|
85
|
+
else:
|
|
86
|
+
print("local_port is required for iOS < 17.0")
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@cli.command("lldb")
|
|
90
|
+
def debugserver_lldb(
|
|
91
|
+
service_provider: RSDServiceProviderDep,
|
|
92
|
+
project_or_ipa_path: Annotated[
|
|
93
|
+
Path,
|
|
94
|
+
typer.Argument(exists=True, file_okay=True, dir_okay=True),
|
|
95
|
+
],
|
|
96
|
+
configuration: Annotated[
|
|
97
|
+
str,
|
|
98
|
+
typer.Option(help="Build configuration to invoke (e.g., Debug or Release)."),
|
|
99
|
+
] = "Debug",
|
|
100
|
+
lldb_command: Annotated[
|
|
101
|
+
str,
|
|
102
|
+
typer.Option(help="Path to the lldb executable to run."),
|
|
103
|
+
] = "lldb",
|
|
104
|
+
launch: Annotated[
|
|
105
|
+
bool,
|
|
106
|
+
typer.Option(help="Automatically launch the app after attaching."),
|
|
107
|
+
] = False,
|
|
108
|
+
breakpoints: Annotated[
|
|
109
|
+
Optional[list[str]],
|
|
110
|
+
typer.Option("--break", "-b", help="Add multiple startup breakpoints"),
|
|
111
|
+
] = None,
|
|
112
|
+
user_commands: Annotated[
|
|
113
|
+
Optional[list[str]],
|
|
114
|
+
typer.Option("--command", "-c", help="Additional commands to run at startup"),
|
|
115
|
+
] = None,
|
|
116
|
+
) -> None:
|
|
117
|
+
"""
|
|
118
|
+
Automate lldb launch for a given xcodeproj or IPA.
|
|
119
|
+
|
|
120
|
+
\b
|
|
121
|
+
This will:
|
|
122
|
+
- Build the given xcodeproj (if provided)
|
|
123
|
+
- Extract the given IPA (if provided)
|
|
124
|
+
- Install it
|
|
125
|
+
- Start a debugserver attached to it
|
|
126
|
+
- Place breakpoints if given any
|
|
127
|
+
- Launch the application if requested
|
|
128
|
+
- Execute any additional commands if requested
|
|
129
|
+
- Switch to lldb shell
|
|
130
|
+
"""
|
|
131
|
+
if Version(service_provider.product_version) < Version("17.0"):
|
|
132
|
+
logger.error("lldb is only supported on iOS >= 17.0")
|
|
133
|
+
return
|
|
134
|
+
|
|
135
|
+
commands = []
|
|
136
|
+
temp_dir = None
|
|
137
|
+
local_app = None
|
|
138
|
+
install_source = None
|
|
139
|
+
|
|
140
|
+
if project_or_ipa_path.suffix == ".xcodeproj":
|
|
141
|
+
with local.cwd(project_or_ipa_path.parent):
|
|
142
|
+
logger.info(f"Building {project_or_ipa_path} for {configuration} configuration")
|
|
143
|
+
local["xcodebuild"]["-project", str(project_or_ipa_path), "-configuration", configuration, "build"]()
|
|
144
|
+
app_candidates = [app for app in Path("build").rglob("*.app") if (app / "Info.plist").exists()]
|
|
145
|
+
if not app_candidates:
|
|
146
|
+
logger.error("No built .app with Info.plist found under build/.")
|
|
147
|
+
return
|
|
148
|
+
app_candidates.sort(key=lambda p: p.stat().st_mtime, reverse=True)
|
|
149
|
+
local_app = app_candidates[0].absolute()
|
|
150
|
+
install_source = local_app
|
|
151
|
+
elif project_or_ipa_path.suffix == ".ipa":
|
|
152
|
+
temp_dir = TemporaryDirectory()
|
|
153
|
+
with ZipFile(project_or_ipa_path, "r") as ipa_zip:
|
|
154
|
+
ipa_zip.extractall(temp_dir.name)
|
|
155
|
+
payload_dir = Path(temp_dir.name) / "Payload"
|
|
156
|
+
apps = list(payload_dir.glob("*.app"))
|
|
157
|
+
if not apps:
|
|
158
|
+
logger.error("No .app bundle found in IPA Payload.")
|
|
159
|
+
temp_dir.cleanup()
|
|
160
|
+
return
|
|
161
|
+
if len(apps) > 1:
|
|
162
|
+
logger.error("Multiple .app bundles found in IPA Payload; please provide a single-app IPA.")
|
|
163
|
+
temp_dir.cleanup()
|
|
164
|
+
return
|
|
165
|
+
local_app = apps[0].absolute()
|
|
166
|
+
install_source = project_or_ipa_path
|
|
167
|
+
else:
|
|
168
|
+
logger.error("Expected an .xcodeproj directory or an .ipa file.")
|
|
169
|
+
return
|
|
170
|
+
|
|
171
|
+
logger.info(f"Using app: {local_app}")
|
|
172
|
+
|
|
173
|
+
info_plist_path = local_app / "Info.plist"
|
|
174
|
+
info_plist = plistlib.loads(info_plist_path.read_bytes())
|
|
175
|
+
bundle_identifier = info_plist["CFBundleIdentifier"]
|
|
176
|
+
logger.info(f"Bundle identifier: {bundle_identifier}")
|
|
177
|
+
|
|
178
|
+
commands.append("platform select remote-ios")
|
|
179
|
+
commands.append(f'target create "{local_app.absolute()}"')
|
|
180
|
+
|
|
181
|
+
with InstallationProxyService(create_using_usbmux()) as installation_proxy:
|
|
182
|
+
logger.info("Installing app")
|
|
183
|
+
installation_proxy.install_from_local(install_source)
|
|
184
|
+
remote_path = installation_proxy.get_apps(bundle_identifiers=[bundle_identifier])[bundle_identifier]["Path"]
|
|
185
|
+
logger.info(f"Remote path: {remote_path}")
|
|
186
|
+
commands.append(f'script lldb.target.module[0].SetPlatformFileSpec(lldb.SBFileSpec("{remote_path}"))')
|
|
187
|
+
|
|
188
|
+
debugserver_port = service_provider.get_service_port("com.apple.internal.dt.remote.debugproxy")
|
|
189
|
+
|
|
190
|
+
# Add connection and launch commands
|
|
191
|
+
commands.append(f"process connect connect://[{service_provider.service.address[0]}]:{debugserver_port}")
|
|
192
|
+
|
|
193
|
+
if breakpoints:
|
|
194
|
+
for bp in breakpoints:
|
|
195
|
+
commands.append(f'breakpoint set -n "{bp}"')
|
|
196
|
+
|
|
197
|
+
if launch:
|
|
198
|
+
commands.append("process launch")
|
|
199
|
+
|
|
200
|
+
if user_commands:
|
|
201
|
+
# Add user commands
|
|
202
|
+
commands += user_commands
|
|
203
|
+
|
|
204
|
+
logger.info("Starting lldb with automated setup and connection")
|
|
205
|
+
|
|
206
|
+
# Works only on unix-based systems, so keep these imports here
|
|
207
|
+
import fcntl
|
|
208
|
+
import pty
|
|
209
|
+
import select as select_module
|
|
210
|
+
import termios
|
|
211
|
+
import tty
|
|
212
|
+
|
|
213
|
+
master, slave = pty.openpty()
|
|
214
|
+
|
|
215
|
+
process = None # Initialize process variable for signal handler
|
|
216
|
+
|
|
217
|
+
# Copy terminal size from the current terminal to PTY
|
|
218
|
+
def resize_pty() -> None:
|
|
219
|
+
"""Update PTY size to match current terminal size"""
|
|
220
|
+
size = struct.unpack(
|
|
221
|
+
"HHHH", fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ, struct.pack("HHHH", 0, 0, 0, 0))
|
|
222
|
+
)
|
|
223
|
+
fcntl.ioctl(master, termios.TIOCSWINSZ, struct.pack("HHHH", *size))
|
|
224
|
+
# Send SIGWINCH to the child process to notify it of the resize
|
|
225
|
+
if process is not None and process.poll() is None:
|
|
226
|
+
process.send_signal(signal.SIGWINCH)
|
|
227
|
+
|
|
228
|
+
# Initial resize
|
|
229
|
+
resize_pty()
|
|
230
|
+
|
|
231
|
+
# Set up signal handler for window resize
|
|
232
|
+
def handle_sigwinch(signum, frame):
|
|
233
|
+
resize_pty()
|
|
234
|
+
|
|
235
|
+
old_sigwinch_handler = signal.signal(signal.SIGWINCH, handle_sigwinch)
|
|
236
|
+
|
|
237
|
+
# Save original terminal settings
|
|
238
|
+
old_tty = termios.tcgetattr(sys.stdin)
|
|
239
|
+
|
|
240
|
+
try:
|
|
241
|
+
# Set TERM environment variable to enable colors
|
|
242
|
+
env = os.environ.copy()
|
|
243
|
+
env["TERM"] = os.environ.get("TERM", "xterm-256color")
|
|
244
|
+
|
|
245
|
+
process = subprocess.Popen([lldb_command], stdin=slave, stdout=slave, stderr=slave, env=env)
|
|
246
|
+
os.close(slave)
|
|
247
|
+
|
|
248
|
+
# Put terminal in raw mode for proper interaction
|
|
249
|
+
tty.setraw(sys.stdin.fileno())
|
|
250
|
+
# Send all commands through stdin
|
|
251
|
+
for command in commands:
|
|
252
|
+
os.write(master, (command + "\n").encode())
|
|
253
|
+
|
|
254
|
+
# Now redirect stdin from the terminal to lldb so user can interact
|
|
255
|
+
while True:
|
|
256
|
+
rlist, _, _ = select_module.select([sys.stdin, master], [], [])
|
|
257
|
+
|
|
258
|
+
if sys.stdin in rlist:
|
|
259
|
+
# User typed something
|
|
260
|
+
data = os.read(sys.stdin.fileno(), 1024)
|
|
261
|
+
if not data:
|
|
262
|
+
break
|
|
263
|
+
os.write(master, data)
|
|
264
|
+
|
|
265
|
+
if master in rlist:
|
|
266
|
+
# lldb has output
|
|
267
|
+
try:
|
|
268
|
+
data = os.read(master, 1024)
|
|
269
|
+
if not data:
|
|
270
|
+
break
|
|
271
|
+
os.write(sys.stdout.fileno(), data)
|
|
272
|
+
except OSError:
|
|
273
|
+
break
|
|
274
|
+
except (KeyboardInterrupt, OSError):
|
|
275
|
+
pass
|
|
276
|
+
finally:
|
|
277
|
+
# Restore terminal settings
|
|
278
|
+
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_tty)
|
|
279
|
+
# Restore original SIGWINCH handler
|
|
280
|
+
signal.signal(signal.SIGWINCH, old_sigwinch_handler)
|
|
281
|
+
os.close(master)
|
|
282
|
+
if process is not None:
|
|
283
|
+
process.terminate()
|
|
284
|
+
process.wait()
|
|
285
|
+
if temp_dir is not None:
|
|
286
|
+
temp_dir.cleanup()
|
{pymobiledevice3-7.0.7 → pymobiledevice3-7.3.0}/pymobiledevice3/cli/developer/dvt/__init__.py
RENAMED
|
@@ -166,46 +166,49 @@ def process_id_for_bundle_id(service_provider: ServiceProviderDep, app_bundle_id
|
|
|
166
166
|
|
|
167
167
|
|
|
168
168
|
def get_matching_processes(
|
|
169
|
-
|
|
169
|
+
device_info: DeviceInfo,
|
|
170
170
|
name: Optional[str] = None,
|
|
171
171
|
bundle_identifier: Optional[str] = None,
|
|
172
172
|
) -> list[MatchedProcessByPid]:
|
|
173
173
|
result: list[MatchedProcessByPid] = []
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
):
|
|
183
|
-
result.append(MatchedProcessByPid(name=current_name, pid=pid))
|
|
174
|
+
for process in device_info.proclist():
|
|
175
|
+
current_name = process["name"]
|
|
176
|
+
current_bundle_identifier = process.get("bundleIdentifier", "")
|
|
177
|
+
pid = process["pid"]
|
|
178
|
+
if (bundle_identifier is not None and bundle_identifier in current_bundle_identifier) or (
|
|
179
|
+
name is not None and name in current_name
|
|
180
|
+
):
|
|
181
|
+
result.append(MatchedProcessByPid(name=current_name, pid=pid))
|
|
184
182
|
return result
|
|
185
183
|
|
|
186
184
|
|
|
187
185
|
@cli.command("pkill")
|
|
188
186
|
def pkill(
|
|
189
187
|
service_provider: ServiceProviderDep,
|
|
190
|
-
|
|
188
|
+
expressions: Annotated[
|
|
189
|
+
list[str],
|
|
190
|
+
typer.Argument(help="One or more process-name (or bundle id) expressions to match."),
|
|
191
|
+
],
|
|
191
192
|
bundle: Annotated[
|
|
192
193
|
bool,
|
|
193
|
-
typer.Option(help="Treat given
|
|
194
|
+
typer.Option(help="Treat given expressions as bundle-identifiers instead of process names"),
|
|
194
195
|
] = False,
|
|
195
196
|
) -> None:
|
|
196
|
-
"""Kill all processes containing
|
|
197
|
-
matching_name = expression if not bundle else None
|
|
198
|
-
matching_bundle_identifier = expression if bundle else None
|
|
199
|
-
matching_processes = get_matching_processes(
|
|
200
|
-
service_provider, name=matching_name, bundle_identifier=matching_bundle_identifier
|
|
201
|
-
)
|
|
202
|
-
|
|
197
|
+
"""Kill all processes containing each expression in their name."""
|
|
203
198
|
with DvtSecureSocketProxyService(lockdown=service_provider) as dvt:
|
|
199
|
+
device_info = DeviceInfo(dvt)
|
|
204
200
|
process_control = ProcessControl(dvt)
|
|
205
201
|
|
|
206
|
-
for
|
|
207
|
-
|
|
208
|
-
|
|
202
|
+
for expression in expressions:
|
|
203
|
+
matching_name = expression if not bundle else None
|
|
204
|
+
matching_bundle_identifier = expression if bundle else None
|
|
205
|
+
matching_processes = get_matching_processes(
|
|
206
|
+
device_info, name=matching_name, bundle_identifier=matching_bundle_identifier
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
for process in matching_processes:
|
|
210
|
+
logger.info(f"Killing {process.name}({process.pid})")
|
|
211
|
+
process_control.kill(process.pid)
|
|
209
212
|
|
|
210
213
|
|
|
211
214
|
@cli.command("launch")
|
|
@@ -301,9 +304,10 @@ def netstat(service_provider: ServiceProviderDep) -> None:
|
|
|
301
304
|
with DvtSecureSocketProxyService(lockdown=service_provider) as dvt, NetworkMonitor(dvt) as monitor:
|
|
302
305
|
for event in monitor:
|
|
303
306
|
if isinstance(event, ConnectionDetectionEvent):
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
+
logger.info(
|
|
308
|
+
f"Connection detected: {event.local_address.data.address}:{event.local_address.port} -> "
|
|
309
|
+
f"{event.remote_address.data.address}:{event.remote_address.port}"
|
|
310
|
+
)
|
|
307
311
|
|
|
308
312
|
|
|
309
313
|
@cli.command("screenshot")
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import ast
|
|
1
2
|
import asyncio
|
|
2
3
|
import logging
|
|
3
4
|
import plistlib
|
|
@@ -61,8 +62,8 @@ def lockdown_set(
|
|
|
61
62
|
domain: Optional[str] = None,
|
|
62
63
|
key: Optional[str] = None,
|
|
63
64
|
) -> None:
|
|
64
|
-
"""set a lockdown value using python's
|
|
65
|
-
print_json(service_provider.set_value(value=
|
|
65
|
+
"""set a lockdown value using python's ast.literal_eval()"""
|
|
66
|
+
print_json(service_provider.set_value(value=ast.literal_eval(value), domain=domain, key=key))
|
|
66
67
|
|
|
67
68
|
|
|
68
69
|
@cli.command("remove")
|
|
@@ -43,6 +43,10 @@ def usbmux_forward(
|
|
|
43
43
|
Optional[str],
|
|
44
44
|
typer.Option(help="Device serial/UDID to forward traffic to."),
|
|
45
45
|
] = None,
|
|
46
|
+
host: Annotated[
|
|
47
|
+
str,
|
|
48
|
+
typer.Option(help="Address to bind the local port to."),
|
|
49
|
+
] = "127.0.0.1",
|
|
46
50
|
daemonize: Annotated[
|
|
47
51
|
bool,
|
|
48
52
|
typer.Option("--daemonize", "-d", help="Run the forwarder in the background."),
|
|
@@ -58,10 +62,12 @@ def usbmux_forward(
|
|
|
58
62
|
raise NotImplementedError("daemonizing is only supported on unix platforms") from e
|
|
59
63
|
|
|
60
64
|
with tempfile.NamedTemporaryFile("wt") as pid_file:
|
|
61
|
-
daemon = Daemonize(
|
|
65
|
+
daemon = Daemonize(
|
|
66
|
+
app=f"forwarder {src_port}->{dst_port}", pid=pid_file.name, action=lambda: forwarder.start(address=host)
|
|
67
|
+
)
|
|
62
68
|
daemon.start()
|
|
63
69
|
else:
|
|
64
|
-
forwarder.start()
|
|
70
|
+
forwarder.start(address=host)
|
|
65
71
|
|
|
66
72
|
|
|
67
73
|
@cli.command("list")
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import ipaddress
|
|
2
|
+
import logging
|
|
3
|
+
from collections.abc import Iterator
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import Union
|
|
6
|
+
|
|
7
|
+
from construct import Adapter, Bytes, Int8ul, Int16ub, Int32ul, Switch, this
|
|
8
|
+
from construct_typed import DataclassMixin, TStruct, csfield
|
|
9
|
+
|
|
10
|
+
from pymobiledevice3.services.dvt.dvt_secure_socket_proxy import DvtSecureSocketProxyService
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class IpAddressAdapter(Adapter):
|
|
14
|
+
"""Decode raw address bytes into ipaddress objects."""
|
|
15
|
+
|
|
16
|
+
def _decode(self, obj, context, path):
|
|
17
|
+
return ipaddress.ip_address(obj)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass
|
|
21
|
+
class AddressV6(DataclassMixin):
|
|
22
|
+
"""IPv6 payload for a socket address."""
|
|
23
|
+
|
|
24
|
+
flow_info: int = csfield(Int32ul)
|
|
25
|
+
address: ipaddress.IPv6Address = csfield(IpAddressAdapter(Bytes(16)))
|
|
26
|
+
scope_id: int = csfield(Int32ul)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass
|
|
30
|
+
class AddressV4(DataclassMixin):
|
|
31
|
+
"""IPv4 payload for a socket address."""
|
|
32
|
+
|
|
33
|
+
address: ipaddress.IPv4Address = csfield(IpAddressAdapter(Bytes(4)))
|
|
34
|
+
_zero: bytes = csfield(Bytes(8))
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass
|
|
38
|
+
class SocketAddress(DataclassMixin):
|
|
39
|
+
"""Parsed socket address with family-specific payload."""
|
|
40
|
+
|
|
41
|
+
length: int = csfield(Int8ul)
|
|
42
|
+
family: int = csfield(Int8ul)
|
|
43
|
+
port: int = csfield(Int16ub)
|
|
44
|
+
data: Union[AddressV4, AddressV6] = csfield(
|
|
45
|
+
Switch(
|
|
46
|
+
this.length,
|
|
47
|
+
{
|
|
48
|
+
0x1C: TStruct(AddressV6),
|
|
49
|
+
0x10: TStruct(AddressV4),
|
|
50
|
+
},
|
|
51
|
+
)
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
address_t = TStruct(SocketAddress)
|
|
56
|
+
|
|
57
|
+
MESSAGE_TYPE_INTERFACE_DETECTION = 0
|
|
58
|
+
MESSAGE_TYPE_CONNECTION_DETECTION = 1
|
|
59
|
+
MESSAGE_TYPE_CONNECTION_UPDATE = 2
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@dataclass
|
|
63
|
+
class InterfaceDetectionEvent:
|
|
64
|
+
"""Interface detection event emitted by Instruments."""
|
|
65
|
+
|
|
66
|
+
interface_index: int
|
|
67
|
+
name: str
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@dataclass
|
|
71
|
+
class ConnectionDetectionEvent:
|
|
72
|
+
"""Connection detection event emitted by Instruments."""
|
|
73
|
+
|
|
74
|
+
local_address: SocketAddress
|
|
75
|
+
remote_address: SocketAddress
|
|
76
|
+
interface_index: int
|
|
77
|
+
pid: int
|
|
78
|
+
recv_buffer_size: int
|
|
79
|
+
recv_buffer_used: int
|
|
80
|
+
serial_number: int
|
|
81
|
+
kind: int
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@dataclass
|
|
85
|
+
class ConnectionUpdateEvent:
|
|
86
|
+
"""Connection update event emitted by Instruments."""
|
|
87
|
+
|
|
88
|
+
rx_packets: int
|
|
89
|
+
rx_bytes: int
|
|
90
|
+
tx_packets: int
|
|
91
|
+
tx_bytes: int
|
|
92
|
+
rx_dups: int
|
|
93
|
+
rx000: int
|
|
94
|
+
tx_retx: int
|
|
95
|
+
min_rtt: int
|
|
96
|
+
avg_rtt: int
|
|
97
|
+
connection_serial: int
|
|
98
|
+
time: int
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
NetworkMonitorEvent = Union[InterfaceDetectionEvent, ConnectionDetectionEvent, ConnectionUpdateEvent]
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class NetworkMonitor:
|
|
105
|
+
"""Iterate over network monitoring events from the Instruments service."""
|
|
106
|
+
|
|
107
|
+
IDENTIFIER = "com.apple.instruments.server.services.networking"
|
|
108
|
+
|
|
109
|
+
def __init__(self, dvt: DvtSecureSocketProxyService):
|
|
110
|
+
self.logger = logging.getLogger(__name__)
|
|
111
|
+
self._channel = dvt.make_channel(self.IDENTIFIER)
|
|
112
|
+
|
|
113
|
+
def __enter__(self) -> "NetworkMonitor":
|
|
114
|
+
self._channel.startMonitoring(expects_reply=False)
|
|
115
|
+
return self
|
|
116
|
+
|
|
117
|
+
def __exit__(self, exc_type, exc_val, exc_tb) -> None:
|
|
118
|
+
self._channel.stopMonitoring()
|
|
119
|
+
|
|
120
|
+
def __iter__(self) -> Iterator[NetworkMonitorEvent]:
|
|
121
|
+
"""Yield network events as they arrive from the service."""
|
|
122
|
+
|
|
123
|
+
while True:
|
|
124
|
+
message = self._channel.receive_plist()
|
|
125
|
+
|
|
126
|
+
event = None
|
|
127
|
+
|
|
128
|
+
if message is None:
|
|
129
|
+
continue
|
|
130
|
+
|
|
131
|
+
if message[0] == MESSAGE_TYPE_INTERFACE_DETECTION:
|
|
132
|
+
event = InterfaceDetectionEvent(*message[1])
|
|
133
|
+
elif message[0] == MESSAGE_TYPE_CONNECTION_DETECTION:
|
|
134
|
+
(
|
|
135
|
+
local_address,
|
|
136
|
+
remote_address,
|
|
137
|
+
interface_index,
|
|
138
|
+
pid,
|
|
139
|
+
recv_buffer_size,
|
|
140
|
+
recv_buffer_used,
|
|
141
|
+
serial_number,
|
|
142
|
+
kind,
|
|
143
|
+
) = message[1]
|
|
144
|
+
event = ConnectionDetectionEvent(
|
|
145
|
+
local_address=address_t.parse(local_address),
|
|
146
|
+
remote_address=address_t.parse(remote_address),
|
|
147
|
+
interface_index=interface_index,
|
|
148
|
+
pid=pid,
|
|
149
|
+
recv_buffer_size=recv_buffer_size,
|
|
150
|
+
recv_buffer_used=recv_buffer_used,
|
|
151
|
+
serial_number=serial_number,
|
|
152
|
+
kind=kind,
|
|
153
|
+
)
|
|
154
|
+
elif message[0] == MESSAGE_TYPE_CONNECTION_UPDATE:
|
|
155
|
+
event = ConnectionUpdateEvent(*message[1])
|
|
156
|
+
else:
|
|
157
|
+
self.logger.warning(f"unsupported event type: {message[0]}")
|
|
158
|
+
yield event
|
|
@@ -38,7 +38,7 @@ class TcpForwarderBase:
|
|
|
38
38
|
# socket to its remote socket and vice versa
|
|
39
39
|
self.connections = {}
|
|
40
40
|
|
|
41
|
-
def start(self, address="
|
|
41
|
+
def start(self, address="127.0.0.1"):
|
|
42
42
|
"""forward each connection from given local machine port to remote device port"""
|
|
43
43
|
# create local tcp server socket
|
|
44
44
|
self.server_socket = socket.socket()
|
|
@@ -191,10 +191,16 @@ class TunneldCore:
|
|
|
191
191
|
|
|
192
192
|
@asyncio_print_traceback
|
|
193
193
|
async def monitor_usbmux_task(self) -> None:
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
194
|
+
while True:
|
|
195
|
+
mux = None
|
|
196
|
+
try:
|
|
197
|
+
mux = usbmux.create_mux()
|
|
198
|
+
mux.listen()
|
|
199
|
+
|
|
200
|
+
while True:
|
|
201
|
+
await asyncio.to_thread(mux.receive_device_state_update)
|
|
202
|
+
|
|
203
|
+
for mux_device in mux.devices:
|
|
198
204
|
task_identifier = f"usbmux-{mux_device.serial}-{mux_device.connection_type}"
|
|
199
205
|
if self.tunnel_exists_for_udid(mux_device.serial):
|
|
200
206
|
# Skip if already established a tunnel for this udid
|
|
@@ -227,14 +233,19 @@ class TunneldCore:
|
|
|
227
233
|
name=f"start-tunnel-task-{task_identifier}",
|
|
228
234
|
),
|
|
229
235
|
)
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
236
|
+
except (BlockingIOError, StreamError, OSError) as e:
|
|
237
|
+
# Connection lost - will reconnect on next iteration
|
|
238
|
+
logger.debug(f"usbmux connection error: {e}, reconnecting...")
|
|
239
|
+
except ConnectionFailedToUsbmuxdError:
|
|
240
|
+
# This is exception is expected to occur repeatedly on linux running usbmuxd
|
|
241
|
+
# as long as there isn't any physical iDevice connected
|
|
242
|
+
logger.debug("failed to connect to usbmux. waiting for it to restart")
|
|
243
|
+
await asyncio.sleep(USBMUX_INTERVAL)
|
|
244
|
+
except asyncio.CancelledError:
|
|
245
|
+
break
|
|
246
|
+
finally:
|
|
247
|
+
if mux is not None:
|
|
248
|
+
mux.close()
|
|
238
249
|
|
|
239
250
|
@asyncio_print_traceback
|
|
240
251
|
async def monitor_mobdev2_task(self) -> None:
|