mirror of
https://github.com/blacktop/ipsw.git
synced 2026-06-07 12:27:36 +00:00
164 lines
3.7 KiB
Go
164 lines
3.7 KiB
Go
package pcap
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/binary"
|
|
"io"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/blacktop/go-plist"
|
|
"github.com/blacktop/ipsw/pkg/usb"
|
|
"github.com/blacktop/ipsw/pkg/usb/lockdownd"
|
|
)
|
|
|
|
const (
|
|
serviceName = "com.apple.pcapd"
|
|
TcpdumpMagic = 0xa1b2c3d4
|
|
VersionMajor = 2
|
|
VersionMinor = 4
|
|
LinkTypeEthernet = 1
|
|
LinkTypeRaw = 101
|
|
)
|
|
|
|
var ethernetHeader = []byte{0xbe, 0xfe, 0xbe, 0xfe, 0xbe, 0xfe, 0xbe, 0xfe, 0xbe, 0xfe, 0xbe, 0xfe, 0x08, 0x00}
|
|
|
|
type GlobalHeader struct {
|
|
MagicNumber uint32 // magic number
|
|
VersionMajor uint16 // major version number
|
|
VersionMinor uint16 // minor version number
|
|
Thiszone int32 // GMT to local correction
|
|
Sigfigs uint32 // accuracy of timestamps
|
|
Snaplen uint32 // max length of captured packets, in octets
|
|
Network uint32 // data link type
|
|
}
|
|
|
|
type PacketHeader struct {
|
|
TimestampSecs uint32 // timestamp seconds
|
|
TimestampMicroSecs uint32 // timestamp microseconds
|
|
InclLength uint32 // number of octets of packet saved in file
|
|
OrigLength uint32 // actual length of packet
|
|
}
|
|
|
|
type IOSPacketHeader struct {
|
|
HdrLength uint32
|
|
HdrVersion uint8
|
|
PktLength uint32
|
|
InterfaceType iface
|
|
Unit uint16
|
|
IO uint8
|
|
ProtocolFamily protocolFamily
|
|
FramePreLength uint32
|
|
FramePostLength uint32
|
|
InterfaceName [16]byte
|
|
Pid uint32 // little endian
|
|
ProcName [17]byte
|
|
Svc uint32 // little endian TODO: map this to name
|
|
SubPid uint32 // little endian
|
|
SubProcName [17]byte
|
|
Seconds uint32
|
|
MicroSeconds uint32
|
|
}
|
|
|
|
type Client struct {
|
|
c *usb.Client
|
|
}
|
|
|
|
func NewClient(udid string) (*Client, error) {
|
|
c, err := lockdownd.NewClientForService(serviceName, udid, false)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &Client{
|
|
c: c,
|
|
}, nil
|
|
}
|
|
|
|
// TODO: look at tools/idevicebtlogger.c for ideas on how to properly construct PCAP header (missing directionality)
|
|
func (c *Client) ReadPacket(ctx context.Context, procName string, wr io.Writer, dump func(IOSPacketHeader, []byte)) error {
|
|
|
|
header := GlobalHeader{
|
|
MagicNumber: TcpdumpMagic,
|
|
VersionMajor: VersionMajor,
|
|
VersionMinor: VersionMinor,
|
|
Thiszone: 0,
|
|
Sigfigs: 0,
|
|
Snaplen: uint32(65535),
|
|
Network: uint32(LinkTypeEthernet),
|
|
}
|
|
|
|
if err := binary.Write(wr, binary.LittleEndian, header); err != nil {
|
|
return err
|
|
}
|
|
|
|
stoped := false
|
|
go func() {
|
|
<-ctx.Done()
|
|
stoped = true
|
|
}()
|
|
|
|
for {
|
|
bs, err := c.c.RecvBytes()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var data []byte
|
|
_, err = plist.Unmarshal(bs, &data)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
buf := bytes.NewReader(data)
|
|
var hdr IOSPacketHeader
|
|
if err := binary.Read(buf, binary.BigEndian, &hdr); err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(procName) > 0 {
|
|
pName := strings.TrimSpace(string(hdr.ProcName[:]))
|
|
subName := strings.TrimSpace(string(hdr.SubProcName[:]))
|
|
if !strings.HasPrefix(pName, procName) && !strings.HasPrefix(subName, procName) {
|
|
continue
|
|
}
|
|
}
|
|
|
|
if dump != nil {
|
|
go dump(hdr, data)
|
|
}
|
|
|
|
pphdr := PacketHeader{
|
|
TimestampSecs: uint32(time.Now().Unix()),
|
|
TimestampMicroSecs: uint32(time.Now().UnixNano() / 1e6),
|
|
InclLength: hdr.PktLength,
|
|
OrigLength: hdr.PktLength,
|
|
}
|
|
if err := binary.Write(wr, binary.LittleEndian, pphdr); err != nil {
|
|
return err
|
|
}
|
|
|
|
if hdr.FramePreLength == 0 {
|
|
ext := ethernetHeader
|
|
body := append(ext, data[hdr.HdrLength:]...)
|
|
err = binary.Write(wr, binary.LittleEndian, body)
|
|
} else {
|
|
err = binary.Write(wr, binary.LittleEndian, data[hdr.HdrLength:])
|
|
}
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if stoped {
|
|
break
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c *Client) Close() error {
|
|
return c.c.Close()
|
|
}
|