Hey everyone, I have been staying at a hotel for a while. It’s one of those modern ones with smart TVs and other connected goodies. I got curious and opened Wireshark, as any tinkerer would do.
I was very surprised to see a huge amount of UDP traffic on port 2046. I looked it up but the results were far from useful. This wasn’t a standard port, so I would have to figure it out manually.
At first, I suspected that the data might be a television stream for the TVs, but the packet length seemed too small, even for a single video frame.
This article is also available in French.
Grabbing the data
The UDP packets weren’t sent to my IP and I wasn’t doing ARP spoofing, so these packets were sent to everyone. Upon closer inspection, I found out that these were Multicast packets. This basically means that the packets are sent once and received by multiple devices simultaneously. Another thing I noticed was the fact that all of those packets were the same length (634 bytes).
I decided to write a Python script to save and analyze this data. First of all, here’s the code I used to receive Multicast packets. In the following code, 234.0.0.2 is the IP I got from Wireshark.
import socket
import struct
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('', 2046))
mreq = struct.pack("4sl", socket.inet_aton("234.0.0.2"), socket.INADDR_ANY)
s.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
while True:
data = s.recv(2048)
print(data)
On top of this, I also used binascii to convert this to hex in order make reading the bytes easier. After watching thousands of these packets scroll through the console, I noticed that the first ~15 bytes were the same. These bytes probably indicate the protocol and the packet/command ID but I only received the same one so I couldn’t investigate those.
Audio is so LAME
It also took me an embarrassingly long time to see the string LAME3.91UUUUUUU
at the end of the packets. I suspected this was MPEG compressed audio data, but saving one packet as test.mp3 failed to played with mplayer and the file utility only identified this as test.mp3: data
. There was obviously data in this packet and file should know when it sees MPEG Audio data, so I decided to write another Python script to save the packet data with offsets. This way it would save the file test1
skipping 1 byte from the packet, test2
skipping 2 bytes and so on. Here’s the code I used and the result.
data = s.recv(2048)
for i in range(25):
open("test{}".format(i), "wb+").write(data[i:])
After this, I ran file test*
and voilà! Now we know we have to skip 8 bytes to get to the MPEG Audio data.
$ file test*
test0: data
test1: UNIF v-16624417 format NES ROM image
test10: UNIF v-763093498 format NES ROM image
test11: UNIF v-1093499874 format NES ROM image
test12: data
test13: TTComp archive, binary, 4K dictionary
test14: data
test15: data
test16: UNIF v-1939734368 format NES ROM image
test17: UNIF v-1198759424 format NES ROM image
test18: UNIF v-256340894 format NES ROM image
test19: UNIF v-839862132 format NES ROM image
test2: UNIF v-67173804 format NES ROM image
test20: data
test21: data
test22: data
test23: DOS executable (COM, 0x8C-variant)
test24: COM executable for DOS
test3: UNIF v-1325662462 format NES ROM image
test4: data
test5: data
test6: data
test7: data
test8: MPEG ADTS, layer III, v1, 192 kbps, 44.1 kHz, JntStereo
test9: UNIF v-2078407168 format NES ROM image
while True:
data = s.recv(2048)
sys.stdout.buffer.write(data[8:])
Now all we need to do is continuously read packets, skip the first 8 bytes, write them to a file and it should play perfectly.
But what was this audio? Was this a sneakily placed bug that listened to me? Was it something related to the smart TVs in my room? Something related to the hotel systems? Only one way to find out.
$ python3 listen_2046.py > test.mp3
* wait a little to get a recording *
^C
$ mplayer test.mp3
MPlayer (C) 2000-2016 MPlayer Team
224 audio & 451 video codecs
Playing test.mp3.
libavformat version 57.25.100 (external)
Audio only file format detected.
=====
Starting playback...
A: 3.9 (03.8) of 13.0 (13.0) 0.7%
The Revelation/Disappointment
What the hell? I can’t believe I spent time for this. It’s just elevator music. It is played in the hotel corridors around the elevators. Oh well, at least I can listen to it from my room now.