xcdevice

package module
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 24, 2022 License: MIT Imports: 15 Imported by: 0

README

xcdevice

A library to communicate with services on iOS devices that does not require jailbreaking.

talking to devices

Xcode normally communicates with the iPhone using something called "usbmux" – this is a system for multiplexing several “connections” over one physical USB connection. Conceptually, it provides a TCP-like system – processes on the host machine open up connections to specific, numbered ports on the mobile device.

usbmuxd

Applications open a connection to the usbmuxd daemon when they want to talk to a device. usbmuxd maintains a list of iOS devices connected to the PC, and also manages the trust relationship between the iOS device and the PC.

graph LR

subgraph PC
    application --> usbmuxd
end

usbmuxd --> lockdown1["lockdownd"]
usbmuxd --> lockdown2["lockdownd"]


subgraph Device["iOS Device 1"]
    lockdown1 --> daemon1a["daemon A"]
    lockdown1 --> daemon1b["daemon B"]
end

subgraph Device2["iOS Device 2"]
    lockdown2 --> daemon2a["daemon A"]
    lockdown2 --> daemon2b["daemon B"]
end
lockdownd

When usbmuxd connects to a device, it sets up a connection to the lockdown service running on that device. From this point on, it is the lockdownd that responds to the messages sent over the connection.

debugging the connection

There is no official documentation available, so the best way to reverse engineer the messages is to observe an "official" application such as iTunes or Xcode.

The data sent over the connection is mostly plain text until a connection to lockdownd is established at which point it converts to a TLS enabled connection, but before that happens, the messages on the wire can be observed with the socat utility.

socat is a multipurpose relay tool for bidirectional data transfers between two independent channels. For example, unix pipes, devices, sockets, files, etc.

brew install socat

# rename the socket, so that it can be replaced by socat
sudo mv /var/run/usbmuxd /var/run/usbmuxx

# start the relay. add `-x` for byte debug
sudo socat -t100 -v UNIX-LISTEN:/var/run/usbmuxd,mode=777,reuseaddr,fork UNIX-CONNECT:/var/run/usbmuxx

# undo changes
sudo mv /var/run/usbmuxx /var/run/usbmuxd

developer disk images

Running an app requires a matching developer disk image to be mounted on the device. You can list available images like so:

ls -al /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/

contributing

You can contribute in many ways and not just by changing the code! If you have any ideas, just open an issue and tell me what you think.

Contributing code-wise - please discuss larger changes via an issue before submitting a pull request. Otherwise, fork the repository and submit a pull request!

license

MIT

Documentation

Index

Constants

View Source
const (
	AfcOperationStatus         = 0x00000001
	AfcOperationWriteFile      = 0x00000005
	AfcOperationMakeDir        = 0x00000009
	AfcOperationGetFileInfo    = 0x0000000A
	AfcOperationFileOpen       = 0x0000000D
	AfcOperationFileOpenResult = 0x0000000E
	AfcOperationFileWrite      = 0x00000010
	AfcOperationFileClose      = 0x00000014
)
View Source
const AfcMagic uint64 = 0x4141504c36414643
View Source
const (
	ConnectionTypeUSB = "USB"
)

Variables

View Source
var DefaultLookupAttributes = []string{
	"CFBundleDisplayName",
	"CFBundleExecutable",
	"CFBundleName",
	"CFBundleVersion",
	"CFBundleShortVersionString",
	"CFBundleIdentifier",
}
View Source
var (
	ErrObjectNotFound = errors.New("object not found")
)

Functions

func Install

func Install(device *Device, filepath string) error

func Lookup

func Lookup(device *Device, bundleID string, attributes []string) (map[string]interface{}, error)

func Uninstall

func Uninstall(device *Device, bundleID string) error

Types

type AFC

type AFC struct {
	// contains filtered or unexported fields
}

func (*AFC) CreateDirectory

func (a *AFC) CreateDirectory(name string) error

func (*AFC) Stat

func (a *AFC) Stat(filepath string) (map[string]interface{}, error)

func (*AFC) WriteFile

func (a *AFC) WriteFile(filename string, data []byte, mode AfcFileMode) error

type AfcFileMode

type AfcFileMode uint32
const (
	AfcFileModeRdOnly   AfcFileMode = 0x00000001
	AfcFileModeRw       AfcFileMode = 0x00000002
	AfcFileModeWrOnly   AfcFileMode = 0x00000003
	AfcFileModeWr       AfcFileMode = 0x00000004
	AfcFileModeAppend   AfcFileMode = 0x00000005
	AfcFileModeRdAppend AfcFileMode = 0x00000006
)

type ApplicationType

type ApplicationType string
const (
	ApplicationTypeAny      ApplicationType = "Any"
	ApplicationTypeSystem   ApplicationType = "System"
	ApplicationTypeUser     ApplicationType = "User"
	ApplicationTypeInternal ApplicationType = "Internal"
)

type Connection

type Connection struct {
	// contains filtered or unexported fields
}

func Open

func Open() (*Connection, error)

func (*Connection) Close

func (c *Connection) Close() error

func (*Connection) Hijack

func (c *Connection) Hijack() net.Conn

func (*Connection) Receive

func (c *Connection) Receive(v interface{}) error

func (*Connection) Send

func (c *Connection) Send(request interface{}) error

type Device

type Device struct {
	ConnectionSpeed int
	ConnectionType  string
	DeviceID        int
	LocationID      int
	ProductID       int
	SerialNumber    string
}

func ListDevices

func ListDevices() ([]Device, error)

type InstallationProxy

type InstallationProxy struct {
	// contains filtered or unexported fields
}

func (*InstallationProxy) InstallApplication

func (p *InstallationProxy) InstallApplication(bundleID, path string) error

func (*InstallationProxy) LookupApplication

func (p *InstallationProxy) LookupApplication(bundleID string, attributes []string) (map[string]interface{}, error)

func (*InstallationProxy) UninstallApplication

func (p *InstallationProxy) UninstallApplication(bundleID string) error

type Lockdown

type Lockdown struct {
	// contains filtered or unexported fields
}

Lockdown is used to start services on the device.

lockdownd uses a simple packet format where each packet is a 32-bit big-endian word indicating the size of the payload of the packet. The packets themselves are in XML plist format.

func LockdownService

func LockdownService(device *Device) (*Lockdown, error)

func (*Lockdown) AFCService

func (l *Lockdown) AFCService() (*AFC, error)

func (*Lockdown) Conn

func (l *Lockdown) Conn() net.Conn

func (*Lockdown) InstallationProxyService

func (l *Lockdown) InstallationProxyService() (*InstallationProxy, error)

type PairRecord

type PairRecord struct {
	HostID            string
	SystemBUID        string
	HostCertificate   []byte
	HostPrivateKey    []byte
	DeviceCertificate []byte
	EscrowBag         []byte
	WiFiMACAddress    string
	RootCertificate   []byte
	RootPrivateKey    []byte
}

func ReadPairRecord

func ReadPairRecord(device *Device) (*PairRecord, error)

type ReplyCode

type ReplyCode uint64
const (
	ReplyCodeOK ReplyCode = iota
	ReplyCodeBadCommand
	ReplyCodeBadDevice
	ReplyCodeConnectionRefused

	ReplyCodeBadVersion
)

func (ReplyCode) String

func (rc ReplyCode) String() string

type ServiceName

type ServiceName string
const (
	ServiceNameInstallationProxy ServiceName = "com.apple.mobile.installation_proxy"
	ServiceNameAFC               ServiceName = "com.apple.afc"
)

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL