2020 Hack-A-Sat DEFCON Space Security Challenge CTF Qualifiers 2020 - Part 2

The Magic Bus Challenge

This challenge involved analyzing a fairly simple bus protocol emerging from a modem looking thing upon connecting to the target port provided. From the challenge description:

There's a very busy bus we've tapped a port onto, surely there is some juicy information hidden in the device memory... somewhere…

Upon connecting netcat to the provided hostname and port, we're provided with a slowly scrolling stream of ASCII text. If you don't send anything, you end up with an output looking similar to this:

Scrolling in this sort of fashion:

A few observations:

  • On each connection, we consistently see it starting with a "^3a", and ending in a "+."
  • Other than +, ^ and ., we've purely got hex characters other than...
  • ... the NO CARRIER message at the end
  • +++ and NO CARRIER are session commands from the Hayes command set, usually used for modem control (commonly referred to as AT commands)
Some experimentation from these observations:
  • Sending +++ to try and switch into ASCII mode has little to no effect.
  • Sending ^3a+......+. appears to have some effect. We get an echo back, or we get slightly different responses back.

We tried to reason about what this protocol was, given we've been told we're connected to a bus, but so far, the +++ and NO CARRIER messages suggest it's some kind of AT interface. Sending AT commands, control characters etc did not appear to have an effect, so we ruled out fairly early that this was suppose to be a modem style interface.
Perhaps it's some kind of encapsulation for actual bytes on the bus? Stripping away the ^ and +., we've actually got something that resembles, at least in part, Modbus ASCII mode. We've got the lines beginning with 3A (ASCII for ':'), plus we now have a reasonable explanation for why we've got hex data in ASCII.
There are problems with this theory though:

  1. The line endings for Modbus ASCII mode are 0A 0D, and we have no new lines, in either hex or ASCII, and,
  2. Modbus ASCII doesn't encode the first colon as ASCII again and the stream isn't double-ascii encoded (there are plenty of non-printable characters after the first ASCII decode parse)
  3. We're starting to see a framing format, messages starting with ^ and ending in ., and we have messages starting with ^3A, ^3B and ^CA.
Discounting the idea that it's Modbus, we decoded it and had a go at de-framing it:
Some patterns here:
  • "3b 00 00 3e" precedes longer "3a 00 00 3e" messages
  • "ca ..." messages are always preceded with a "3a 00 00 3f 00 00 00", which are always preceded by a "3b 00 00 3f"
Further, upon ASCII decoding the messages, we find:
  • 3a 00 00 3f 00 00 00 ... messages mostly have unprintable characters.
  • ca ... messages have loads of printable characters. Some are particularly interesting...

Holy crap there's the flag?
Well Yes, But Actually No | Know Your Meme

Problem is, whilst there are a bunch of these snippets, even gluing them together, we're clearly missing data:


hexdump -C foo.bin | rg -A 5 ' ca '
00000040  e6 3f ca 01 be 78 75 34  4b 41 53 49 39 78 39 4b  |.?...xu4KASI9x9K|
00000050  49 54 6d 59 74 65 6e 64  73 7d 00 e2 85 b2 59 d6  |ITmYtends}....Y.|
00000060  2f 2d c9 d0 fb 92 d2 c4  59 aa 5b 20 42 c6 b5 61  |/-......Y.[ B..a|
00000070  3b 00 00 3e 3a 00 00 3e  00 00 00 0e f3 65 3c e9  |;..>:..>.....e<.|
00000080  1a 40 41 2f 28 a1 c0 71  8e 9f 40 b7 a3 40 c1 b0  |.@A/(..q..@..@..|
00000090  3b e7 3f 3a 00 00 3e 00  00 00 0e f3 65 3c e9 1a  |;.?:..>.....e<..|
--
000000d0  c1 80 24 ea 3f ca 00 0f  f7 eb 15 96 3d 6b 70 5c  |..$.?.......=kp\|
000000e0  c9 2c 5e d5 cf 5c 31 99  19 77 9a c6 a9 08 65 8d  |.,^..\1..w....e.|
000000f0  55 92 6a 37 2c 00 ff 23  eb 14 b9 29 7f 29 3b 00  |U.j7,..#...).);.|
00000100  00 3e 3a 00 00 3e 00 00  00 5e 24 ae bc 11 f8 3f  |.>:..>...^$....?|
00000110  41 c0 d4 a0 c0 72 fe 9e  40 7d 77 3f c1 50 66 eb  |A....r..@}w?.Pf.|
00000120  3f 3a 00 00 3e 00 00 00  5e 24 ae bc 11 f8 3f 41  |?:..>...^$....?A|
--
00000160  db e4 3f ca 00 0d 00 c8  f7 eb 15 96 3d 6b 70 5c  |..?.........=kp\|
00000170  c9 2c 5e d5 cf 5c 31 99  19 77 9a c6 a9 08 65 8d  |.,^..\1..w....e.|
00000180  55 92 6a 37 2c 00 ff 23  eb 14 b9 29 7f 29 85 48  |U.j7,..#...).).H|
00000190  56 e3 1d 25 3f 4f be 59  c6 4a 75 69 63 79 20 44  |V..%?O.Y.Juicy D|
000001a0  61 74 61 20 3b 00 00 3e  3a 00 00 3e 00 00 00 f6  |ata ;..>:..>....|
000001b0  0b 20 3d 1e 68 3f 41 be  f6 9f c0 21 6c a0 40 de  |. =.h?A....!l.@.|
--
00000200  40 11 3f 40 c1 71 8c e6  3f ca 00 0f f7 eb 15 96  |@.?@.q..?.......|
00000210  3d 6b 70 5c c9 2c 5e d5  cf 5c 31 99 19 77 9a c6  |=kp\.,^..\1..w..|
00000220  a9 08 65 8d 55 92 6a 37  2c 00 ff 23 eb 14 b9 29  |..e.U.j7,..#...)|
00000230  7f 29 85 48 56 e3 1d 25  3f 4f be 59 c6 4a 75 69  |.).HV..%?O.Y.Jui|
00000240  63 79 20 3b 00 00 3e 3a  00 00 3e 00 00 00 fe b5  |cy ;..>:..>.....|
00000250  e2 3b ce 55 40 41 24 d4  a0 c0 cb b3 a0 40 e1 51  |.;.U@A$......@.Q|
--
000002a0  5b ed 3f c1 33 3b e2 3f  ca 00 0d 00 c8 f7 eb 15  |[.?.3;.?........|
000002b0  96 3d 6b 70 5c c9 2c 5e  d5 cf 5c 31 99 19 77 9a  |.=kp\.,^..\1..w.|
000002c0  c6 a9 08 65 8d 55 92 6a  37 2c 00 ff 23 eb 14 b9  |...e.U.j7,..#...|
000002d0  29 7f 29 85 48 56 e3 1d  3b 00 00 3e 3a 00 00 3e  |).).HV..;..>:..>|
000002e0  00 00 00 1b e3 ca bc 07  43 40 41 43 54 a0 c0 78  |........C@ACT..x|
000002f0  28 a1 40 cf 5f 3f c1 92  83 e8 3f 3a 00 00 3e 00  |(.@._?....?:..>.|
00000300  00 00 1b e3 ca bc 07 43  40 41 43 54 a0 c0 78 28  |.......C@ACT..x(|
00000310  a1 40 cf 5f 3f c1 92 83  e8 3f 3b 00 00 3f 3a 00  |.@._?....?;..?:.|
00000320  00 3f 00 00 00 f7 c2 51  40 ab c4 3f 41 1e 2b 9f  |.?.....Q@..?A.+.|
00000330  c0 23 00 a1 40 a5 89 3f  c1 24 9d e7 3f ca 01 97  |.#..@..?.$..?...|
00000340  5f 49 39 71 2d 45 36 74  68 50 36 54 4d 39 72 5f  |_I9q-E6thP6TM9r_|
00000350  67 66 74 38 53 69 32 63  71 38 41 32 69 59 44 7a  |gft8Si2cq8A2iYDz|
00000360  64 4b 36 5f 34 5a 6a 78  75 34 4b 41 53 49 39 78  |dK6_4Zjxu4KASI9x|
00000370  39 4b 3b 00 00 3e 3a 00  00 3e 00 00 00 01 a3 40  |9K;..>:..>.....@|
00000380  3c ee 69 40 41 e2 22 a0  c0 69 d6 9e 40 27 9b 3f  |<.i@A."..i..@'.?|
--
000003d0  42 40 c1 8d 6a e8 3f ca  01 24 08 65 8d 55 92 6a  |B@..j.?..$.e.U.j|
000003e0  37 2c 00 ff 23 eb 14 b9  29 7f 29 85 48 56 e3 1d  |7,..#...).).HV..|
000003f0  25 3f 4f be 59 c6 4a 75  69 63 79 20 44 61 74 61  |%?O.Y.Juicy Data|
00000400  20 30 31 00 52 01 3b 00  00 3e 3a 00 00 3e 00 00  | 01.R.;..>:..>..|
00000410  00 3a 9c 0a 3d a4 bc 3f  41 96 56 a0 c0 ed f9 9f  |.:..=..?A.V.....|
00000420  40 da 63 40 c1 e5 88 e5  3f 3a 00 00 3e 00 00 00  |@.c@....?:..>...|
--
00000460  c7 9f 40 90 b3 3f c1 dd  ee e4 3f ca 01 60 9b 6b  |..@..?....?..`.k|
00000470  3a 1f 68 f0 35 ce 66 6c  61 67 7b 78 72 61 79 36  |:.h.5.flag{xray6|
00000480  35 30 31 30 78 72 61 79  3a 47 47 73 37 35 4a 6d  |5010xray:GGs75Jm|
00000490  76 4f 41 48 33 6e 30 37  6f 3b 00 00 3e 3a 00 00  |vOAH3n07o;..>:..|
000004a0  3e 00 00 00 d0 66 5f 3b  5c a0 40 41 36 b5 9f c0  |>....f_;\.@A6...|
000004b0  1a 2c a1 40 dc a3 3f c1  32 19 e7 3f 3a 00 00 3e  |.,.@..?.2..?:..>|
--
000004f0  a0 c0 56 81 a0 40 47 63  40 c1 9f 99 e5 3f ca 00  |..V..@Gc@....?..|
00000500  28 92 6a 37 2c 00 ff 23  eb 14 b9 29 7f 29 85 48  |(.j7,..#...).).H|
00000510  56 e3 1d 25 3f 4f be 59  c6 4a 75 69 63 79 20 44  |V..%?O.Y.Juicy D|
00000520  61 74 61 20 30 31 00 52  01 1e 7b 81 47 00 c9 9d  |ata 01.R..{.G...|
00000530  e3 e7 c2 23 36 81 3b 00  00 3e 3a 00 00 3e 00 00  |...#6.;..>:..>..|
00000540  00 05 59 88 bb 81 67 40  41 45 2e a0 c0 e9 94 9f  |..Y...g@AE......|
--
00000590  1c a0 40 7f 47 40 c1 3b  ad e7 3f ca 01 5b 36 81  |..@.G@.;..?..[6.|
000005a0  7c fc d9 9b 6b 3a 1f 68  f0 35 ce 66 6c 61 67 7b  ||...k:.h.5.flag{|
000005b0  78 72 61 79 36 35 30 31  30 78 72 61 79 3a 47 47  |xray65010xray:GG|
000005c0  73 3b 00 00 3e 3a 00 00  3e 00 00 00 b5 ff 03 bd  |s;..>:..>.......|
000005d0  3c 45 40 41 b6 2c a1 c0  88 7f a0 40 b7 c3 3f c1  |.......<|
--
00000620  3f c1 62 b3 e9 3f ca 00  07 61 74 61 20 30 30 00  |?.b..?...ata 00.|
00000630  c8 f7 eb 15 96 3d 6b 70  5c c9 2c 5e d5 cf 5c 31  |.....=kp\.,^..\1|
00000640  99 19 77 9a c6 a9 08 65  8d 55 92 6a 37 2c 3b 00  |..w....e.U.j7,;.|
00000650  00 3e 3a 00 00 3e 00 00  00 a1 0d 13 bd a7 f9 3f  |.>:..>.........?|
00000660  41 b1 15 a0 c0 37 d3 9f  40 bb 52 40 c1 43 9d e2  |A....7..@.R@.C..|
00000670  3f 3a 00 00 3e 00 00 00  a1 0d 13 bd a7 f9 3f 41  |?:..>.........?A|
--
000006b0  48 e2 3f ca 00 10 eb 15  96 3d 6b 70 5c c9 2c 5e  |H.?......=kp\.,^|
000006c0  d5 cf 5c 31 99 19 77 9a  c6 a9 08 65 8d 55 92 6a  |..\1..w....e.U.j|
000006d0  37 2c 00 ff 23 eb 14 b9  29 7f 29 85 48 56 e3 1d  |7,..#...).).HV..|
000006e0  25 3f 4f be 59 c6 4a 75  69 63 79 20 44 61 74 3b  |%?O.Y.Juicy Dat;|
000006f0  00 00 3e 3a 00 00 3e 00  00 00 9e c9 23 3d 97 69  |..>:..>.....#=.i|
00000700  3f 41 d7 4e 9f c0 07 ea  9f 40 97 69 40 c1 33 0e  |?A.N.....@.i@.3.|

Unfortunately, we're missing a segment of characters from our flag that looks fairly non-bruteforcable. The connection times out after a certain amount of data has been dumped out, and in none of our connections the full flag was dumped out. Going back to the previously identified patterns, we can try make some assumptions about them and trial injecting messages into the bus to get a response:

  • Given that 3b .. messages always preceded a 3a ... message, I reasoned that these are two nodes communicating, and 3b and 3a are network identifiers
  • That there is a difference between responses from 3a based on if 3b sent a 3f or 3e, that this field is a message ID of sorts

Based on the flow of Node 3B sending a 3F mesage to Node 3A, node 3A sending a message I couldn't parse, and node CA responding with the contents of memory, I figured the message flow sort of looked like this:
3b 00 00 3f <--- Request for memory contents
3a 00 00 3f 00 00 00 64 52 51 40 8d f7 3f 41 19 f3 9f c0 f9 aa 9f 40 27 6c 3f <--- 3A requesting CA for memory contents
ca 00 07 61 74 61 20 30 30 00 c8 f7 eb 15 96 3d 6b 70 5c c9 2c 5e d5 cf 5c 31 <--- CA responding

From here I tried repeating 3A's messages, but wasn't able to get CA to respond. Perhaps there's some form of authentication or message counters I was missing. That was fine, because sending a 3b 00 00 3f did result in 3A sending a request to CA for memory contents. There were some caveats to this though:

  • Transmitting when someone else was just resulted in your message being ignored or repeated back to you (some form of collision detection?)
  • \
  • Spamming the bus with 3b 00 00 3f messages wont work regardless. As mentioned, after a certain number of messages, you get disconnected and the flag changes per connection.
  • Even if you weren't thrown off the bus, I had no control over the memory location we were peaking at, and its contents seemed to change over time.

So the solution from here was just to play it cool and inject some 3b 00 00 3f messages at the right time, as to get the whole flag out of memory without being disconnected first. This took a couple of attempts, but we got there with this code:

from pwn import *
import time

def print_clean(msg_in):
msg_out = msg_in.decode().replace("^","").replace("+"," ").replace(".","")
if msg_out.startswith("3b 00 00 3e"):
print("master unknown diag request")
if msg_out.startswith("3b 00 00 3f"):
print("master peek memory request")
elif msg_out.startswith("3a 00 00 3"):
print("slave message", msg_out)
elif msg_out.startswith("ca"):
print("flag resp")
else:
print("unknown msg:", msg_out, "\n")

def enc(a):
msg = "^"
for i in a:
msg += hex(ord(i))[2:].zfill(2) + "+"
msg += "."
return msg

r = remote("bus.satellitesabove.me", 5041)
print(r.recvline())
r.sendline("ticket{redacted}")
buf = b""
last = None
c = 0
bingo = [1,5,11,50]
while c < 288:
next = r.recvuntil(".")
print_clean(next)
last = next.strip()
if c in bingo:
print("bingo, injecting at", c)
r.send("^3b+00+00+3f+.")
c+=1
if last.decode().startswith("^ca"):
temp = last.decode()[1:-1].replace("+", "")
print("ca flag rsp: ", bytearray.fromhex(temp)[3:])
buf += next
c += 1

log.close()
print("DONE")
r.interactive()

Note the bingo array just being the result of watching the responses and what was in memory at the time, and working out how far off it would be shifted. This resulted in us getting enough memory segments back to recover the flag.
Awesome network protocol analysis challenge!

Comments

  1. Nice job, I didn't think about timing the injections.

    ReplyDelete

Post a Comment

Popular posts from this blog

2020 Hack-A-Sat DEFCON Space Security Challenge CTF Qualifiers 2020 - Part 1

Man-in-the-middling SSL / TLS on Windows

2020 Hack-A-Sat DEFCON Space Security Challenge CTF Qualifiers 2020 - Part 3