10
2
Fork 0

bytes away

This commit is contained in:
xenia 2020-05-26 02:00:55 -04:00
parent 191df36fb8
commit e4dd59bc50
10 changed files with 164 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

View File

@ -0,0 +1,32 @@
FROM ubuntu:18.04
RUN apt-get update -y && apt-get install -y \
cmake \
freeglut3 \
freeglut3-dev \
gcc \
g++ \
git \
iproute2 \
libffi-dev \
libgdbm-dev \
libgdbm5 \
libgstreamer-plugins-base1.0-dev \
libgstreamer1.0-dev \
libncurses5-dev \
libreadline6-dev \
libsmokeqt4-dev \
libssl-dev \
libyaml-dev \
net-tools \
qt4-default \
qt4-dev-tools \
ruby2.5 \
ruby2.5-dev \
vim \
zlib1g-dev
RUN apt-get install -y bundler
WORKDIR /cosmos
CMD /bin/bash

View File

@ -0,0 +1,79 @@
# 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:
![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.
![KitToFlagPkt structure in Ghidra](ghidra_structure.png)
We created a Ruby script in the COSMOS Script Runner to execute PEEK_MEM commands for each byte in
the flag range:
```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
* <https://cosmosrb.com/>
* <https://cfs.gsfc.nasa.gov/>
* <https://ghidra-sre.org/>

View File

@ -0,0 +1,44 @@
from pwn import *
import time
r = remote('bytes.satellitesabove.me', 5042)
r.clean()
r.send('THE_TICKET')
time.sleep(0.1)
r.readuntil('tcp:')
[ip, port] = r.readuntil('\n').decode().strip().split(':')
port = int(port)
TEMPL='''
TITLE 'cFS Command and Telemetry Server'
# Can't map same target to two interfaces. Current strategy is to always connect locally
# and allow a switch to a PiSat interface. Another option may be to start both interfaces
# and then remap the targets.
INTERFACE LOCAL_CFS_INT tcpip_client_interface.rb {ip} {port} {port} 10 nil
PROTOCOL WRITE ChecksumProtocol
TARGET SYSTEM
TARGET CFE_ES
TARGET CFE_EVS
TARGET CFE_SB
TARGET CFE_TBL
TARGET CFE_TIME
TARGET MM
TARGET KIT_CI
TARGET KIT_SCH
TARGET KIT_TO
INTERFACE COSMOSINT cmd_tlm_server_interface.rb
TARGET COSMOS
DISABLE_DISCONNECT
'''
with open('cosmos/config/tools/cmd_tlm_server/cmd_tlm_server.txt', 'w') as f:
f.write(TEMPL.format(ip=ip, port=port))
r.interactive()

View File

@ -0,0 +1,6 @@
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'")
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View File

@ -0,0 +1,3 @@
#!/bin/bash
docker run -it -e DISPLAY -e QT_X11_NO_MITSHM=1 --net=host -v $PWD/cosmos:/cosmos cosmos2 bash