From a63a569a547d5fde17635d01687175ec99ee17a7 Mon Sep 17 00:00:00 2001 From: Erin Moon Date: Mon, 1 Jun 2020 00:04:44 -0500 Subject: [PATCH] spacebook: original code --- aaaa/spacebook/README.md | 63 ++++++++++------------------ aaaa/spacebook/spacebook-original.py | 54 ++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 41 deletions(-) create mode 100644 aaaa/spacebook/spacebook-original.py diff --git a/aaaa/spacebook/README.md b/aaaa/spacebook/README.md index 3357411..8f40ce7 100644 --- a/aaaa/spacebook/README.md +++ b/aaaa/spacebook/README.md @@ -19,63 +19,44 @@ We're given a boresight vector $\vec{v}\in\mathbb{R}^3$ for each star, and a mag ![Distribution of star magnitudes for catalog and unknown sets](spacebook-magnitude-distribution.png) -*Note that code from here on in this report is reconstructed, since I accidentally overwrote the original copy. I took the chance to use scipy for Kabsch this time instead of the original package I used, [`rmsd`](https://github.com/charnley/rmsd).* - My immediate suspicion was that we could take the outliers (simply by thresholding for stars with $m>500$) and, for each, directly match it to the catalog by finding the star with closest magnitude in the catalog: ```{.python} -def match_brightest_stars(unknown, catalog): - brightest = [] - catalog_matches = [] - for star in unknown: - if star['m'] < 500: - continue +refstars_magsorted = sorted(refstars, key=lambda x:x['m'])[::-1] - # 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]) +catalog_magnitudes = np.array([x['m'] for x in catalog]) +matches = [] - return brightest, catalog_matches +for idx, star in enumerate(refstars_magsorted): + if star['m'] <= 500: + break + match = np.argmin(np.abs(catalog_magnitudes-star['m'])) + matches.append(match) ``` We can then align those brightest stars to their closest magnitude matches using the Kabsch algorithm: ```{.python} -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 +P = np.vstack([x['v'] for x in [catalog[i] for i in matches]]) +Q = np.vstack([x['v'] for x in refstars_magsorted[:4]]) +print("rmsd: {}".format(calculate_rmsd.kabsch_rmsd(P,Q))) +rotation_mtx = calculate_rmsd.kabsch(P, Q) +rotation = Rotation.from_matrix(rotation_mtx) ``` -Then for each unknown star with vector $\vec{v}$, we can find its catalog index by evaluating +Knowing the rotation, we can rotate all stars into the catalog reference frame and then evaluate $$\arg\min_{\vec{u}\in\text{catalog}} \norm{\vec{u}-\vec{v}}_2$$ -for every challenge: +for each unknown star with vector $\vec{v}$ to find the closest star in the dictionary: ```{.python} -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()) +rotated = [dict(v=rotation.apply(x['v']), m=x['m']) for x in refstars_magsorted] +found_idxes = [] +for star in rotated: + found_idxes.append(np.argmin([np.linalg.norm(star['v']-catalogstar['v']) for catalogstar in catalog])) ``` +It's then trivial to send `found_idxs` back to the challenge as a comma-separated string of indices for each problem sent to us; the server happily sends us the flag after we answer its questions. + ### Full code -```{.python include=spacebook.py} +```{.python include=spacebook-original.py} ``` ## Resources diff --git a/aaaa/spacebook/spacebook-original.py b/aaaa/spacebook/spacebook-original.py new file mode 100644 index 0000000..4e55107 --- /dev/null +++ b/aaaa/spacebook/spacebook-original.py @@ -0,0 +1,54 @@ +import numpy as np +from pwnlib import tubes +import time +import matplotlib.pyplot as plt +from rmsd import calculate_rmsd +from scipy.spatial.transform import Rotation +%matplotlib inline + +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()) + +TICKET = 'THE_TICKET' +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): + refstars = read_starfile(r.recvuntil('\n\n').decode()) + + refstars_magsorted = sorted(refstars, key=lambda x:x['m'])[::-1] + + catalog_magnitudes = np.array([x['m'] for x in catalog]) + matches = [] + + for idx, star in enumerate(refstars_magsorted): + if star['m'] <= 500: + break + match = np.argmin(np.abs(catalog_magnitudes-star['m'])) + matches.append(match) + print(matches) + + P = np.vstack([x['v'] for x in [catalog[i] for i in matches]]) + Q = np.vstack([x['v'] for x in refstars_magsorted[:4]]) + print("rmsd: {}".format(calculate_rmsd.kabsch_rmsd(P,Q))) + rotation_mtx = calculate_rmsd.kabsch(P, Q) + rotation = Rotation.from_matrix(rotation_mtx) + + rotated = [dict(v=rotation.apply(x['v']), m=x['m']) for x in refstars_magsorted] + found_idxes = [] + for star in rotated: + found_idxes.append(np.argmin([np.linalg.norm(star['v']-catalogstar['v']) for catalogstar in catalog])) + + r.send(','.join([str(x) for x in found_idxes]) + '\n') + time.sleep(0.1) + r.recvuntil('Left...\n') +print(r.clean()) \ No newline at end of file