10
2
Fork 0
has-writeup/aaaa/my-0x20
Erin Moon 71583185a7 linkify resources sections 2020-06-03 15:36:19 -05:00
..
README.md linkify resources sections 2020-06-03 15:36:19 -05:00
zoxtwenty.py writeup for 0x20 2020-05-27 22:00:15 -05:00

README.md

My 0x20

Category: Astronomy, Astrophysics, Astrometry, Astrodynamics, AAAA Points (final): 142 points Solves: 24

This social media app is back with a vengeance!

Given files: myspace-mike33686zulu.tar.bz2

Write-up

by erin (barzamin).

0x20 is SpaceBook, except without a backdoor. If you haven't read that writeup yet, go take a look at it.

That is, the trick in SpaceBook -- magnitudes are trivially matchable -- is gone. Additionally, we have less superbright outliers in the provided unknown star set. We can no longer match specific stars trivially. However, we can still solve the problem: this is what real star trackers have to do (although they have to deal with stuff like measurement and catalog error that don't show up here).

Since the observed (unknown) stars are all one simple rigid transformation (the observation orientation!) away from their positions in the catalog, relative distances and angles are preserved. Assuming that the local neighborhood of each star is represented relatively well in the observation set, we can look at the neighborhood of each star -- hopefully -- to determine what star it is.

Vaguely inspired by Pattern Recognition of Star Constellations for Spacecraft Applications, C. C. Liebe 1993 (thanks, google), I designed a simple star fingerprint: every star is represented by a 3-vector containing:

  • the distance to the closest neighbor
  • the distance to the second-closest neighbor
  • the angle between the two closest neighbors, relative to the star under consideration.

To make finding nearest neighbors fast, I used scikit-learn's ball tree implementation. I could then easily generate fingerprints for any given set of stars and its ball tree (warning: CTF-quality ML code from here on, sorry):

def angle(x, y):
    x_ = x/np.linalg.norm(x)
    y_ = y/np.linalg.norm(y)
    return np.arccos(np.clip(np.dot(x_, y_), -1.0, 1.0))

def gen_fingerprints(X, bt):
    dist, ind = bt.query(X[:], k=3)
    fingerprints = []
    for i in range(X.shape[0]):
        a = X[i,:]
        [bi, ci] = ind[i,1:]
        b = X[bi,:]
        c = X[ci,:]
        fingerprints.append([
            *dist[i, 1:],
            angle(b-a, c-a),
        ])
    return fingerprints

We could then fingerprint the star catalog:

with open('./myspace-mike33686zulu/test.txt') as f:
    catalog = read_starfile(f.read())

X = np.vstack([s['v'] for s in catalog])
bt_catalog = BallTree(X, leaf_size=30)

fingerprints = gen_fingerprints(X, bt_catalog)

You could do something probably more noise resistant, like finding N best-match fingerprints, doing Kabsch on those pairs, and then finding the rest by L2 norm similarity between boresight vectors after rotating to the catalog orientation. I just spat out the index of the closest catalog fingerprint match for each unknown star, throwing out fingerprint matches with error that was too high (L2 distance between fingerprints > $1\times10^{-4}$). Do that for every challenge, and you're done:

for _ in range(5):
    refstars = read_starfile(r.recvuntil('\n\n').decode())

    Y = np.vstack([s['v'] for s in refstars])
    bt_unknown = BallTree(Y, leaf_size=30)

    fingerprints_unknown = gen_fingerprints(Y, bt_unknown)

    matches = []
    for query in fingerprints_unknown:
        error = [np.linalg.norm(np.array(fp_known) - np.array(query))
                 for fp_known in fingerprints]
        match_idx = np.argmin(error)
        if error[match_idx] < 1e-4:
            print(match_idx, error[match_idx])
            matches.append(match_idx)

    r.send(','.join(map(str,matches)) + '\n')
    r.recvuntil('Left...\n')
print(r.clean())

Fun fact! We got second or third on this (I don't remember), even though I had the code done in literally this state before anyone else submitted a solution. This was entirely my fault, since I was accidentally using the SpaceBook star catalog.

Full code

Resources and other writeups