pymobiledevice3 4.27.5__tar.gz → 4.27.7__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.
Potentially problematic release.
This version of pymobiledevice3 might be problematic. Click here for more details.
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/PKG-INFO +1 -1
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/_version.py +3 -3
- pymobiledevice3-4.27.7/pymobiledevice3/restore/mbn.py +606 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/restore/restore.py +22 -10
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/mobile_image_mounter.py +1 -1
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3.egg-info/PKG-INFO +1 -1
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3.egg-info/SOURCES.txt +1 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/.gitattributes +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/.github/FUNDING.yml +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/.github/pull_request_template.md +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/.github/workflows/codeql.yml +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/.github/workflows/generate-executable.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/.github/workflows/markdown-lint.yml +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/.github/workflows/python-app.yml +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/.github/workflows/python-publish.yml +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/.gitignore +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/.pre-commit-config.yaml +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/CODE_OF_CONDUCT.md +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/CONTRIBUTING.md +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/LICENSE +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/README.md +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/example.gif +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/markdownlint-config.json +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/misc/DTServices-14.2.txt +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/misc/DTServices-14.5.txt +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/misc/RemoteXPC.md +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/misc/plist_sniffer.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/misc/pyinstaller.md +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/misc/remotexpc_sniffer.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/misc/understanding_idevice_protocol_layers.md +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/misc/usbmux_sniff.sh +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/__init__.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/__main__.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/bonjour.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/ca.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/cli/__init__.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/cli/activation.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/cli/afc.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/cli/amfi.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/cli/apps.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/cli/backup.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/cli/bonjour.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/cli/cli_common.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/cli/companion_proxy.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/cli/completions.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/cli/crash.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/cli/developer.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/cli/diagnostics.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/cli/lockdown.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/cli/mounter.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/cli/notification.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/cli/pcap.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/cli/power_assertion.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/cli/processes.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/cli/profile.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/cli/provision.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/cli/remote.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/cli/restore.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/cli/springboard.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/cli/syslog.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/cli/usbmux.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/cli/version.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/cli/webinspector.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/common.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/exceptions.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/irecv.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/irecv_devices.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/lockdown.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/lockdown_service_provider.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/osu/__init__.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/osu/os_utils.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/osu/posix_util.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/osu/win_util.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/pair_records.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/remote/__init__.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/remote/common.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/remote/core_device/__init__.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/remote/core_device/app_service.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/remote/core_device/core_device_service.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/remote/core_device/device_info.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/remote/core_device/diagnostics_service.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/remote/core_device/file_service.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/remote/module_imports.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/remote/remote_service.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/remote/remote_service_discovery.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/remote/remotexpc.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/remote/tunnel_service.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/remote/utils.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/remote/xpc_message.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/resources/__init__.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/resources/dsc_uuid_map.json +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/resources/dsc_uuid_map.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/resources/firmware_notifications.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/resources/notifications.txt +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/resources/webinspector/element_attribute.js +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/resources/webinspector/element_clear.js +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/resources/webinspector/enter_fullscreen.js +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/resources/webinspector/find_nodes.js +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/resources/webinspector/focus.js +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/resources/webinspector/get_attribute.js +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/resources/webinspector/is_displayed.js +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/resources/webinspector/is_editable.js +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/resources/webinspector/is_enabled.js +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/restore/__init__.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/restore/asr.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/restore/base_restore.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/restore/consts.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/restore/device.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/restore/fdr.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/restore/ftab.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/restore/img4.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/restore/recovery.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/restore/restore_options.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/restore/restored_client.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/restore/tss.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/service_connection.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/__init__.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/accessibilityaudit.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/afc.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/amfi.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/companion.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/crash_reports.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/debugserver_applist.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/device_arbitration.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/device_link.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/diagnostics.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/dtfetchsymbols.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/dvt/__init__.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/dvt/dvt_secure_socket_proxy.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/dvt/dvt_testmanaged_proxy.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/dvt/instruments/__init__.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/dvt/instruments/activity_trace_tap.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/dvt/instruments/application_listing.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/dvt/instruments/condition_inducer.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/dvt/instruments/core_profile_session_tap.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/dvt/instruments/device_info.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/dvt/instruments/energy_monitor.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/dvt/instruments/graphics.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/dvt/instruments/location_simulation.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/dvt/instruments/location_simulation_base.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/dvt/instruments/network_monitor.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/dvt/instruments/notifications.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/dvt/instruments/process_control.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/dvt/instruments/screenshot.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/dvt/instruments/sysmontap.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/dvt/testmanaged/xcuitest.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/file_relay.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/heartbeat.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/house_arrest.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/installation_proxy.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/lockdown_service.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/misagent.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/mobile_activation.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/mobile_config.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/mobilebackup2.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/notification_proxy.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/os_trace.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/pcapd.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/power_assertion.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/preboard.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/remote_fetch_symbols.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/remote_server.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/restore_service.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/screenshot.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/simulate_location.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/springboard.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/syslog.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/web_protocol/__init__.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/web_protocol/alert.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/web_protocol/automation_session.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/web_protocol/cdp_screencast.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/web_protocol/cdp_server.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/web_protocol/cdp_target.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/web_protocol/driver.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/web_protocol/element.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/web_protocol/inspector_session.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/web_protocol/selenium_api.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/web_protocol/session_protocol.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/web_protocol/switch_to.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/services/webinspector.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/tcp_forwarder.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/tunneld/__init__.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/tunneld/api.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/tunneld/server.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/usbmux.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3/utils.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3.egg-info/dependency_links.txt +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3.egg-info/entry_points.txt +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3.egg-info/requires.txt +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pymobiledevice3.egg-info/top_level.txt +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pyproject.toml +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/pytest.ini +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/requirements.txt +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/setup.cfg +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/tests/__init__.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/tests/cli/__init__.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/tests/cli/test_cli.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/tests/conftest.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/tests/services/__init__.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/tests/services/instruments/__init__.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/tests/services/instruments/test_core_profile_session.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/tests/services/instruments/test_dvt_secure_socket_proxy.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/tests/services/instruments/test_fetch_symbols.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/tests/services/instruments/test_location.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/tests/services/instruments/test_screenshot.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/tests/services/test_accessibility.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/tests/services/test_afc.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/tests/services/test_apps.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/tests/services/test_backup2.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/tests/services/test_bonjour.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/tests/services/test_crash_reports.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/tests/services/test_list_devices.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/tests/services/test_lockdown.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/tests/services/test_pcapd.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/tests/services/test_springboard_services_relay.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/tests/services/test_start_tunnel.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/tests/services/test_syslog_relay.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/tests/services/test_tcp_forwarder.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/tests/services/test_web_protocol/__init__.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/tests/services/test_web_protocol/common.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/tests/services/test_web_protocol/conftest.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/tests/services/test_web_protocol/test_driver.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/tests/services/test_web_protocol/test_element.py +0 -0
- {pymobiledevice3-4.27.5 → pymobiledevice3-4.27.7}/tests/services/test_webinspector.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pymobiledevice3
|
|
3
|
-
Version: 4.27.
|
|
3
|
+
Version: 4.27.7
|
|
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 = '4.27.
|
|
32
|
-
__version_tuple__ = version_tuple = (4, 27,
|
|
31
|
+
__version__ = version = '4.27.7'
|
|
32
|
+
__version_tuple__ = version_tuple = (4, 27, 7)
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'g0f0840055'
|
|
@@ -0,0 +1,606 @@
|
|
|
1
|
+
# mbn.py
|
|
2
|
+
# Support for Qualcomm MBN (Modem Binary) formats — Python port
|
|
3
|
+
# Mirrors the logic of mbn.c (v1/v2/BIN headers, ELF detection, and v7 stitching)
|
|
4
|
+
#
|
|
5
|
+
# Copyright (c) 2012 Martin Szulecki
|
|
6
|
+
# Copyright (c) 2012 Nikias Bassen
|
|
7
|
+
# Copyright (c) 2025 Visual Ehrmanntraut <visual@chefkiss.dev>
|
|
8
|
+
#
|
|
9
|
+
# Ported to Python by DoronZ <doron88@gmail.com>. Licensed under LGPL-2.1-or-later (same as original).
|
|
10
|
+
|
|
11
|
+
import io
|
|
12
|
+
import logging
|
|
13
|
+
from typing import Optional
|
|
14
|
+
|
|
15
|
+
from construct import Bytes, ChecksumError, Int16ul, Int32ul, Int64ul, Struct
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
# -----------------------------------------------------------------------------
|
|
20
|
+
# Constants
|
|
21
|
+
# -----------------------------------------------------------------------------
|
|
22
|
+
MBN_V1_MAGIC = b"\x0a\x00\x00\x00"
|
|
23
|
+
MBN_V1_MAGIC_SIZE = 4
|
|
24
|
+
|
|
25
|
+
MBN_V2_MAGIC = b"\xd1\xdc\x4b\x84\x34\x10\xd7\x73"
|
|
26
|
+
MBN_V2_MAGIC_SIZE = 8
|
|
27
|
+
|
|
28
|
+
MBN_BIN_MAGIC = b"\x04\x00\xea\x6c\x69\x48\x55"
|
|
29
|
+
MBN_BIN_MAGIC_SIZE = 7
|
|
30
|
+
MBN_BIN_MAGIC_OFFSET = 1
|
|
31
|
+
|
|
32
|
+
# ELF
|
|
33
|
+
EI_MAG0, EI_MAG1, EI_MAG2, EI_MAG3, EI_CLASS = 0, 1, 2, 3, 4
|
|
34
|
+
EI_NIDENT = 16
|
|
35
|
+
ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3 = 0x7F, ord("E"), ord("L"), ord("F")
|
|
36
|
+
ELFCLASSNONE, ELFCLASS32, ELFCLASS64 = 0, 1, 2
|
|
37
|
+
|
|
38
|
+
# -----------------------------------------------------------------------------
|
|
39
|
+
# Construct Structs (little-endian)
|
|
40
|
+
# -----------------------------------------------------------------------------
|
|
41
|
+
|
|
42
|
+
# MBN v1
|
|
43
|
+
MBN_V1 = Struct(
|
|
44
|
+
"type" / Int32ul,
|
|
45
|
+
"unk_0x04" / Int32ul,
|
|
46
|
+
"unk_0x08" / Int32ul,
|
|
47
|
+
"unk_0x0c" / Int32ul,
|
|
48
|
+
"data_size" / Int32ul, # total - sizeof(header)
|
|
49
|
+
"sig_offset" / Int32ul, # real offset = enc_sig_offset & 0xFFFFFF00 (FYI)
|
|
50
|
+
"unk_0x18" / Int32ul,
|
|
51
|
+
"unk_0x1c" / Int32ul,
|
|
52
|
+
"unk_0x20" / Int32ul,
|
|
53
|
+
"unk_0x24" / Int32ul,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
# MBN v2
|
|
57
|
+
MBN_V2 = Struct(
|
|
58
|
+
"magic1" / Bytes(8),
|
|
59
|
+
"unk_0x08" / Int32ul,
|
|
60
|
+
"unk_0x0c" / Int32ul, # 0xFFFFFFFF
|
|
61
|
+
"unk_0x10" / Int32ul, # 0xFFFFFFFF
|
|
62
|
+
"header_size" / Int32ul,
|
|
63
|
+
"unk_0x18" / Int32ul,
|
|
64
|
+
"data_size" / Int32ul, # total - sizeof(header)
|
|
65
|
+
"sig_offset" / Int32ul,
|
|
66
|
+
"unk_0x24" / Int32ul,
|
|
67
|
+
"unk_0x28" / Int32ul,
|
|
68
|
+
"unk_0x2c" / Int32ul,
|
|
69
|
+
"unk_0x30" / Int32ul,
|
|
70
|
+
"unk_0x34" / Int32ul, # 0x1
|
|
71
|
+
"unk_0x38" / Int32ul, # 0x1
|
|
72
|
+
"unk_0x3c" / Int32ul, # 0xFFFFFFFF
|
|
73
|
+
"unk_0x40" / Int32ul, # 0xFFFFFFFF
|
|
74
|
+
"unk_0x44" / Int32ul, # 0xFFFFFFFF
|
|
75
|
+
"unk_0x48" / Int32ul, # 0xFFFFFFFF
|
|
76
|
+
"unk_0x4c" / Int32ul, # 0xFFFFFFFF
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
# MBN BIN
|
|
80
|
+
MBN_BIN = Struct(
|
|
81
|
+
"magic" / Bytes(8),
|
|
82
|
+
"unk_0x08" / Int32ul,
|
|
83
|
+
"version" / Int32ul,
|
|
84
|
+
"total_size" / Int32ul, # includes header
|
|
85
|
+
"unk_0x14" / Int32ul,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
# v7 trailer header used by mbn_mav25_stitch
|
|
89
|
+
MBN_V7 = Struct(
|
|
90
|
+
"reserved" / Int32ul,
|
|
91
|
+
"version" / Int32ul,
|
|
92
|
+
"common_metadata_size" / Int32ul,
|
|
93
|
+
"qti_metadata_size" / Int32ul,
|
|
94
|
+
"oem_metadata_size" / Int32ul,
|
|
95
|
+
"hash_table_size" / Int32ul,
|
|
96
|
+
"qti_signature_size" / Int32ul,
|
|
97
|
+
"qti_certificate_chain_size" / Int32ul,
|
|
98
|
+
"oem_signature_size" / Int32ul,
|
|
99
|
+
"oem_certificate_chain_size" / Int32ul,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
# ELF (minimal fields we need)
|
|
103
|
+
ELF32_Ehdr = Struct(
|
|
104
|
+
"e_ident" / Bytes(16),
|
|
105
|
+
"e_type" / Int16ul,
|
|
106
|
+
"e_machine" / Int16ul,
|
|
107
|
+
"e_version" / Int32ul,
|
|
108
|
+
"e_entry" / Int32ul,
|
|
109
|
+
"e_phoff" / Int32ul,
|
|
110
|
+
"e_shoff" / Int32ul,
|
|
111
|
+
"e_flags" / Int32ul,
|
|
112
|
+
"e_ehsize" / Int16ul,
|
|
113
|
+
"e_phentsize" / Int16ul,
|
|
114
|
+
"e_phnum" / Int16ul,
|
|
115
|
+
"e_shentsize" / Int16ul,
|
|
116
|
+
"e_shnum" / Int16ul,
|
|
117
|
+
"e_shstrndx" / Int16ul,
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
ELF64_Ehdr = Struct(
|
|
121
|
+
"e_ident" / Bytes(16),
|
|
122
|
+
"e_type" / Int16ul,
|
|
123
|
+
"e_machine" / Int16ul,
|
|
124
|
+
"e_version" / Int32ul,
|
|
125
|
+
"e_entry" / Int64ul,
|
|
126
|
+
"e_phoff" / Int64ul,
|
|
127
|
+
"e_shoff" / Int64ul,
|
|
128
|
+
"e_flags" / Int32ul,
|
|
129
|
+
"e_ehsize" / Int16ul,
|
|
130
|
+
"e_phentsize" / Int16ul,
|
|
131
|
+
"e_phnum" / Int16ul,
|
|
132
|
+
"e_shentsize" / Int16ul,
|
|
133
|
+
"e_shnum" / Int16ul,
|
|
134
|
+
"e_shstrndx" / Int16ul,
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
ELF32_Phdr = Struct(
|
|
138
|
+
"p_type" / Int32ul,
|
|
139
|
+
"p_offset" / Int32ul,
|
|
140
|
+
"p_vaddr" / Int32ul,
|
|
141
|
+
"p_paddr" / Int32ul,
|
|
142
|
+
"p_filesz" / Int32ul,
|
|
143
|
+
"p_memsz" / Int32ul,
|
|
144
|
+
"p_flags" / Int32ul,
|
|
145
|
+
"p_align" / Int32ul,
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
ELF64_Phdr = Struct(
|
|
149
|
+
"p_type" / Int32ul,
|
|
150
|
+
"p_flags" / Int32ul,
|
|
151
|
+
"p_offset" / Int64ul,
|
|
152
|
+
"p_vaddr" / Int64ul,
|
|
153
|
+
"p_paddr" / Int64ul,
|
|
154
|
+
"p_filesz" / Int64ul,
|
|
155
|
+
"p_memsz" / Int64ul,
|
|
156
|
+
"p_align" / Int64ul,
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
# -----------------------------------------------------------------------------
|
|
161
|
+
# Helpers
|
|
162
|
+
# -----------------------------------------------------------------------------
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def _is_valid_elf_ident(e_ident: bytes) -> bool:
|
|
166
|
+
return (
|
|
167
|
+
len(e_ident) >= EI_NIDENT
|
|
168
|
+
and e_ident[EI_MAG0] == ELFMAG0
|
|
169
|
+
and e_ident[EI_MAG1] == ELFMAG1
|
|
170
|
+
and e_ident[EI_MAG2] == ELFMAG2
|
|
171
|
+
and e_ident[EI_MAG3] == ELFMAG3
|
|
172
|
+
and e_ident[EI_CLASS] != ELFCLASSNONE
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def _read_elf_headers(data: bytes):
|
|
177
|
+
if len(data) < EI_NIDENT:
|
|
178
|
+
return None, None
|
|
179
|
+
e_ident = data[:EI_NIDENT]
|
|
180
|
+
if not _is_valid_elf_ident(e_ident):
|
|
181
|
+
return None, None
|
|
182
|
+
if e_ident[EI_CLASS] == ELFCLASS64:
|
|
183
|
+
if len(data) < ELF64_Ehdr.sizeof():
|
|
184
|
+
return None, None
|
|
185
|
+
hdr = ELF64_Ehdr.parse(data[: ELF64_Ehdr.sizeof()])
|
|
186
|
+
return "ELF64", hdr
|
|
187
|
+
elif e_ident[EI_CLASS] == ELFCLASS32:
|
|
188
|
+
if len(data) < ELF32_Ehdr.sizeof():
|
|
189
|
+
return None, None
|
|
190
|
+
hdr = ELF32_Ehdr.parse(data[: ELF32_Ehdr.sizeof()])
|
|
191
|
+
return "ELF32", hdr
|
|
192
|
+
return None, None
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def _read_program_headers(data: bytes, kind: str, hdr) -> list:
|
|
196
|
+
phdrs = []
|
|
197
|
+
if hdr.e_phnum == 0:
|
|
198
|
+
logger.error("%s: ELF has no program sections", "_read_program_headers")
|
|
199
|
+
return phdrs
|
|
200
|
+
|
|
201
|
+
table_size = hdr.e_phnum * (
|
|
202
|
+
ELF64_Phdr.sizeof() if kind == "ELF64" else ELF32_Phdr.sizeof()
|
|
203
|
+
)
|
|
204
|
+
if hdr.e_phoff + table_size > len(data):
|
|
205
|
+
logger.error(
|
|
206
|
+
"%s: Program header table is out of bounds", "_read_program_headers"
|
|
207
|
+
)
|
|
208
|
+
return []
|
|
209
|
+
|
|
210
|
+
table = data[hdr.e_phoff:hdr.e_phoff + table_size]
|
|
211
|
+
bio = io.BytesIO(table)
|
|
212
|
+
for _ in range(hdr.e_phnum):
|
|
213
|
+
if kind == "ELF64":
|
|
214
|
+
ph = ELF64_Phdr.parse_stream(bio)
|
|
215
|
+
else:
|
|
216
|
+
ph = ELF32_Phdr.parse_stream(bio)
|
|
217
|
+
phdrs.append(ph)
|
|
218
|
+
return phdrs
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def _elf_last_segment_end(data: bytes) -> Optional[int]:
|
|
222
|
+
kind, hdr = _read_elf_headers(data)
|
|
223
|
+
if not hdr:
|
|
224
|
+
return None
|
|
225
|
+
phdrs = _read_program_headers(data, kind, hdr)
|
|
226
|
+
if not phdrs:
|
|
227
|
+
return None
|
|
228
|
+
# last by highest p_offset
|
|
229
|
+
last = max(phdrs, key=lambda p: int(p.p_offset))
|
|
230
|
+
return int(last.p_offset + last.p_filesz)
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def _mbn_v7_header_sizes_valid(h, sect_size: int) -> bool:
|
|
234
|
+
total = (
|
|
235
|
+
MBN_V7.sizeof()
|
|
236
|
+
+ h.common_metadata_size
|
|
237
|
+
+ h.qti_metadata_size
|
|
238
|
+
+ h.oem_metadata_size
|
|
239
|
+
+ h.hash_table_size
|
|
240
|
+
+ h.qti_signature_size
|
|
241
|
+
+ h.qti_certificate_chain_size
|
|
242
|
+
+ h.oem_signature_size
|
|
243
|
+
+ h.oem_certificate_chain_size
|
|
244
|
+
)
|
|
245
|
+
return total <= sect_size
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def _mbn_v7_header_sizes_expected(h) -> bool:
|
|
249
|
+
return (
|
|
250
|
+
(h.qti_metadata_size in (0, 0xE0))
|
|
251
|
+
and (h.oem_metadata_size in (0, 0xE0))
|
|
252
|
+
and (h.oem_signature_size in (0, 0x68))
|
|
253
|
+
and (h.oem_certificate_chain_size in (0, 0xD20))
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
def _mbn_v7_log(h, func: str, prefix: str) -> None:
|
|
258
|
+
logger.debug(
|
|
259
|
+
"%s: %s header {version=0x%x, common_metadata_size=0x%x, qti_metadata_size=0x%x, "
|
|
260
|
+
"oem_metadata_size=0x%x, hash_table_size=0x%x, qti_signature_size=0x%x, "
|
|
261
|
+
"qti_certificate_chain_size=0x%x, oem_signature_size=0x%x, oem_certificate_chain_size=0x%x}",
|
|
262
|
+
func,
|
|
263
|
+
prefix,
|
|
264
|
+
h.version,
|
|
265
|
+
h.common_metadata_size,
|
|
266
|
+
h.qti_metadata_size,
|
|
267
|
+
h.oem_metadata_size,
|
|
268
|
+
h.hash_table_size,
|
|
269
|
+
h.qti_signature_size,
|
|
270
|
+
h.qti_certificate_chain_size,
|
|
271
|
+
h.oem_signature_size,
|
|
272
|
+
h.oem_certificate_chain_size,
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
# -----------------------------------------------------------------------------
|
|
277
|
+
# Public API
|
|
278
|
+
# -----------------------------------------------------------------------------
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
def mbn_stitch(data: bytes, blob: bytes) -> Optional[bytes]:
|
|
282
|
+
"""
|
|
283
|
+
Overwrite the tail of `data` with `blob`. Format-aware size logging/checks.
|
|
284
|
+
Returns new bytes or None.
|
|
285
|
+
"""
|
|
286
|
+
if data is None:
|
|
287
|
+
logger.error("%s: data is NULL", "mbn_stitch")
|
|
288
|
+
return None
|
|
289
|
+
if not data:
|
|
290
|
+
logger.error("%s: data size is 0", "mbn_stitch")
|
|
291
|
+
return None
|
|
292
|
+
if blob is None:
|
|
293
|
+
logger.error("%s: blob is NULL", "mbn_stitch")
|
|
294
|
+
return None
|
|
295
|
+
if not blob:
|
|
296
|
+
logger.error("%s: blob size is 0", "mbn_stitch")
|
|
297
|
+
return None
|
|
298
|
+
|
|
299
|
+
data_size = len(data)
|
|
300
|
+
blob_size = len(blob)
|
|
301
|
+
parsed_size = 0
|
|
302
|
+
|
|
303
|
+
try:
|
|
304
|
+
# MBN v2
|
|
305
|
+
if data_size > MBN_V2_MAGIC_SIZE and data[:MBN_V2_MAGIC_SIZE] == MBN_V2_MAGIC:
|
|
306
|
+
if data_size < MBN_V2.sizeof():
|
|
307
|
+
logger.error("%s: truncated MBN v2 header", "mbn_stitch")
|
|
308
|
+
return None
|
|
309
|
+
h = MBN_V2.parse(data[: MBN_V2.sizeof()])
|
|
310
|
+
parsed_size = h.data_size + MBN_V2.sizeof()
|
|
311
|
+
logger.debug(
|
|
312
|
+
"%s: encountered MBN v2 image, parsed_size = 0x%x",
|
|
313
|
+
"mbn_stitch",
|
|
314
|
+
parsed_size,
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
# MBN v1
|
|
318
|
+
elif data_size > MBN_V1_MAGIC_SIZE and data[:MBN_V1_MAGIC_SIZE] == MBN_V1_MAGIC:
|
|
319
|
+
if data_size < MBN_V1.sizeof():
|
|
320
|
+
logger.error("%s: truncated MBN v1 header", "mbn_stitch")
|
|
321
|
+
return None
|
|
322
|
+
h = MBN_V1.parse(data[: MBN_V1.sizeof()])
|
|
323
|
+
parsed_size = h.data_size + MBN_V1.sizeof()
|
|
324
|
+
logger.debug(
|
|
325
|
+
"%s: encountered MBN v1 image, parsed_size = 0x%x",
|
|
326
|
+
"mbn_stitch",
|
|
327
|
+
parsed_size,
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
# BIN
|
|
331
|
+
elif (
|
|
332
|
+
data_size > (MBN_BIN_MAGIC_SIZE + MBN_BIN_MAGIC_OFFSET)
|
|
333
|
+
and data[MBN_BIN_MAGIC_OFFSET:MBN_BIN_MAGIC_OFFSET + MBN_BIN_MAGIC_SIZE]
|
|
334
|
+
== MBN_BIN_MAGIC
|
|
335
|
+
):
|
|
336
|
+
if data_size < MBN_BIN.sizeof():
|
|
337
|
+
logger.error("%s: truncated MBN BIN header", "mbn_stitch")
|
|
338
|
+
return None
|
|
339
|
+
h = MBN_BIN.parse(data[: MBN_BIN.sizeof()])
|
|
340
|
+
parsed_size = h.total_size
|
|
341
|
+
logger.debug(
|
|
342
|
+
"%s: encountered MBN BIN image, parsed_size = 0x%x",
|
|
343
|
+
"mbn_stitch",
|
|
344
|
+
parsed_size,
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
# ELF
|
|
348
|
+
else:
|
|
349
|
+
end = _elf_last_segment_end(data)
|
|
350
|
+
if end is not None:
|
|
351
|
+
parsed_size = end
|
|
352
|
+
logger.debug(
|
|
353
|
+
"%s: encountered ELF image, parsed_size = 0x%x",
|
|
354
|
+
"mbn_stitch",
|
|
355
|
+
parsed_size,
|
|
356
|
+
)
|
|
357
|
+
else:
|
|
358
|
+
logger.warning("Unknown file format passed to %s", "mbn_stitch")
|
|
359
|
+
parsed_size = data_size
|
|
360
|
+
|
|
361
|
+
if parsed_size != data_size:
|
|
362
|
+
logger.warning(
|
|
363
|
+
"%s: size mismatch for MBN data, expected 0x%x, input size 0x%x",
|
|
364
|
+
"mbn_stitch",
|
|
365
|
+
parsed_size,
|
|
366
|
+
data_size,
|
|
367
|
+
)
|
|
368
|
+
|
|
369
|
+
stitch_offset = data_size - blob_size
|
|
370
|
+
if stitch_offset < 0 or stitch_offset + blob_size > data_size:
|
|
371
|
+
logger.error(
|
|
372
|
+
"%s: stitch offset (0x%x) + size (0x%x) is larger than the destination (0x%x)",
|
|
373
|
+
"mbn_stitch",
|
|
374
|
+
stitch_offset,
|
|
375
|
+
blob_size,
|
|
376
|
+
data_size,
|
|
377
|
+
)
|
|
378
|
+
return None
|
|
379
|
+
|
|
380
|
+
out = bytearray(data)
|
|
381
|
+
logger.debug(
|
|
382
|
+
"%s: stitching mbn at 0x%x, size 0x%x",
|
|
383
|
+
"mbn_stitch",
|
|
384
|
+
stitch_offset,
|
|
385
|
+
blob_size,
|
|
386
|
+
)
|
|
387
|
+
out[stitch_offset: stitch_offset + blob_size] = blob
|
|
388
|
+
return bytes(out)
|
|
389
|
+
|
|
390
|
+
except ChecksumError as e:
|
|
391
|
+
logger.error("%s: construct checksum error: %s", "mbn_stitch", str(e))
|
|
392
|
+
return None
|
|
393
|
+
except Exception as e:
|
|
394
|
+
logger.error("%s: unexpected error: %s", "mbn_stitch", str(e))
|
|
395
|
+
return None
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
def mbn_mav25_stitch(data: bytes, blob: bytes) -> Optional[bytes]:
|
|
399
|
+
"""
|
|
400
|
+
Patch an ELF's last program-section area with a v7 trailer from `blob`.
|
|
401
|
+
- Writes new metadata+hash at section start
|
|
402
|
+
- Writes OEM sig+chain after existing dest qti sig+chain
|
|
403
|
+
Returns new bytes or None.
|
|
404
|
+
"""
|
|
405
|
+
if data is None:
|
|
406
|
+
logger.error("%s: data is NULL", "mbn_mav25_stitch")
|
|
407
|
+
return None
|
|
408
|
+
if not data:
|
|
409
|
+
logger.error("%s: data size is 0", "mbn_mav25_stitch")
|
|
410
|
+
return None
|
|
411
|
+
if blob is None:
|
|
412
|
+
logger.error("%s: blob is NULL", "mbn_mav25_stitch")
|
|
413
|
+
return None
|
|
414
|
+
if not blob:
|
|
415
|
+
logger.error("%s: blob size is 0", "mbn_mav25_stitch")
|
|
416
|
+
return None
|
|
417
|
+
|
|
418
|
+
data_size, blob_size = len(data), len(blob)
|
|
419
|
+
|
|
420
|
+
kind, ehdr = _read_elf_headers(data)
|
|
421
|
+
if not ehdr:
|
|
422
|
+
logger.error("%s: data is not a valid ELF", "mbn_mav25_stitch")
|
|
423
|
+
return None
|
|
424
|
+
|
|
425
|
+
if blob_size < MBN_V7.sizeof():
|
|
426
|
+
logger.error("%s: header is bigger than blob", "mbn_mav25_stitch")
|
|
427
|
+
return None
|
|
428
|
+
|
|
429
|
+
src = MBN_V7.parse(blob[: MBN_V7.sizeof()])
|
|
430
|
+
_mbn_v7_log(src, "mbn_mav25_stitch", "src")
|
|
431
|
+
if src.version != 7:
|
|
432
|
+
logger.error(
|
|
433
|
+
"%s: src header version (0x%x) is incorrect",
|
|
434
|
+
"mbn_mav25_stitch",
|
|
435
|
+
src.version,
|
|
436
|
+
)
|
|
437
|
+
return None
|
|
438
|
+
if not _mbn_v7_header_sizes_expected(src):
|
|
439
|
+
logger.warning(
|
|
440
|
+
"%s: header sizes in header are unexpected (qti_metadata_size=0x%x, oem_metadata_size=0x%x, "
|
|
441
|
+
"oem_signature_size=0x%x, oem_certificate_chain_size=0x%x)",
|
|
442
|
+
"mbn_mav25_stitch",
|
|
443
|
+
src.qti_metadata_size,
|
|
444
|
+
src.oem_metadata_size,
|
|
445
|
+
src.oem_signature_size,
|
|
446
|
+
src.oem_certificate_chain_size,
|
|
447
|
+
)
|
|
448
|
+
|
|
449
|
+
# last PHDR (by index)
|
|
450
|
+
phdrs = _read_program_headers(data, kind, ehdr)
|
|
451
|
+
if not phdrs:
|
|
452
|
+
return None
|
|
453
|
+
last_ph = phdrs[-1]
|
|
454
|
+
sect_off, sect_size = int(last_ph.p_offset), int(last_ph.p_filesz)
|
|
455
|
+
|
|
456
|
+
if sect_off == 0:
|
|
457
|
+
logger.error("%s: section has 0 offset", "mbn_mav25_stitch")
|
|
458
|
+
return None
|
|
459
|
+
if sect_size == 0:
|
|
460
|
+
logger.error("%s: section has 0 size", "mbn_mav25_stitch")
|
|
461
|
+
return None
|
|
462
|
+
if sect_off + sect_size > data_size:
|
|
463
|
+
logger.error(
|
|
464
|
+
"%s: section (0x%x+0x%x) is bigger than the data",
|
|
465
|
+
"mbn_mav25_stitch",
|
|
466
|
+
sect_off,
|
|
467
|
+
sect_size,
|
|
468
|
+
)
|
|
469
|
+
return None
|
|
470
|
+
if sect_size < MBN_V7.sizeof():
|
|
471
|
+
logger.error(
|
|
472
|
+
"%s: dest header is bigger than the section (0x%x)",
|
|
473
|
+
"mbn_mav25_stitch",
|
|
474
|
+
sect_size,
|
|
475
|
+
)
|
|
476
|
+
return None
|
|
477
|
+
|
|
478
|
+
dest = MBN_V7.parse(data[sect_off: sect_off + MBN_V7.sizeof()])
|
|
479
|
+
_mbn_v7_log(dest, "mbn_mav25_stitch", "dest")
|
|
480
|
+
if dest.version != 7:
|
|
481
|
+
logger.error(
|
|
482
|
+
"%s: dest header version (0x%x) is incorrect",
|
|
483
|
+
"mbn_mav25_stitch",
|
|
484
|
+
dest.version,
|
|
485
|
+
)
|
|
486
|
+
return None
|
|
487
|
+
if not _mbn_v7_header_sizes_valid(dest, sect_size):
|
|
488
|
+
logger.error(
|
|
489
|
+
(
|
|
490
|
+
"%s: sizes in dest header are invalid (common_metadata_size=0x%x, qti_metadata_size=0x%x, "
|
|
491
|
+
"oem_metadata_size=0x%x, hash_table_size=0x%x, qti_signature_size=0x%x, "
|
|
492
|
+
"qti_certificate_chain_size=0x%x, oem_signature_size=0x%x, "
|
|
493
|
+
"oem_certificate_chain_size=0x%x)"
|
|
494
|
+
),
|
|
495
|
+
"mbn_mav25_stitch",
|
|
496
|
+
dest.common_metadata_size,
|
|
497
|
+
dest.qti_metadata_size,
|
|
498
|
+
dest.oem_metadata_size,
|
|
499
|
+
dest.hash_table_size,
|
|
500
|
+
dest.qti_signature_size,
|
|
501
|
+
dest.qti_certificate_chain_size,
|
|
502
|
+
dest.oem_signature_size,
|
|
503
|
+
dest.oem_certificate_chain_size,
|
|
504
|
+
)
|
|
505
|
+
return None
|
|
506
|
+
if not _mbn_v7_header_sizes_expected(dest):
|
|
507
|
+
logger.warning(
|
|
508
|
+
"%s: header sizes in dest header are unexpected (qti_metadata_size=0x%x, oem_metadata_size=0x%x, "
|
|
509
|
+
"oem_signature_size=0x%x, oem_certificate_chain_size=0x%x)",
|
|
510
|
+
"mbn_mav25_stitch",
|
|
511
|
+
dest.qti_metadata_size,
|
|
512
|
+
dest.oem_metadata_size,
|
|
513
|
+
dest.oem_signature_size,
|
|
514
|
+
dest.oem_certificate_chain_size,
|
|
515
|
+
)
|
|
516
|
+
|
|
517
|
+
# compute new layout from src
|
|
518
|
+
new_metadata_size = (
|
|
519
|
+
MBN_V7.sizeof()
|
|
520
|
+
+ src.common_metadata_size
|
|
521
|
+
+ src.qti_metadata_size
|
|
522
|
+
+ src.oem_metadata_size
|
|
523
|
+
)
|
|
524
|
+
new_metadata_and_hash_table_size = new_metadata_size + src.hash_table_size
|
|
525
|
+
new_oem_sig_and_cert_chain_size = (
|
|
526
|
+
src.oem_signature_size + src.oem_certificate_chain_size
|
|
527
|
+
)
|
|
528
|
+
|
|
529
|
+
new_oem_sig_and_cert_chain_off = (
|
|
530
|
+
new_metadata_and_hash_table_size
|
|
531
|
+
+ dest.qti_signature_size
|
|
532
|
+
+ dest.qti_certificate_chain_size
|
|
533
|
+
)
|
|
534
|
+
|
|
535
|
+
# bounds
|
|
536
|
+
if new_metadata_and_hash_table_size > blob_size:
|
|
537
|
+
logger.error(
|
|
538
|
+
"%s: new metadata (0x%x) and hash table (0x%x) are bigger than the source (0x%x)",
|
|
539
|
+
"mbn_mav25_stitch",
|
|
540
|
+
new_metadata_size,
|
|
541
|
+
src.hash_table_size,
|
|
542
|
+
blob_size,
|
|
543
|
+
)
|
|
544
|
+
return None
|
|
545
|
+
if new_metadata_and_hash_table_size > sect_size:
|
|
546
|
+
logger.error(
|
|
547
|
+
"%s: new metadata (0x%x) and hash table (0x%x) are bigger than the destination (0x%x)",
|
|
548
|
+
"mbn_mav25_stitch",
|
|
549
|
+
new_metadata_size,
|
|
550
|
+
src.hash_table_size,
|
|
551
|
+
sect_size,
|
|
552
|
+
)
|
|
553
|
+
return None
|
|
554
|
+
if new_metadata_and_hash_table_size + new_oem_sig_and_cert_chain_size > blob_size:
|
|
555
|
+
logger.error(
|
|
556
|
+
"%s: new OEM signature and certificate chain are bigger than the source",
|
|
557
|
+
"mbn_mav25_stitch",
|
|
558
|
+
)
|
|
559
|
+
return None
|
|
560
|
+
if new_oem_sig_and_cert_chain_off + new_oem_sig_and_cert_chain_size > sect_size:
|
|
561
|
+
logger.error(
|
|
562
|
+
"%s: new OEM signature and certificate chain are outside the bounds of the destination",
|
|
563
|
+
"mbn_mav25_stitch",
|
|
564
|
+
)
|
|
565
|
+
return None
|
|
566
|
+
|
|
567
|
+
out = bytearray(data)
|
|
568
|
+
# write metadata + hash
|
|
569
|
+
logger.debug(
|
|
570
|
+
"%s: stitching mbn at 0x%x (0x%x bytes)",
|
|
571
|
+
"mbn_mav25_stitch",
|
|
572
|
+
sect_off,
|
|
573
|
+
new_metadata_and_hash_table_size,
|
|
574
|
+
)
|
|
575
|
+
out[sect_off: sect_off + new_metadata_and_hash_table_size] = blob[
|
|
576
|
+
:new_metadata_and_hash_table_size
|
|
577
|
+
]
|
|
578
|
+
|
|
579
|
+
# write OEM sig + chain
|
|
580
|
+
logger.debug(
|
|
581
|
+
"%s: stitching mbn at 0x%x (0x%x bytes)",
|
|
582
|
+
"mbn_mav25_stitch",
|
|
583
|
+
sect_off + new_oem_sig_and_cert_chain_off,
|
|
584
|
+
new_oem_sig_and_cert_chain_size,
|
|
585
|
+
)
|
|
586
|
+
start = new_metadata_and_hash_table_size
|
|
587
|
+
end = start + new_oem_sig_and_cert_chain_size
|
|
588
|
+
|
|
589
|
+
slice_start = sect_off + new_oem_sig_and_cert_chain_off
|
|
590
|
+
slice_end = sect_off + new_oem_sig_and_cert_chain_off + new_oem_sig_and_cert_chain_size
|
|
591
|
+
out[slice_start:slice_end] = blob[start:end]
|
|
592
|
+
|
|
593
|
+
return bytes(out)
|
|
594
|
+
|
|
595
|
+
|
|
596
|
+
# -----------------------------------------------------------------------------
|
|
597
|
+
# Tiny helpers (optional)
|
|
598
|
+
# -----------------------------------------------------------------------------
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
def mbn_is_valid_elf(buf: bytes) -> bool:
|
|
602
|
+
return len(buf) >= EI_NIDENT and _is_valid_elf_ident(buf[:EI_NIDENT])
|
|
603
|
+
|
|
604
|
+
|
|
605
|
+
def mbn_is_64bit_elf(buf: bytes) -> bool:
|
|
606
|
+
return len(buf) >= EI_NIDENT and buf[EI_CLASS] == ELFCLASS64
|