pym

pymobiledevice3

Pure python3 implementation for working with iDevices (iPhone, etc...).

Showing:

Popularity

Downloads/wk

0

GitHub Stars

79

Maintenance

Last Commit

6d ago

Contributors

15

Package

Dependencies

19

License

Categories

Readme

Python application Pypi version Language grade: Python

Description

pymobiledevice3 is a pure python3 implementation for working with iDevices (iPhone, etc...).

Main features include:

  • TCP port forwarding
  • Viewing syslog lines (including debug)
  • Profile management
  • Application management
  • File system management (AFC)
  • Crash reports management
  • Network sniffing
  • Firmware update
  • Mounting images
  • Notification listening and triggering (notify_post() api)
  • Querying and setting SpringBoard options
  • DeveloperDiskImage features:
    • Taking screenshots
    • Simulate locations
    • Process management
    • Sniffing KDebug messages (strace capabilities++)
    • Process monitoring (top like)
    • Accessibility features
  • Backup

Installation

Install the last released version using pip:

python3 -m pip install --user -U pymobiledevice3

Or install the latest version from sources:

git clone git@github.com:doronz88/pymobiledevice3.git
cd pymobiledevice3
python3 -m pip install --user -U -e .

You can also install auto-completion for all available sub-commands by adding the following into your ~/.zshrc:

# python-click<8.0
eval "$(_PYMOBILEDEVICE3_COMPLETE=source_zsh pymobiledevice3)"
# python-click>=8.0
eval "$(_PYMOBILEDEVICE3_COMPLETE=zsh_source pymobiledevice3)"

Lower iOS versions (<13)

If you wish to use pymobiledevice3 with iOS versions lower than 13, Make sure to install openssl:

On MAC:

brew install openssl

On Linux:

sudo apt install openssl

Usage

You can either use the CLI:

Usage: pymobiledevice3 [OPTIONS] COMMAND [ARGS]...

Options:
  --help  Show this message and exit.

Commands:
  activation       activation options
  afc              FileSystem utils
  apps             application options
  backup2          backup utils
  companion        companion options
  crash            crash report options
  developer        developer options.
  diagnostics      diagnostics options
  list-devices     list connected devices
  lockdown         lockdown options
  mounter          mounter options
  notification     notification options
  pcap             sniff device traffic
  power-assertion  Create a power assertion (wraps...
  processes        processes cli
  profile          profile options
  provision        privision options
  restore          restore options
  springboard      springboard options
  syslog           syslog options

Or import and use the API yourself:

from pymobiledevice3.lockdown import LockdownClient
from pymobiledevice3.services.syslog import SyslogService

lockdown = LockdownClient()
for line in SyslogService(lockdown=lockdown).watch():
    # just print all syslog lines as is
    print(line)

Example

A recorded example can be viewed at:

https://terminalizer.com/view/18920b405193

Lockdown services

SupportServiceDescription
DONEcom.apple.mobile.heartbeatJust a ping to lockdownd service
DONEcom.apple.mobileactivationdActivation services
DONEcom.apple.afcFile access for /var/mobile/Media
DONEcom.apple.crashreportcopymobileFile access for /var/mobile/Library/Logs/CrashReports
DONEcom.apple.pcapdSniff device's network traffic
DONEcom.apple.syslog_relayJust streams syslog lines as raw strings
DONEcom.apple.os_trace_relayMore extensive syslog monitoring
DONEcom.apple.mobile.diagnostics_relayGeneral diagnostic tools
DONEcom.apple.mobile.notification_proxyAPI wrapper for notify_post() & notify_register_dispatch()
DONEcom.apple.crashreportmoverJust trigger crash_mover to move all crash reports into crash directory
DONEcom.apple.mobile.MCInstallProfile management
DONEcom.apple.misagentProvisioning Profiles management
DONEcom.apple.companion_proxyCompanion features (watches and etc.)
DONEcom.apple.mobilebackup2Local backup management
DONEcom.apple.mobile.assertion_agentCreate power assertion to prevent different kinds of sleep
DONEcom.apple.springboardservicesIcon related
DONEcom.apple.mobile.mobile_image_mounterImage mounter service (used for DeveloperDiskImage mounting)
DONEcom.apple.mobile.house_arrestGet AFC utils (file management per application bundle)
DONEcom.apple.mobile.installation_proxyApplication management
DONEcom.apple.instruments.remoteserverDeveloper instrumentation service, iOS<14 (DeveloperDiskImage)
DONEcom.apple.instruments.remoteserver.DVTSecureSocketProxyDeveloper instrumentation service, iOS>=14 (DeveloperDiskImage)
DONEcom.apple.mobile.screenshotrTake screenshot into a PNG format (DeveloperDiskImage)
DONEcom.apple.accessibility.axAuditDaemon.remoteserverAccessibility features (DeveloperDiskImage)
DONEcom.apple.dt.simulatelocationAllows to simulate locations (DeveloperDiskImage)
DONEcom.apple.dt.fetchsymbolsAllows fetching of dyld and dyld shared cache files (DeveloperDiskImage)
Not yetcom.apple.idamdAllows settings the IDAM configuration (whatever that means...)
Not yetcom.apple.atcAirTraffic related
Not yetcom.apple.ait.aitdAirTraffic related
Not yetcom.apple.mobile.file_relayFile access for iOS <= 8
Not yetcom.apple.mobile.insecure_notification_proxyAPI wrapper for notify_post() & notify_register_dispatch() from whitelist
Not yetcom.apple.mobilesync
Not yetcom.apple.purpletestr
Not yetcom.apple.webinspectorUsed to debug WebViews

com.apple.instruments.remoteserver.DVTSecureSocketProxy

Exports several ObjC objects and allows calling their respective selectors. The /Developer/Library/PrivateFrameworks/DVTInstrumentsFoundation.framework/DTServiceHub service reads the configuration stored from [[NSUserDefaults standardUserDefaults] boolForKey:@"DTXConnectionTracer"] If the value is true, then /tmp/DTServiceHub[PID].DTXConnection.RANDOM.log is created and can be used to debug the transport protocol.

For example:

root@iPhone (/var/root)# tail -f /tmp/DTServiceHub[369].DTXConnection.qNjM2U.log
170.887982 x4 resuming [c0]: <DTXConnection 0x100d20670 : x4>
170.889120 x4   sent   [c0]: < DTXMessage 0x100d52b10 : i2.0 c0 dispatch:[_notifyOfPublishedCapabilities:<NSDictionary 0x100d0e1b0 | 92 key/value pairs>] >
170.889547 x4 received [c0]: < DTXMessage 0x100d0a550 : i1.0 c0 dispatch:[_notifyOfPublishedCapabilities:<NSDictionary 0x100d16a40 | 2 key/value pairs>] >
170.892101 x4 received [c0]: < DTXMessage 0x100d0a550 : i3.0e c0 dispatch:[_requestChannelWithCode:[1]identifier :"com.apple.instruments.server.services.deviceinfo"] >
170.892238 x4   sent   [c0]: < DTXMessage 0x100d61830 : i3.1 c0 >
170.892973 x4 received [c1f]: < DTXMessage 0x100d0a550 : i4.0e c1 dispatch:[runningProcesses] >
171.204957 x4   sent   [c1f]: < DTXMessage 0x100c557a0 : i4.1 c1 object:(__NSArrayM*)<NSArray 0x100c199d0 | 245 objects> { <NSDictionary 0x100c167c0 | 5 key/value pairs>, <NSDictionary 0x100d17970 | 5 key/value pairs>, <NSDictionary 0x100d17f40 | 5 key/value pairs>, <NSDictionary 0x100d61750 | 5 key/value pairs>, <NSDictionary 0x100c16760 | 5 key/value pairs>, ...  } >
171.213326 x4 received [c0]: < DTXMessage : kDTXInterruptionMessage >
171.213424 x4  handler [c0]: < DTXMessage : i1 kDTXInterruptionMessage >
171.213477 x4 received [c1f]: < DTXMessage : kDTXInterruptionMessage >

For editing the configuration we can simply add the respected key into: /var/mobile/Library/Preferences/.GlobalPreferences.plist and kill cfprefsd

The valid selectors for triggering can be found using the following Frida script the same way Troy Bowman used for iterating all classes which implement the protocol DTXAllowedRPC:

frida -U DTServiceHub
for (var name in ObjC.protocols) {
    var protocol = ObjC.protocols[name]
    if ('DTXAllowedRPC' in protocol.protocols) {
        console.log('@protocol', name)
        console.log('  ' + Object.keys(protocol.methods).join('\n  '))
    }
}

The complete list for the relevant APIs can be found here:

com.apple.os_trace_relay

Provides API for the following operations:

  • Show process list (process name and pid)
  • Stream syslog lines in binary form with optional filtering by pid.
  • Get old stored syslog archive in PAX format (can be extracted using pax -r < filename).
    • Archive contain the contents are the /var/db/diagnostics directory

com.apple.mobile.diagnostics_relay

Provides an API to:

  • Query MobileGestalt & IORegistry keys.
  • Reboot, shutdown or put the device in sleep mode.

com.apple.mobile.file_relay

On older iOS versions, this was the main relay used for file operations, which was later replaced with AFC.

com.apple.pcapd

Starting iOS 5, apple added a remote virtual interface (RVI) facility that allows mirroring networks trafic from an iOS device. On Mac OSX the virtual interface can be enabled with the rvictl command. This script allows to use this service on other systems.

The bits and bytes

To understand the bits and bytes of the communication with lockdownd you are advised to take a look at this article:

https://jon-gabilondo-angulo-7635.medium.com/understanding-usbmux-and-the-ios-lockdown-service-7f2a1dfd07ae

Sending your own messages

Lockdown messages

Every such subcommand may wrap several relay requests underneath. If you wish to try and play with some the relays yourself, you can run:

pymobiledevice3 lockdown service <service-name>

This will start an IPython shell where you already have the connection established using the client variable and you can send & receive messages.

# This shell allows you to communicate directly with every service layer behind the lockdownd daemon.

# For example, you can do the following:
client.send_plist({"Command": "DoSomething"})

# and view the reply
print(client.recv_plist())

# or just send raw message
client.sendall(b"hello")

# and view the result
print(client.recvall(20))

Instruments messages

If you want to play with DTServiceHub which lies behind the developer options, you can also use:

pymobiledevice3 developer shell

To also get an IPython shell, which lets you call ObjC methods from the exported objects in the instruments' namespace like so:

# This shell allows you to send messages to the DVTSecureSocketProxy and receive answers easily.
# Generally speaking, each channel represents a group of actions.
# Calling actions is done using a selector and auxiliary (parameters).
# Receiving answers is done by getting a return value and seldom auxiliary (private / extra parameters).
# To see the available channels, type the following:
developer.supported_identifiers

# In order to send messages, you need to create a channel:
channel = developer.make_channel('com.apple.instruments.server.services.deviceinfo')

# After creating the channel you can call allowed selectors:
channel.runningProcesses()

# If an answer is expected, you can receive it using the receive method:
processes = channel.receive_plist()

# Sometimes the selector requires parameters, You can add them using MessageAux. For example lets kill a process:
channel = developer.make_channel('com.apple.instruments.server.services.processcontrol')
args = MessageAux().append_obj(80)  # This will kill pid 80
channel.killPid_(args, expects_reply=False)  # Killing a process doesn't require an answer.

# In some rare cases, you might want to receive the auxiliary and the selector return value.
# For that cases you can use the recv_plist method.
return_value, auxiliary = developer.recv_plist()

Contributing

See CONTRIBUTING.

Rate & Review

Great Documentation0
Easy to Use0
Performant0
Highly Customizable0
Bleeding Edge0
Responsive Maintainers0
Poor Documentation0
Hard to Use0
Slow0
Buggy0
Abandoned0
Unwelcoming Community0
100