Home > front end >  Perl: Reproducing a UDP packet
Perl: Reproducing a UDP packet

Time:11-09

I'm trying to emulate the UDP output of a particular piece of software (a very simple remote control for an audio player). Capturing its output with tcpdump -X was no problem, and resulted in packets like the ones below:

Turn the device off...

18:30:03.623499 IP x.x.x.1.27490 > x.x.x.2.23500: UDP, length 32
    0x0000:  4500 003c 42e6 0000 8011 92ee 0a02 2810  E..<B.........(.
    0x0010:  0a02 28c9 6b62 5bcc 0028 b213 0500 007f  ..(.kb[..(......
    0x0020:  0100 0000 1800 0000 0000 0000 0000 0000  ................
    0x0030:  0000 0000 0100 0000 0200 0000            ............

Turn the device on...

18:30:06.222808 IP x.x.x.1.27490 > x.x.x.2.23500: UDP, length 32
    0x0000:  4500 003c 42e7 0000 8011 92ed 0a02 2810  E..<B.........(.
    0x0010:  0a02 28c9 6b62 5bcc 0028 b213 0500 007f  ..(.kb[..(......
    0x0020:  0100 0000 1800 0000 0000 0000 0000 0000  ................
    0x0030:  0000 0000 0200 0000 0100 0000            ............

Now I'm trying to reproduce these packets in Perl, so I can send them via IO::Socket::INET and have them arrive looking the same as the above.

I've been fooling around with the Perl pack function, but I'm afraid my understanding of what I'm looking at is insufficient to craft a working template.

Am I even on the right track here?

CodePudding user response:

IP packet structure UDP packet structure

The first byte tells gives us important information.

45
  • Version: 4 (IPv4)
  • IHL: 5 (IP header is 20 bytes long, including this byte.)

Now we know how long the header is.

   00 00 3c  42 e6 00 00  80 11 92 ee  0a 02 28 10
0a 02 28 c9
  • DSCP: 0
  • ECN: 0
  • Total length: 0x003c (60)
  • Identification: 0x42e6
  • Flags: 0
  • Fragment offset: 0
  • TTL: 0x80 (128)
  • Protocol: 0x11 (UDP)
  • Header checksum: 0x92ee
  • Source IP: 0x0a022810 (10.2.40.16)
  • Destination IP: 0x0a0228c9 (10.2.40.201)

It's an unfragmented packet, so it's the full packet.

The next 60 - 20 = 40 bytes is the IP packet payload.

It's a UDP packet, so the next 8 bytes form the UDP packet header.

6b 62 5b cc  00 28 b2 13
  • Source port: 0x6b62 (27490)
  • Destination port: 0x5bcc (23500)
  • Length (IP header excluded): 0x0028 (40)
  • Checksum: 0xb213

The next 40 - 8 = 32 bytes is the UDP packet payload.

05 00 00 7f  01 00 00 00  18 00 00 00  00 00 00 00
00 00 00 00  00 00 00 00  01 00 00 00  02 00 00 00

So you'd use a UDP socket bound to 10.2.40.16:27490 to send the following string to 10.2.40.201:23500:

"\x05\x00\x00\x7f"."\x01\x00\x00\x00"."\x18\x00\x00\x00"."\x00\x00\x00\x00".
"\x00\x00\x00\x00"."\x00\x00\x00\x00"."\x01\x00\x00\x00"."\x02\x00\x00\x00"

(Divided into four-byte strings for readability. How you build the string is irrelevant.)

There might be some differences in the headers, but you don't get full control over that anyway. The TTL field decreases as the the packet moves through the network. The packet can become fragmented (divided into smaller packets called fragments). etc. Besides, differences in the headers do no seem relevant here.

  • Related