cd ..

n00bzCTF

Not last week but the week before that I participated in n00bzCTF! I solved 5 problems and had lots of fun working with teammates from Japan. When I woke up to check the problems to solve, they’d already done so many! Here are a few that I solved.

RSA

Crypto

The cryptography category is incomplete without RSA. So here is a simple RSA challenge. Have fun!
e = 3
n = 135112…
c = 130377…

Where n and c were about 100-200 digits long. I saw a problem like this when I was making my RSA presentation for the Directed Reading Program at university. So I went and found the writeup, installed the necessary packages, and we were cracking!

The shell commands used for installing the packages:

python3 -m venv n00bz-ctf
source n00bz-ctf/bin/activate
python3 -m pip install gmpy

The script run to find the flag:

import gmpy
mToE = c
mToE = gmpy.mpz(int(mToE))
m = int(mToE.root(e)[0])
print(bytes.fromhex(hex(m)[2:]))

This is explained in point three in this answer on Cryptography StackExchange where we do root extraction on c = m^e.

n00bz{crypt0_1s_1nc0mpl3t3_w1th0ut_rs4!!}

Vinegar 2

Crypto

Never limit yourself to only alphabets!

Given chall.py and enc.txt. I started by reading through chall.py and adding notes:

flag=''
key='5up3r_s3cr3t_k3y_f0r_1337h4x0rs_r1gh7?'
flag_arr = []
key_arr = []
decr_arr=[]

# Create an array of the indices of the matrices which start with the letters in the flag
for flag_letter in flag:
	# go through every matrix of alphabet orders
	for i in range(len(alphanumerical)):
		# if the matrix starts with the letter in the flag, append it to flag_arr
		if matrix[i][0][0]==flag_letter:
			flag_arr.append(i)

# do the same for the key
for key_letter in '5up3r_s3cr3t_k3y_f0r_1337h4x0rs_r1gh7?':
	for i in range(len(alphanumerical)):
		if matrix[i][0][0]==key_letter:
			key_arr.append(i)

# For each flag letter,
for i in range(len(flag)):
	# Get the matrix which starts with that letter
	# Append the letter at the index of the matrix which starts with the corresponding key letter
	enc_arr.append(matrix[flag_arr[i]][0][key_arr[i]])

encrypted=''.join(enc_arr)
encrypted='*fa4Q(}$ryHGswGPYhOC{C{1)&_vOpHpc2r0({'

The matrix is the encryption/decription key and the scheme is Vigenere. So that’s why they called it Vinegar! I always look forward to the funny challenge names. After messing with the code, I got the solution:

alphanumerical = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*(){}_?'
matrix = []
for i in alphanumerical:
	matrix.append([i])

idx=0
for i in alphanumerical:
	matrix[idx][0] = (alphanumerical[idx:len(alphanumerical)]+alphanumerical[0:idx])
	idx += 1

key='5up3r_s3cr3t_k3y_f0r_1337h4x0rs_r1gh7?'
key_arr = []
encrypted='*fa4Q(}$ryHGswGPYhOC{C{1)&_vOpHpc2r0({' # given in enc.txt
enc_arr= list(encrypted)
flag_arr = []
# Want to solve for
flag=''
decr_arr=[]

# Build the key array
for key_letter in key:
	for i in range(len(alphanumerical)):
		if matrix[i][0][0]==key_letter:
			key_arr.append(i)

# Build the flag array
for enc_i in range(len(encrypted)):
	for i in range(len(alphanumerical)):
		# Find the matrix whose key_arr[i]-th character is enc_arr[i]
		if matrix[i][0][key_arr[enc_i]]==encrypted[enc_i]:
			flag_arr.append(i)
			break

for i in flag_arr:
	decr_arr.append(matrix[i][0][0])

flag=''.join(decr_arr)
print(flag)

n00bz{4lph4num3r1c4l_1s_n0t_4_pr0bl3m}

Numbers 2

Programming

The full challenge statement is here. The statement referenced n00bzCTF 2023, so I took a look at the old writeups and found this similar problem. I used the code in the solution as starter code for this problem.

Then I connected to the container to see the different formats of questions that could be asked. The possible formats were

  • “Give me the least common multiple of {x} and {y}:”
  • “Give me the greatest common divisor of {x} and {y}:”
  • “Give me the greatest prime factor of {x}:”

So I started cracking! I took the list of prime numbers up to 621 or so from Wikipedia and hard-coded it into an array. Because of that, the script is quite large, so I put it in a separate file. You can download/view it here. After running, I got an EOF error. Can you guess what caused it?

Traceback (most recent call last):
  File "/PATH/n00bz-ctf/num2.py", line 45, in <module>
    round = io.readline() # Current round:
  File "/PATH/python3.10/site-packages/pwnlib/tubes/tube.py", line 1489, in wrapper
    return func(self, *a, **kw)
  File "/PATH/python3.10/site-packages/pwnlib/tubes/tube.py", line 498, in recvline
    return self.recvuntil(self.newline, drop = not keepends, timeout = timeout)
  File "/PATH/python3.10/site-packages/pwnlib/tubes/tube.py", line 341, in recvuntil
    res = self.recv(timeout=self.timeout)
  File "/PATH/python3.10/site-packages/pwnlib/tubes/tube.py", line 106, in recv
    return self._recv(numb, timeout) or b''
  File "/PATH/python3.10/site-packages/pwnlib/tubes/tube.py", line 176, in _recv
    if not self.buffer and not self._fillbuffer(timeout):
  File "/PATH/python3.10/site-packages/pwnlib/tubes/tube.py", line 155, in _fillbuffer
    data = self.recv_raw(self.buffer.get_fill_size())
  File "/PATH/python3.10/site-packages/pwnlib/tubes/sock.py", line 56, in recv_raw
    raise EOFError
EOFError

I didn’t have enough primes in my array! So I went back and added the whole table from Wikipedia (primes up to 1,000), ran the script again, and vwala!

n00bz{numb3r5_4r3_fun_7f3d4a}

Subtraction

Misc

My little brother is learning math, can you show him how to do some subtraction problems?

Given server.py.

I started by adding notes.

import random
n = 696969
a = []

# Fill the array with even integers from 0 to 696968
for i in range(n):
    a.append(random.randint(0, n))
    a[i] -= a[i] % 2

# print(' '.join(list(map(str, a))))
# print(max(a)//2)

for turns in range(20):
    c = int(input())
    # Replace with the absolute difference in each value
    for i in range(n):
        a[i] = abs(c - a[i])

    print(set(a))
    # Until they all become the same number
    if len(set(a)) == 1:
        print(set(a))
        # print(open('/flag.txt', 'r').read())
        break

And as you can see by the print comments in the middle that I added, I started by replying with the floor of half of the max value in the array. But that didn’t always work in less than 20 tries.1

So I was a bit stumped. What to do? Then I realized that if I want to get the elements to converge to a point, why not choose the median?

from statistics import median

strA = open('./subtract_server_response.txt').read()
a=[int(i) for i in strA.split()]

response = int(median(a))
print("median: " + str(response))

for i in range(20):
    print(f"sending {response}")
    for i in range(len(a)):
        a[i] = abs(response - a[i])
    setA = set(a)
    a = list(setA)
    response = int(median(a))
    
print(a)

With that, we got the flag!

n00bz{1_sh0uld_t34ch_my_br0th3r_logs}

For more challenges, check the official writeups here!

Notes

  1. Turns out I was supposed to use the ceil, not the floor, according to the writeup. Oops.