misc
Challenges

Read The Rules

Read the rules. They can be found in the #rules channel in discord, or here. The rules will contain a link, which will ultimately contain the flag.
Go to the saide rules page...you should be able to found the links at the very last line
scriptCTF{600D_1ucK_5011D3r1}

Div

I love division
import os
import decimal
decimal.getcontext().prec = 50
secret = int(os.urandom(16).hex(),16)
num = input('Enter a number: ')
if 'e' in num.lower():
print("Nice try...")
exit(0)
if len(num) >= 10:
print('Number too long...')
exit(0)
fl_num = decimal.Decimal(num)
div = secret / fl_num
if div == 0:
print(open('flag.txt').read().strip())
else:
print('Try again...')
The answer is inf
because:
secret / inf = 0
"inf" passes both checks (no 'e', length < 10)
decimal.Decimal("inf")
creates infinitysecret / ∞ = 0
triggers the flag conditionscriptCTF{70_1nf1n17y_4nd_b3y0nd_00ec1b195af8}

emoji

Emojis everywhere! Is it a joke? Or something is hiding behind it.
🁳🁣🁲🁩🁰🁴🁃🁔🁆🁻🀳🁭🀰🁪🀱🁟🀳🁮🁣🀰🁤🀱🁮🁧🁟🀱🁳🁟🁷🀳🀱🁲🁤🁟🀴🁮🁤🁟🁦🁵🁮🀡🀱🁥🀴🀶🁤🁽
This one was quite vauge, so some llm magic and kaboom...we know the type of shennanigen behinds the "emoji"
So the emojis are encoding ASCII text using playing card symbols as a substitution cipher. Each emoji maps to a specific character based on its position in the playing card Unicode block.
Conversion:
ord(char)
gets the Unicode value of each emoji- 0x1F030
removes the base playing card offset+ 48
shifts to ASCII rangechr()
converts back to readable characters
scriptCTF{3m0j1_3nc0d1ng_1s_w31rd_4nd_fun!1e46d}
# emoji_string = "🁳🁣🁲🁩🁰🁴🁃🁔🁆🁻🀳🁭🀰🁪🀱🁟🀳🁮🁣🀰🁤🀱🁮🁧🁟🀱🁳🁟🁷🀳🀱🁲🁤🁟🀴🁮🁤🁟🁦🁵🁮🀡🀱🁥🀴🀶🁤🁽"
with open('emoji.txt', 'r') as file:
emoji_string = file.read()
flag = ''.join(chr(ord(char) - 0x1F030 + 48) for char in emoji_string)
print(flag)
Enchant

I was playing minecraft, and found this strange enchantment on the enchantment table. Can you figure out what it is? Wrap the flag in scriptCTF{}
ᒲ╎リᒷᓵ∷ᔑ⎓ℸ ̣ ╎ᓭ⎓⚍リ
tbh, I did a quick paste into Google to see what it is, and I got Galatic Alphabet.


scriptCTF{Minecraftisfun}
Div 2

Some might call this a programming challenge...
import secrets
import decimal
decimal.getcontext().prec = 50
secret = secrets.randbelow(1 << 127) + (1 << 127) # Choose a 128 bit number
for _ in range(1000):
print("[1] Provide a number\n[2] Guess the secret number")
choice = int(input("Choice: "))
if choice == 1:
num = input('Enter a number: ')
fl_num = decimal.Decimal(num)
assert int(fl_num).bit_length() == secret.bit_length()
div = secret / fl_num
print(int(div))
if choice == 2:
guess = int(input("Enter secret number: "))
if guess == secret:
print(open('flag.txt').read().strip())
else:
print("Incorrect!")
exit(0)
What the program does is generate a secret 128-bit number and allows us to
Provide a number and get
int(secret / our_number)
Guess the secret number
The vulnerability is at line
div = secret / fl_num print(int(div))
This gives you
secret // fl_num
(integer division result), which leaks information about the secret's magnitude relative to your input.We also know the secret's range from this line in the challenge:
secret = secrets.randbelow(1 << 127) + (1 << 127) # Choose a 128 bit number
That is why we can perform a search to narrow down the 128-bit space logarithmically
from pwn import *
def solve():
p = process(['python3', 'chall.py'])
# p = remote('play.scriptsorcerers.xyz', 10311)
# Binary search for the secret
# Secret is 128-bit: between 2^127 and 2^128-1
low = 1 << 127
high = (1 << 128) - 1
while low <= high:
mid = (low + high) // 2
print(f"Trying mid = {mid}")
# Query: what is secret // mid ?
p.sendlineafter(b'Choice: ', b'1')
p.sendlineafter(b'Enter a number: ', str(mid).encode())
quotient = int(p.recvline().strip())
if quotient == 0:
# secret < mid
high = mid - 1
elif quotient == 1:
# secret >= mid and secret < 2 * mid
# Check if secret >= mid + 1
if mid + 1 <= high:
p.sendlineafter(b'Choice: ', b'1')
p.sendlineafter(b'Enter a number: ', str(mid + 1).encode())
quotient2 = int(p.recvline().strip())
if quotient2 == 0:
# secret < mid + 1, so secret == mid
secret = mid
break
else:
# secret >= mid + 1
low = mid + 1
else:
secret = mid
break
else:
# quotient >= 2, so secret >= 2 * mid
low = 2 * mid
# Guess the secret
p.sendlineafter(b'Choice: ', b'2')
p.sendlineafter(b'Enter secret number: ', str(secret).encode())
result = p.recvline().strip().decode()
print(f"Result: {result}")
p.close()
solve()
```python
❯ python solve.py
[+] Starting local process '/home/x/miniconda3/envs/ctfs/bin/python3': pid 1176860
Trying mid = 255211775190703847597530955573826158591
Trying mid = 297747071055821155530452781502797185023
Trying mid = 276479423123262501563991868538311671807
Trying mid = 287113247089541828547222325020554428415
...
Trying mid = 281308022660211790137507177938664385631
Trying mid = 281308022660211790137507177938664385647
Trying mid = 281308022660211790137507177938664385639
Trying mid = 281308022660211790137507177938664385643
Trying mid = 281308022660211790137507177938664385641
Result: scriptCTF{b1n4ry_s34rch_u51ng_d1v1s10n?!!_5ad3d0d2dee7}
[*] Stopped process '/home/x/miniconda3/envs/ctfs/bin/python3' (pid 1176860)
scriptCTF{b1n4ry_s34rch_u51ng_d1v1s10n?!!_5ad3d0d2dee7}
Subtract

The image size is 500x500. You might want to remove some stuff... Note: Some may call it guessy!
❯ unzip -l coords.zip
Archive: coords.zip
Length Date Time Name
--------- ---------- ----- ----
2645453 2025-07-12 09:06 coordinates.txt
--------- -------
2645453 1 file
The description said it...the coords is to form an 500x500 image, and we have to remove the noise.
Upon closer inspection, many coordinates appear multiple times in the file.
When we count how many times each coordinate appears:
Most pixels appear an even number of times (typically twice)
A smaller subset appears an odd number of times (typically once)
By keeping only odd-parity pixels, the noise cancels out and the hidden message emerges
import re
import numpy as np
from PIL import Image
from collections import Counter
def solve():
# Read coordinates
with open("coordinates.txt", 'r') as f:
content = f.read()
# Extract all (x,y) pairs
pairs = re.findall(r'\((\d+),\s*(\d+)\)', content)
coords = [(int(x), int(y)) for x, y in pairs]
# Count occurrences of each coordinate
counter = Counter(coords)
# Create image: only plot coordinates with ODD occurrences
img = np.zeros((500, 500), dtype=np.uint8)
for (x, y), count in counter.items():
if count % 2 == 1: # Keep odd parity only
if 0 <= x < 500 and 0 <= y < 500:
img[y, x] = 255
# Find content bounds and crop
white_pixels = np.where(img == 255)
if len(white_pixels[0]) > 0:
min_y, max_y = white_pixels[0].min(), white_pixels[0].max()
min_x, max_x = white_pixels[1].min(), white_pixels[1].max()
# Add padding
padding = 10
min_y = max(0, min_y - padding)
max_y = min(499, max_y + padding)
min_x = max(0, min_x - padding)
max_x = min(499, max_x + padding)
# Crop and save
cropped = img[min_y:max_y+1, min_x:max_x+1]
Image.fromarray(cropped).save('flag.png')
else:
Image.fromarray(img).save('flag.png')
solve()

What really tripped me up was the character that looked like a
6
. I must have tried it at least 10 different ways (which was all wrong and tanked my accuracy), thinking there was some hidden trick to remove the “noise.”Turns out, it was just plain leet speak (1337) where
6
should actually be read as5
. I don’t know if this is the intended way to deduce the solution, but it’s the best explanation I have.

scriptCTF{5ub7r4c7_7h3_n01s3}
Modulo

Modulo is so cool!
tbd.
Last updated