diff --git a/README.md b/README.md index 572f303..0204ca9 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ - [aaaa/digital-filters-meh](aaaa/digital-filters-meh) - [aaaa/like-to-watch](aaaa/like-to-watch) - [aaaa/seeing-stars](aaaa/seeing-stars) +- [aaaa/spacebook](aaaa/spacebook) - [comms/56k](comms/56k) - [ground-segment/phasors-to-stun](ground-segment/phasors-to-stun) - [payload/leakycrypto](payload/leakycrypto) diff --git a/aaaa/spacebook/README.md b/aaaa/spacebook/README.md new file mode 100644 index 0000000..027216f --- /dev/null +++ b/aaaa/spacebook/README.md @@ -0,0 +1,16 @@ +# SpaceBook + +**Category**: Astronomy, Astrophysics, Astrometry, Astrodynamics, AAAA +**Points (final)**: 75 points +**Solves**: 56 + +> Hah, yeah we're going to do the hard part anyways! Glue all previous parts together by identifying these stars based on the provided catalog. Match the provided boresight refence vectors to the catalog refence vectors and tell us our attitude. +> +> Note: The catalog format is unit vector (X,Y,Z) in a celestial reference frame and the magnitude (relative brightness) + +**Given files**: spacebook-golf56788echo.tar.bz2 + +## Writeup +by [erin (`barzamin`)](https://imer.in). + +![Distribution of star magnitudes for catalog and unknown sets](magnitude-distribution.png) \ No newline at end of file diff --git a/aaaa/spacebook/magnitude-distribution.png b/aaaa/spacebook/magnitude-distribution.png new file mode 100644 index 0000000..71b4b04 Binary files /dev/null and b/aaaa/spacebook/magnitude-distribution.png differ diff --git a/aaaa/spacebook/spacebook.py b/aaaa/spacebook/spacebook.py new file mode 100644 index 0000000..7f257cf --- /dev/null +++ b/aaaa/spacebook/spacebook.py @@ -0,0 +1,62 @@ +import numpy as np +from pwnlib import tubes +import time +import matplotlib.pyplot as plt +from scipy.spatial.transform import Rotation +import seaborn as sb + +def read_starfile(data): + stars = [] + for line in data.strip().split('\n'): + [x,y,z,m] = [float(s.strip()) for s in line.split(',')] + stars.append({'v': np.array([x,y,z]), 'm':m}) + return stars + +with open('./spacebook-golf56788echo/test.txt') as f: + catalog = read_starfile(f.read()) + +def match_brightest_stars(unknown, catalog): + brightest = [] + catalog_matches = [] + for star in unknown: + if star['m'] < 500: + continue + + # find closest magnitude in catalog + match = np.argmin(np.abs(np.array([s['m'] for s in catalog]) - star['m'])) + print(f'[+] matched {star} to {catalog[match]}') + brightest.append(star) + catalog_matches.append(catalog[match]) + + return brightest, catalog_matches + +def orient(ref, catalog): + P = [s['v'] for s in catalog] + Q = [s['v'] for s in ref] + + rot, rmsd = Rotation.align_vectors(P, Q) + print(f'[+] aligned; rmsd = {rmsd}') + return rot + +TICKET = 'ticket{golf56788echo:GC_k-MZGAfTKMu0NDrCfBq2vYcpBpr5MuWKIFWJU3xOm2B_YAUF-EUiGswBD9NJ5Mw}' +r = tubes.remote.remote('spacebook.satellitesabove.me', 5015) +r.send(TICKET+'\n') +time.sleep(0.5) +r.recvuntil('Ticket please:\n', drop=True) + +for _ in range(5): + unknown_stars = read_starfile(r.recvuntil('\n\n').decode()) + + # find pairs + unknown_ref, catalog_ref = match_brightest_stars(unknown_stars, catalog) + # get attitude + attitude = orient(unknown_ref, catalog_ref) + # rotate each star to catalog-referenced coordinates and match by L2 norm + index_guesses = [] + for star in unknown_stars: + v = attitude.apply(star['v']) + index_guesses.append(np.argmin([np.linalg.norm(catalog_star['v'] - v) for catalog_star in catalog])) + + r.send(','.join(map(str, index_guesses))+'\n') + r.recvuntil('Left...\n') +print(r.clean())