Hack a Sat — Talk to me, Goose

[ Also available https://lucasteske.dev/2020/05/hack-a-sat-talk-to-me-goose/ ]

This challenge is just after the “Can you hear me now?” challenge (see https://medium.com/@lucasteske/hack-a-sat-can-you-hear-me-now-c6f68ed6086b ). Now LaunchDotCom has a new Satellite called Carnac 2.0.

There are two attached files. The first one is the manual of the satellite in which we can see the onboard equipment:

There is also a XTCE file in which the Telemetry Data looks the same as previous challenge, but now there is a Command Section which implies that we will need to send commands back to the satellite. If we connect to the telemetry server and run the bonus script form the previous challenge, we will see that is only transmitting EPS

Also you can see that most of the equipments are off. The one that interest us is the FLAG_ENABLE which enables the FLAG Generator equipment to output our flag.

So I went directly to the XTCE to find a Enable Flag command that would toggle that. I found this section:

The logic is the same as applied for the previous flag, but now instead is for encoding a command and sending back to the satellite. We can assume we can send data back using the same connection we opened to the telemetry server. So I first created a encoder for the header:

Then the missing data would be 3 bytes:

  • CMD => Which tells the command to execute
  • PARAM => The command parameter
  • PowerState => To enable the power

Since we would need to send data back, I decided to use the pwntools library ( see http://docs.pwntools.com/en/stable/ ) and make a realtime decoder for the telemetry.

If you see the code, I also implemented it to find which telemetry server to connect. So it basically connects to the main server, presents the ticket, gets the address of the telemetery server and then operates the telemetry server. I also let the EPS and FLAG decoder enabled on this one.

Then I made a function called SendEnables which would send data back to the satellite trying to enable the flag.

The first two bytes are the restriction imposed by the EnableFLAG command according to XTCE. The third byte represents the PowerState in which value 1 is for POWER ON state.

Sadly, that didn’t worked. The satellite seemed to be ignoring the command since the BAD_CMD_COUNT field wasn’t increasing. Then I started playing with other enables. I noticed that the voltage value was increasing every time I received a EPS packet. According to the doc this value is a two byte encoded float in some weird way.

I tried for a few hours to understand what that that meant. I couldn’t figure out so I just decoded as a uint16. I couldn’t figure out to calculate so I just assumed its a normal uint16 that would have direct correlation to voltage itself.

So I imagine that it was some sort of voltage related issue since when the voltage value reached the same value as LOW_POWER_THRESH the connection went off. So I decided to encode the command to send the LOW_POWER_THRESH change values.

Since that would have PLENGTH =3, I did another function to create the header (yes, I was lazy).

And since I had no clue how to encode that, I send some random values (like 65535, 0, 32768). All of them were incrementing the BAD_CMD_COUNT which probably mean that I was not encoding valid values. So I decided a bruteforce approach to find out which values were valid.

Since it was slow, I decided to send 100 commands each time send enable was calculated.

I was only expecting it to not increment the BAD_CMD_COUNT sometime, so I could find out the range of valid values. But after it reached 1200

The flag poped out!


There was a very big moment of laugh in my team because of that (we were in discord and everyone was seeing my screen in that moment). That must not be a safe way to control a satellite :P

Full Script



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store