Category: Misc

scriptCTF is a 48-hour jeopardy style CTF for hackers to test their skills against creative and innovative CTF challenges. We have mostly beginner friendly challenges, with a few hard ones. scriptCTF makes CTFs fun and approachable for all skill levels! This is hosted by ScriptSorcerers and some members of n00bzUnit3d (as a replacement of n00bzCTF).
As you can see, I definitely used up my last attempt. As the challenge description said, had to guess 🙂 I’ll explain why this challenge requires so much guesswork.
We have a list of coordinates for a 500×500 image. The procedure for these types of Misc questions is usually as follows:
Progress Plan
- Read the coordinates ((x, y) pairs).
- Plot them as white dots on a 500×500 blank canvas (e.g., with a black background).
- The resulting pattern/text will likely be a flag.
- The “remove some stuff… guessy” tip in the description: Perhaps some of the coordinates are noise. So, you might need to remove some dots when you see the image.
How Do We Proceed?
1. Count the Number of Coordinates
Is the file really providing all 500×500 = 250,000 pixels, or just slightly fewer?
print(len(points))
250573
When we see that it is more than it should be, we see the “noise”.
2. Subsampling / Pattern Searching
To “remove the noise,” we can try a few possibilities:
- Remove pixels with odd x or y coordinates → the remaining subset might form the flag.
- Sample every nth point (for example, every 2nd or 3rd).
- Apply XOR/parity: if the same pixel appears multiple times, maybe only the odd occurrences should remain.
Conclusion
points = []
with open("coordinates.txt") as f:
for line in f:
line = line.strip()
if not line:
continue
x, y = line.strip("()").split(",")
points.append((int(x), int(y)))
- Opens
coordinates.txt
line by line. - Removes whitespace.
- Splits each line into
(x, y)
numbers. - Converts them to integers and stores them as tuples in the list
points
.
At the end, points
= list of all (x, y)
pixel coordinates.
size = (500, 500)
counter = Counter(points)
img = Image.new("RGB", size, "black")
draw = ImageDraw.Draw(img)
- Image size is fixed to 500×500 (based on challenge description).
counter = Counter(points)
→ counts how many times each(x, y)
occurs.- Creates a black canvas.
draw
is a drawing object to plot pixels.
for (x, y), c in counter.items():
if c % 2 == 1: # odd occurrences only
draw.point((x, y), fill="white")
- Iterates over each coordinate and its number.
- If this coordinate appears an odd number of times → draw it in white.
- If it appears an even number of times → skip (cancel).
This applies an XOR mask: multiple occurrences cancel each other out, leaving only odd occurrences. This is exactly what we want. You can find the full code below.
from PIL import Image, ImageDraw
from collections import Counter
# Read coordinates from the file
points = []
with open("coordinates.txt") as f:
for line in f:
line = line.strip()
if not line:
continue
# Remove parentheses and split into x, y
x, y = line.strip("()").split(",")
points.append((int(x), int(y)))
# Prepare a 500x500 canvas (black background)
size = (500, 500)
counter = Counter(points) # count how many times each coordinate occurs
img = Image.new("RGB", size, "black")
draw = ImageDraw.Draw(img)
# Draw only the coordinates that occur an odd number of times
# (This works like XOR: if a point is repeated, it cancels out unless it appears an odd number of times)
for (x, y), c in counter.items():
if c % 2 == 1:
draw.point((x, y), fill="white")
# Save the resulting image
img.save("output_xor.png")
'''
# Alternative simple method: draw all points directly as white
for x, y in points:
draw.point((x, y), fill="white")
'''
# Print the number of points and a status message
print(len(points))
print("output_xor.png saved!")
When we examine “output_xor.png” we can access the flag.

FLAG: scriptCTF{5ub7r4c7_7h3_n01s3}