CTF-Writeups

Skyglyph I: Guide Star - CTF Challenge

Category: Misc
Difficulty: Easy

📥 Download Challenge

Download Skyglyph I Guide Star.zip - Try to solve it yourself before reading the writeup!


Challenge Summary

This challenge is a star-tracker calibration puzzle. You are given tracker_dump.csv containing many detections:

The trick is: use those guide stars to calibrate the camera, then map all detections back into a 2D sky plane. When plotted, the stars form a readable message/flag.


1. Use Guide Stars as Correspondences

Guide-star rows give you a correspondence between:

RA is given in hours — convert to degrees: ra_deg = 15 * ra_h, then to radians.

2. Project RA/Dec into a 2D Tangent Plane

Pixels are 2D. RA/Dec live on a sphere. We project RA/Dec to a local 2D tangent plane using a gnomonic projection.

Pick a projection center (ra0, dec0) — a deterministic choice is:

For each guide star:

Δra = wrap(ra - ra0) into [-π, π]

cosc = sin(dec0)*sin(dec) + cos(dec0)*cos(dec)*cos(Δra)
u    = (cos(dec) * sin(Δra)) / cosc
v    = (cos(dec0)*sin(dec) - sin(dec0)*cos(dec)*cos(Δra)) / cosc

3. Fit a Camera Model (Plane → Pixels)

Model how the tangent plane maps to pixel coordinates:

Radial Distortion (k1, k2)

r² = u² + v²
f  = 1 + k1*r² + k2*r⁴
(u_d, v_d) = (u*f, v*f)

Similarity Transform

[x, y] = s * R(θ) * [u_d, v_d] + [tx, ty]

Fit parameters p = (s, θ, tx, ty, k1, k2) by minimizing the reprojection error on the guide-star correspondences using a robust Gauss-Newton optimizer with Huber-like weighting.

4. Invert the Model (Pixels → Tangent Plane)

After fitting p, recover plane coordinates for all detections:

  1. Undo translation / scale / rotation to get distorted plane coords (u_d, v_d)
  2. Invert the radial distortion by solving r_d = r * (1 + k1*r² + k2*r⁴) for r using Newton iterations

5. Fix Orientation Deterministically

The recovered plane can be rotated or mirrored. The challenge defines a deterministic convention:

6. Render the “Blue Dots” Image

Plot the recovered plane coordinates. To reduce clutter, render only the brightest detections (keep points above a flux quantile, default: top 10%).

The solver writes a zoomable SVG: recovered_full.svg

Open it in a browser and zoom until the message is clear. If it’s too dense, raise the quantile:

python3 solver_skyglyph1_fullsvg.py --dir . --q 0.95

← Back to Blog