# Bytes Away! **Category:** Satellite Bus **Points (final):** 223 **Solves:** 11 >We have an encrypted telemetry link from one of our satellites but we seem to have lost the >encryption key. Thankfully we can still send unencrypted commands using our Cosmos interface >(included). I've also included the last version of kit_to.so that was updated to the satellite. Can >you help us restore communication with the satellite so we can see what error "flag" is being >transmitted? ## Write-up by [haskal](https://awoo.systems) Two files are provided for this challenge, one contains the `kit_to.so` and the other contains a full [COSMOS](https://cosmosrb.com/) directory tree for accessing the virtual satellite, which can be booted up with the provided netcat endpoint. COSMOS is an open-source command and control framework for satellites using [NASA's Core Flight System](https://cfs.gsfc.nasa.gov/). The provided COSMOS directory contains everything we need to interact with the virtual satellite, and the `kit_to.so` is part of the code that runs onboard the actual satellite. Booting up COSMOS is enormously complicated, so Docker can be used to automate the setup. We adapted the Ball Aerospace COSMOS Docker image, and created a script to configure COSMOS to connect to the CTF's satellite instance automatically by writing the configuration file at `cosmos/config/tools/cmd_tlm_server/cmd_tlm_server.txt`. When COSMOS is successfully connected to the CTF instance it looks like this (no themes were installed in the Docker container so it looks like Windows 95, I'm so sorry,) ![COSMOS main window](COSMOS.png) COSMOS can be used to send commands with the Command Sender, and we can send for example a command for ENABLE_TELEMETRY, which causes the satellite to start sending telemetry. However these are encrypted, so COSMOS cannot understand them. ![COSMOS command sender for ENABLE_TELEMETRY](COSMOS_enable_telemetry.png) We also discover another present subsystem called `MM`, which allows for reading and writing arbitrary memory on the satellite (how useful!) as well as interacting with memory by symbols (extremely useful!). ![COSMOS command sender with MM PEEK_MEM command](COSMOS_MM.png) The provided `kit_to.so` contains the code used by the satellite to transmit telemetry to COSMOS. We used [Ghidra](https://ghidra-sre.org/) to analyze the binary (which helpfully includes symbols and debugging information, and that makes our lives way easier for this problem). We discovered that it uses AES CBC with a key and IV retrieved with external functions `get_key` and `get_iv` that are not present in the binary. However, these are stored in known locations in memory, which means it would be possible to read the AES key and IV using the PEEK_MEM command in COSMOS and then decrypt the telemetry packets, but there's an easier way. The code contains a function `KIT_TO_SendFlagPkt` which (as you might guess) sends the flag via encrypted telemetry, and this also writes the flag as an intermediate value to a known memory location. PIE is enabled for this binary, however since the PEEK_MEM command allows looking up memory by symbol name the address randomization is very trivially bypassed. ![KIT_TO_SendFlagPkt in Ghidra showing the global flag location](ghidra.png) Inspecting the structure of `KitToFlagPkt` shows that the flag is located at offset 12 and is (up to) 200 bytes long. We created a Ruby script in the COSMOS Script Runner to execute PEEK_MEM commands for each byte in the flag range, based on the command COSMOS outputs to the console when running the command manually in the GUI. Note that in order for the function `KIT_TO_SendFlagPkt` to be called at all, we must first run the ENABLE_TELEMETRY command even though we're not going to look at any actual telemetry. ```ruby 12.upto(212) { |off| offset = off cmd("MM PEEK_MEM with CCSDS_STREAMID 6280, CCSDS_SEQUENCE 49152, CCSDS_LENGTH 73, " + "CCSDS_FUNCCODE 2, CCSDS_CHECKSUM 0, DATA_SIZE 8, MEM_TYPE 1, PAD_16 0, " + "ADDR_OFFSET #{offset}, ADDR_SYMBOL_NAME 'KitToFlagPkt'") } ``` This directly prints the flag to the console, simply decode the hex to get the flag value. ## Resources and other writeups * * *