2020 Hack-A-Sat DEFCON Space Security Challenge CTF Qualifiers 2020 - Part 2
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:
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)
- 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:
- The line endings for Modbus ASCII mode are 0A 0D, and we have no new lines, in either hex or ASCII, and,
- 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)
- We're starting to see a framing format, messages starting with ^ and ending in ., and we have messages starting with ^3A, ^3B and ^CA.
- "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"
- 3a 00 00 3f 00 00 00 ... messages mostly have unprintable characters.
- ca ... messages have loads of printable characters. Some are particularly interesting...
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!
Nice job, I didn't think about timing the injections.
ReplyDelete