diff --git a/ground-segment/talk-to-me-goose/README.md b/ground-segment/talk-to-me-goose/README.md new file mode 100644 index 0000000..1f37f38 --- /dev/null +++ b/ground-segment/talk-to-me-goose/README.md @@ -0,0 +1,97 @@ +# Talk to me, Goose + +**Category**: Ground Segment +**Points (final)**: 94 points +**Solves**: 42 + +> LaunchDotCom has a new satellite, the Carnac 2.0. What can you do with it from its design doc? + +**Given files**: `cmd_telemetry_defs.zip`, `LaunchDotCom_Carnac_2.zip` + +## Write-up +by [erin (`barzamin`)](https://imer.in). + +Inside `LaunchDotCom_Carnac_2.zip` is a documentation PDF describing the "satellite" we're connecting to. One of the interesting things it notes is that "LaunchDotCom recommends Ball Aerospace’s COSMOS suite of software for command and telemetry processing with the Carnac 2.0."; we already set this up for the _That's not on my calendar_ challenge (written up by `haskal` in this report). + +We're given an XTCE file inside `cmd_telemetry_defs.zip`, `cmd_telemetry_defs.xtce`, which describes the command/telemetry protocol to the satellite. COSMOS can [load an XTCE definition](https://cosmosrb.com/docs/xtce/) into a COSMOS configuration, so we just generated a new COSMOS configuration tree and imported `cmd_telemetry_defs.xtce`. Out of the box, this won't identify packets properly for some reason; we had to add a file `$COSMOS_CONFIG_DIR/config/targets/CHALLENGE1/target.txt` containing +``` +TLM_UNIQUE_ID_MODE +``` +to make COSMOS fall back to a non-hash-based packet ID mode for the imported XTCE `CHALLENGE` target to work. + +We also had to write an [interface config](https://cosmosrb.com/docs/interfaces/) for COSMOS in `$COSMOS_CONFIG_DIR/config/tools/cmd_tlm_server/cmd_tlm_server.txt` so it could connect to the TCP-tunneled-CCSDS telemetry port the challenge gives us after a ticket; ours was of the form +``` +TITLE 'COSMOS Command and Telemetry Server' +# 10 nil: read, write timeouts +# length: protocol frame decoder +# 32: bit offset in packet to length field +# 16: size of length bitfield +# 7: length value offset (true # bytes read is length + this) +# 1: 1 byte per count in length field +# BIG_ENDIAN: endianness *of length field* +INTERFACE LOCAL_CFS_INT tcpip_client_interface.rb {ip} {port} {port} 10 nil LENGTH 32 16 7 1 BIG_ENDIAN + TARGET CHALLENGE1 + TARGET SYSTEM +``` + +and was generated by a script which connected to the challenge, passed the token, and templated/wrote out this interface config file. We ran COSMOS in the Docker container detailed in _That's not on my calendar_. + +Connect with COSMOS: [hacker voice im in] + +![COSMOS CMD/TLM server connected](goose-im-in.png) + +All the packets we're getting are `EPS PACKET`s indicating undervoltage: + +![COSMOS showing that the goose is hungry](goose-hongy.png) + +According to the manual PDF, the EPS shuts off "non-essential subsystems" in this state (which probably includes the subsystem that should be sending us flag packets). Immediately after starting a connection, though, we can send a `LOW_PWR_THRESH` command with a `LW_PWR_THRES` of 5V to put the low-power threshold below the battery voltage so the EPS thinks it's no longer running out of power: + +![COSMOS displaying command sender for LOW_PWR_THRESH](goose-low-pwr-thresh.png) + +And then all we have to do is send an `ENABLEPAYLOAD` command: + +![COSMOS displaying command sender for ENABLEPAYLOAD`](goose-enablepayload.png) + +The goose is now happy and `FLAG_PWR` is on! +![COSMOS showing a happy goose](goose-happy.png) + +The flag will come back whenever the flag task's scheduler fires, in a FLAG_PACKET: + +![COSMOS showing we have a FLAG_PACKET](cosmos-havemail.png) + +Instead of decoding the packet into fields in COSMOS (that won't show us an ASCII string, just FLAG1, FLAG2, etc integer fields in a list), I copy-pasted the flag packet from COSMOS's hexdump +![COSMOS displaying FLAG_PACKET](cosmos-hexdump.png) + +And threw together a quick script to decode by inspection of the XTCE file's defintion of the flag layout (basically identical to _Can you hear me now?_): +```{.python} +from bitstring import Bits, BitArray, ConstBitStream + +# b = BitArray(open('./data', 'rb')) +b = ConstBitStream('THE_HEX_HERE') +packetlocs = list(b.findall('0x0066')) +print(f"found packets: {packetlocs}") + +for loc in packetlocs: + b.pos = loc + ver = b.read(3).uint + ty = b.read(1).bin + sec_hd = b.read(1).bin + apid = b.read(11).uint + gp_flags = b.read(2).bin + ssc = b.read(14).uint + plength = b.read(16).uint + + print(ver, ty, sec_hd, hex(apid), gp_flags, ssc, f'len={plength} ({hex(plength)})') + + flag = [] + for i in range(120): + flag.append(chr(b.read(7).uint)) + print(''.join(flag)) +``` + +Flag achieved; another can-you-use-COSMOS challenge down. + +## Resources +- https://cosmosrb.com/docs/xtce/ +- https://cosmosrb.com/docs/interfaces/ +- https://cosmosrb.com/docs/protocols/ \ No newline at end of file diff --git a/ground-segment/talk-to-me-goose/cosmos-havemail.png b/ground-segment/talk-to-me-goose/cosmos-havemail.png new file mode 100644 index 0000000..78a4058 Binary files /dev/null and b/ground-segment/talk-to-me-goose/cosmos-havemail.png differ diff --git a/ground-segment/talk-to-me-goose/cosmos-hexdump.png b/ground-segment/talk-to-me-goose/cosmos-hexdump.png new file mode 100644 index 0000000..31fd54d Binary files /dev/null and b/ground-segment/talk-to-me-goose/cosmos-hexdump.png differ diff --git a/ground-segment/talk-to-me-goose/gen-cosmos-config.py b/ground-segment/talk-to-me-goose/gen-cosmos-config.py new file mode 100644 index 0000000..f138b19 --- /dev/null +++ b/ground-segment/talk-to-me-goose/gen-cosmos-config.py @@ -0,0 +1,22 @@ +from pwn import * +import time + +r = remote('goose.satellitesabove.me', 5033) +r.clean() +r.send('ticket{kilo720quebec:GP6PhNAXPXwLrMQ7cGlVqENRtYi3wK3dy6QggSJ_utEZ6ghqObtNpc1m5PSpJKEVvw}\n') +time.sleep(0.1) +r.readuntil('running at ') +[ip, port] = r.clean().decode().strip().split(':') +port = int(port) + +TEMPL=''' +TITLE 'COSMOS Command and Telemetry Server' +#COLLECT_METADATA +# wtout rtout prot off +INTERFACE LOCAL_CFS_INT tcpip_client_interface.rb {ip} {port} {port} 10 nil LENGTH 32 16 7 1 BIG_ENDIAN + TARGET CHALLENGE1 + TARGET SYSTEM +''' + +with open('cosmos/config/tools/cmd_tlm_server/cmd_tlm_server.txt', 'w') as f: + f.write(TEMPL.format(ip=ip, port=port)) diff --git a/ground-segment/talk-to-me-goose/goose-enablepayload.png b/ground-segment/talk-to-me-goose/goose-enablepayload.png new file mode 100644 index 0000000..f8abacf Binary files /dev/null and b/ground-segment/talk-to-me-goose/goose-enablepayload.png differ diff --git a/ground-segment/talk-to-me-goose/goose-happy.png b/ground-segment/talk-to-me-goose/goose-happy.png new file mode 100644 index 0000000..369198c Binary files /dev/null and b/ground-segment/talk-to-me-goose/goose-happy.png differ diff --git a/ground-segment/talk-to-me-goose/goose-hongy.png b/ground-segment/talk-to-me-goose/goose-hongy.png new file mode 100644 index 0000000..13323ca Binary files /dev/null and b/ground-segment/talk-to-me-goose/goose-hongy.png differ diff --git a/ground-segment/talk-to-me-goose/goose-im-in.png b/ground-segment/talk-to-me-goose/goose-im-in.png new file mode 100644 index 0000000..8fec72e Binary files /dev/null and b/ground-segment/talk-to-me-goose/goose-im-in.png differ diff --git a/ground-segment/talk-to-me-goose/goose-low-pwr-thresh.png b/ground-segment/talk-to-me-goose/goose-low-pwr-thresh.png new file mode 100644 index 0000000..5eaf9e4 Binary files /dev/null and b/ground-segment/talk-to-me-goose/goose-low-pwr-thresh.png differ