10
2
Fork 0
has-writeup/aaaa/seeing-stars/README.md

66 lines
2.0 KiB
Markdown

# Seeing Stars
**Category**: Astronomy, Astrophysics, Astrometry, Astrodynamics, AAAA
**Points (final)**: 23
**Solves**: 213
> Here is the output from a CCD Camera from a star tracker, identify as many stars as you can! (in image reference coordinates)
> Note: The camera prints pixels in the following order (x,y): (0,0), (1,0), (2,0)... (0,1), (1,1), (2,1)…
>
> Note that top left corner is (0,0)
## Write-up
by [hazel (`arcetera`)](https://qtp2t.club/)
The CCD image given by the netcat is a 128x128 matrix of comma-separated values.
We read the data into a NumPy array, and pass that into OpenCV.
``` python
data = []
for line in rawdat.strip().split('\n'):
data.append([int(x) for x in line.split(',')])
x = np.array(data, dtype='uint8').T
im = x
```
We then run a filter on the data, only grabbing values in [127, 255] to filter
out data that is *obviously not* stars.
We then run two dilates on the image post-filter, because otherwise
we end up with a division by zero on centroid finding later for `M["m00"]`.
Finally, we grabbed the contour of every object visible in the image.
``` python
ret, thresh = cv2.threshold(im.copy(), 127, 255, 0)
kernel = np.ones((5, 5), np.uint8)
dilated = cv2.dilate(thresh.copy(), kernel, iterations = 2)
cnts, hier = cv2.findContours(dilated.copy(), \
cv2.RETR_TREE, \
cv2.CHAIN_APPROX_NONE)
```
For each contour, we grabbed its centroid:
``` python
solve = ''
for c in cnts:
M = cv2.moments(c)
cX = int(M["m10"] / M["m00"])
cY = int(M["m01"] / M["m00"])
solve += (str(cX) + "," + str(cY)+'\n')
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, 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>