Skip to content

Commit 029e238

Browse files
committed
debug proxy for tunnel interfaces
1 parent 72af7ea commit 029e238

File tree

13 files changed

+1525
-6
lines changed

13 files changed

+1525
-6
lines changed
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
package usbmuxd
2+
3+
import (
4+
"encoding/hex"
5+
"io"
6+
"path"
7+
8+
ios "github.com/danielpaulus/go-ios/ios"
9+
log "github.com/sirupsen/logrus"
10+
)
11+
12+
type serviceConfig struct {
13+
codec func(string, string, *log.Entry) decoder
14+
handshakeOnlySSL bool
15+
}
16+
17+
// serviceConfigurations stores info about which codec to use for which service by name.
18+
// In addition, DTX based services only execute a SSL Handshake
19+
// and then go back to sending unencrypted data right after the handshake.
20+
var serviceConfigurations = map[string]serviceConfig{
21+
"com.apple.instruments.remoteserver": {NewDtxDecoder, true},
22+
"com.apple.accessibility.axAuditDaemon.remoteserver": {NewDtxDecoder, true},
23+
"com.apple.testmanagerd.lockdown": {NewDtxDecoder, true},
24+
"com.apple.debugserver": {NewBinDumpOnly, true},
25+
"com.apple.instruments.remoteserver.DVTSecureSocketProxy": {NewDtxDecoder, false},
26+
"com.apple.testmanagerd.lockdown.secure": {NewDtxDecoder, false},
27+
"bindumper": {NewBinDumpOnly, false},
28+
}
29+
30+
func getServiceConfigForName(serviceName string) serviceConfig {
31+
if val, ok := serviceConfigurations[serviceName]; ok {
32+
return val
33+
}
34+
return serviceConfigurations["bindumper"]
35+
}
36+
37+
type BinaryForwardingProxy struct {
38+
deviceConn ios.DeviceConnectionInterface
39+
decoder decoder
40+
}
41+
42+
func (b BinaryForwardingProxy) Close() {
43+
b.deviceConn.Close()
44+
}
45+
46+
func (b BinaryForwardingProxy) Send(msg []byte) error {
47+
return b.deviceConn.Send(msg)
48+
}
49+
50+
func (b *BinaryForwardingProxy) ReadMessage() ([]byte, error) {
51+
r := b.deviceConn.Reader()
52+
buffer := make([]byte, 50000)
53+
n, err := r.Read(buffer)
54+
if err != nil {
55+
return buffer[0:n], err
56+
}
57+
return buffer[0:n], nil
58+
}
59+
60+
func handleConnectToService(connectRequest ios.UsbMuxMessage,
61+
decodedConnectRequest map[string]interface{},
62+
p *ProxyConnection,
63+
muxOnUnixSocket *ios.UsbMuxConnection,
64+
muxToDevice *ios.UsbMuxConnection,
65+
serviceInfo PhoneServiceInformation,
66+
) {
67+
err := muxToDevice.SendMuxMessage(connectRequest)
68+
if err != nil {
69+
panic("Failed sending muxmessage to device")
70+
}
71+
connectResponse, err := muxToDevice.ReadMessage()
72+
if err != nil {
73+
panic("Failed reading muxmessage to device")
74+
}
75+
err = muxOnUnixSocket.SendMuxMessage(connectResponse)
76+
if err != nil {
77+
panic("Failed sending muxmessage to device")
78+
}
79+
80+
serviceConfig := getServiceConfigForName(serviceInfo.ServiceName)
81+
binToDevice := BinaryForwardingProxy{muxToDevice.ReleaseDeviceConnection(), serviceConfig.codec(
82+
path.Join(p.info.ConnectionPath, "from-device.json"),
83+
path.Join(p.info.ConnectionPath, "from-device.bin"),
84+
p.log,
85+
)}
86+
binOnUnixSocket := BinaryForwardingProxy{muxOnUnixSocket.ReleaseDeviceConnection(), serviceConfig.codec(
87+
path.Join(p.info.ConnectionPath, "to-device.json"),
88+
path.Join(p.info.ConnectionPath, "to-device.bin"),
89+
p.log,
90+
)}
91+
92+
if serviceInfo.UseSSL {
93+
if serviceConfig.handshakeOnlySSL {
94+
err = binToDevice.deviceConn.EnableSessionSslHandshakeOnly(p.pairRecord)
95+
if err != nil {
96+
panic("Failed enabling ssl EnableSessionSslHandshakeOnly")
97+
}
98+
binOnUnixSocket.deviceConn.EnableSessionSslServerModeHandshakeOnly(p.pairRecord)
99+
} else {
100+
err = binToDevice.deviceConn.EnableSessionSsl(p.pairRecord)
101+
if err != nil {
102+
panic("Failed EnableSessionSsl")
103+
}
104+
binOnUnixSocket.deviceConn.EnableSessionSslServerMode(p.pairRecord)
105+
}
106+
}
107+
proxyBinDumpConnection(p, binOnUnixSocket, binToDevice)
108+
}
109+
110+
func proxyBinDumpConnection(p *ProxyConnection, binOnUnixSocket BinaryForwardingProxy, binToDevice BinaryForwardingProxy) {
111+
defer func() {
112+
log.Println("done") // Println executes normally even if there is a panic
113+
if x := recover(); x != nil {
114+
log.Printf("run time panic, moving back socket %v", x)
115+
err := MoveBack(ios.GetUsbmuxdSocket())
116+
if err != nil {
117+
log.WithFields(log.Fields{"error": err}).Error("Failed moving back socket")
118+
}
119+
panic(x)
120+
}
121+
}()
122+
go proxyBinFromDeviceToHost(p, binOnUnixSocket, binToDevice)
123+
for {
124+
bytes, err := binOnUnixSocket.ReadMessage()
125+
if err != nil {
126+
log.WithFields(log.Fields{"error": err}).Error("Failed readmessage bin unix sock")
127+
}
128+
binOnUnixSocket.decoder.decode(bytes)
129+
if err != nil && len(bytes) == 0 {
130+
binOnUnixSocket.Close()
131+
binToDevice.Close()
132+
if err == io.EOF {
133+
p.LogClosed()
134+
return
135+
}
136+
p.log.Errorf("Failed reading bytes %v", err)
137+
return
138+
}
139+
140+
err = binToDevice.Send(bytes)
141+
if err != nil {
142+
log.Errorf("failed binforward sending to device: %v", err)
143+
}
144+
}
145+
}
146+
147+
func proxyBinFromDeviceToHost(p *ProxyConnection, binOnUnixSocket BinaryForwardingProxy, binToDevice BinaryForwardingProxy) {
148+
defer func() {
149+
log.Println("done") // Println executes normally even if there is a panic
150+
if x := recover(); x != nil {
151+
log.Printf("run time panic, moving back socket %v", x)
152+
err := MoveBack(ios.ToUnixSocketPath(ios.GetUsbmuxdSocket()))
153+
if err != nil {
154+
log.WithFields(log.Fields{"error": err}).Error("Failed moving back socket")
155+
}
156+
panic(x)
157+
}
158+
}()
159+
for {
160+
bytes, err := binToDevice.ReadMessage()
161+
if err != nil {
162+
log.WithFields(log.Fields{"error": err}).Errorf("Failed binToDevice.ReadMessage b: %d", len(bytes))
163+
}
164+
binToDevice.decoder.decode(bytes)
165+
166+
if err != nil && len(bytes) == 0 {
167+
binOnUnixSocket.Close()
168+
binToDevice.Close()
169+
if err == io.EOF {
170+
p.LogClosed()
171+
return
172+
}
173+
p.log.Errorf("Failed reading bytes %v", err)
174+
return
175+
}
176+
p.log.WithFields(log.Fields{"direction": "device2host"}).Trace(hex.Dump(bytes))
177+
err = binOnUnixSocket.Send(bytes)
178+
if err != nil {
179+
log.Errorf("failed binforward sending to host: %v", err)
180+
}
181+
}
182+
}

0 commit comments

Comments
 (0)