For this challenge we are provided with an XML file telemetry.xtce
along with a server address and port, and the following challenge description:
LaunchDotCom's ground station is streaming telemetry data from its Carnac 1.0 satellite on a TCP port. Implement a decoder from the XTCE definition.
This telemetry schema file describes the binary layout of the sattelite's telemetry data, as specified by the XTCE spec https://www.omg.org/xtce/index.htm. In hindsight I would have just used Ball Aerospace COSMOS (https://cosmosrb.com/) which came up in a subsequent challenge, but for this intro level one you don't need any tools.
According to telemetry.xtce
the flag appears to be encoded as 7 bit integers.
<!-- Parameters used by Payload -->
<xtce:Parameter name="PAYLOAD_FLAG1" parameterTypeRef="4ByteInteger"/>
<xtce:Parameter name="PAYLOAD_FLAG2" parameterTypeRef="4ByteInteger"/>
<xtce:Parameter name="PAYLOAD_FLAG3" parameterTypeRef="4ByteInteger"/>
<xtce:Parameter name="PAYLOAD_DATA" parameterTypeRef="PayloadBlob"/>
<!-- Parameters used by FLAG Gen -->
<xtce:Parameter name="FLAG11" parameterTypeRef="7BitInteger"/>
<xtce:Parameter name="FLAG12" parameterTypeRef="7BitInteger"/>
<xtce:Parameter name="FLAG13" parameterTypeRef="7BitInteger"/>
<xtce:Parameter name="FLAG14" parameterTypeRef="7BitInteger"/>
Connecting to the provided port apparently causes the mock telemetry service to be started on another port:
$ nc hearmenow.satellitesabove.me 5032
Ticket please:
ticket{...}
Telemetry Service running at 18.219.199.203:11335
Dumping the output of netcatting the telemetry service resulted in the following binary blob:
blob
Since the schema appears to imply that the flag is encoded as a string of 7 bit integers, it was simple enough to convert it into a binary string and search for the 7-bit encoded prefix of flag{
. The telemetry schema seems to suggest that the flag can be 120 characters long so the following python code is able to decode the flag by finding the encoded flag{
value and decoding it along with the 115 characters that follow it:
import re
def bits(x) :
return bin(x)[2:].zfill(8)
def bits7(x) :
return bin(ord(x))[2:].zfill(7)
binary = bin(int(blob, 16))
prefix = bits7('f') + bits7('l') + bits7('a') + bits7('g') + bits7('{')
flag7bit = re.match('.*('+prefix+'(?:(?:[01]){7}){115})',binary).group(1)
decoded = ''
for i in range(0, len(flag7bit)//7) :
start = 7*i
end = 7*i + 7
decoded += chr(int(flag7bit[start:end], 2))
print(decoded)