NED CTF 2023 Challenges writeup

Assalam — u- Alikum friends!, my name is Rehan Mumtaz. I am the President of NED Cyber Community and final year software student from NED University. I am here sharing you all the writeups of the challenges I made in the recent NED CTF 2023.
There are 3 different categories in which I contribute:
- Warmup
- Osint
- Cryptography
Warmup
Famous One ( 50 pts )

In this challenge we have to find out the country from where the picture it was taken?

Trying reverse image search, there were similar different countries tend to show the same result. Look at the title of the challenge “FAMOUS”, I dig deeper into it ; we found

Flag: NCC{iceland}
Mun se supaari Nikaal ( 50 pts )

In this challenge, we were provided with some encoded characters. Googling these characters, I found out the encoding but it seemed its name was like

Brainfuck programming language
So i opened dcode.fr for decoding

Upon getting the text, i reversed it and retrieve the flag
flag: NCC{warmups_ez_pz}
OSINT
Help me Harry ! ( 300 pts )

We were provided with a gif image and a password protected zip. As reading the challenge description, I assumed it is somewhat connected with the Harry Potter movie. I analysed :
- i need to find password of the zip file, as it is prohibited to do bruteforcing.
- There is some twist with the original movie line, as Ron is the one who sacrificed his life for the mission in the Chess game but things were opposite over here.
- Password of the zip file is combine moves of the harry team to checkmate as it was instructed
Combine your team step and pass through me.
First of all looking at the chess board, on the x & y axes combining these two, a move is created; that means it is of two letters for a move.
I googled the steps needed to checkmate, and in the movie not the whole game was covered, only the certain part of it was shown. I got the steps in this article as shown below:
- c3 ( Ron sacrifices a rook to protect Harry ,their 1st move )
- c5 ( Harry take this move and sacrificed himself, 2nd move)
- h3 ( Ron take this move and checkmate , 3rd move )
pass: c3c5h3
Opening the zip with this password, we got this file

Checking this image, i found out its talking about some book
Chamber of secrets
Next, i run strings commands over this file and found out the url
‘ tinyurl.com/pottttttter ‘. I got the following flag (1st part) with hint
NCC{r0n_4s_@
// dONT VISIt me unless you find my owner and year I was bought
I have to find the owner of this book with the year it was first bought. Googling these i got TomRiddle as the owner and 1943 as year. Since it was given dont visit, i checked the url with its endpoint and its look fishy (potttttttter) .
I added those 2 things as the endpoint & url becomes (tinyurl.com/tomriddle1943) . I was redirected to google drive and following picture popped up

Doing reverse image search showed it was some Runes alphabet. Opening its dictionary and decoding it provided me with flag 2nd part
flag: NCC{r0n_4s_@gem}
Sindho Darya ( 500 pts )

Reading the title tells us about some sindh river. We were provided with the audio file. Listening to the voice tells us about some different words separated by dots.
Words I wrote : quaked.jazz.tailback
These words didnot mean anything when I googled it. Looking at the hint tells me about the location. So i searched and found this website. The three words website is another way of telling a location. I searched via these cordinates and found out the Keenjhar Lake location. I quickly searched these in google maps and look for any hint there and I found out

Checking the encoding turns out DNA encoding, decoding it gives me

Opening the pastebin provided me a long paragraph, but one thing I notice there are different characters at the end of each paragraph. I picked them all onebyone

𓉨𒅴潳搯鹴𖥮𓁵捬𒁣摭陰ꍬ艡顡ꍨᕩ𓉨𒅴潳搯鹴𖥮𓁵捬𒁣摭陰ꍬ艡顡ꍨᕩ
I searched for how these can be decoded but couldnot find anything, revisit the link again and found out there was a hint given encoding of base 65536. Decoding it provided me with : https://tinyurl.com/pallaMachli
Checking out this link provided me with lots of images in a single folder. Analyzing the images provided me with an email address:

cyberwarr7@gmail.com
Getting the email address, i quickly run epios tool. As provided in the description about busy schedule, I checkout the calendar link

and retrieve the flag
flag : NCC{osint_t0_b4ch@_h@3_g33}
Cryptography
Johnny RSA ( 300 pts )

Reading the description tells us about problem is entirely based upon prime numbers. We were provided with the encryption.py file and cipher text. Lets analyze the code:
from Crypto.Util.number import *
import random
fl4g = 'just a test flag'
def zyxv(a, b):
if a == 0:
return (b, 0, 1)
else:
phi, hi, ki = zyxv(b % a, a)
return (phi, ki - (b // a) * hi, hi)
def pForPrime(n):
num = n + 1
while True:
if isPrime(num):
return num
num += 1
def invOfMod(n, m):
foo, x, y = zyxv(n, m)
if foo != 1:
#create the Exception('As there is no modular inverse')
print "hehe"
else:
return x % m
partial = random.getrandbits(252) + (1 << 251)
p = pForPrime(partial)
part1 = pForPrime(p*10)
part2 = pForPrime(part1*10)
part3 = pForPrime(part2*10)
N = p*part1*part2*part3
e = 65537
c = pow(bytes_to_long(fl4g),e,N)
print "this is ",c
# 285876694736313373115727102895590518529037967857715478865324417502887442565471564532286367254203603936883908083855569573861923801835808039117580002544830446515649741184683181210817040545591244744076296582526006232511918698310699401946477588433591061721118364901450712176238081603244938724774915421725728927023
print "this is ",N
# 1054877928716663351837371954177595860020996117011823422503679289363556104282667678730827569238069468701587798979549576934253785190396398320479042110677969046582395306905834865271541246304038494980673201689226177468773343213345157969554264445838722397302271538906427578287663876072833756666343853821150126661813
My analysis were: -
- Prime number is combination of 4 prime numbers
- 1st prime number is generated randomly and it is of 251 bits.
- The later ones are made using the 1st one.
- N = p**4 x 10**6
Lets make a decryption script :
from functools import reduce
from math import sqrt
from Crypto.Util.number import *
n = 1054877928716663351837371954177595860020996117011823422503679289363556104282667678730827569238069468701587798979549576934253785190396398320479042110677969046582395306905834865271541246304038494980673201689226177468773343213345157969554264445838722397302271538906427578287663876072833756666343853821150126661813
c = 285876694736313373115727102895590518529037967857715478865324417502887442565471564532286367254203603936883908083855569573861923801835808039117580002544830446515649741184683181210817040545591244744076296582526006232511918698310699401946477588433591061721118364901450712176238081603244938724774915421725728927023
def search(final, t0, t1, h):
while t0 < t1:
median = (t0 + t1) // 2
if h(median) > final:
t1 = median - 1
else:
t0 = median + 1
return t0
power = lambda p: 1000000 * p**4
partial = search(n, 1 << 251, 1 << 252, power)
AllPrimes = [g for g in range(-1000 + partial , 1000 + partial ) if n % g == 0][:1]
print('Prime numbers are:', AllPrimes)
flag = long_to_bytes(pow(c, invOfMod(65537, reduce(lambda a, b: a * (b - 1), primes, 1)), n)).decode('utf-8')
print(flag)
flag: NCC{rs$_is_my_b@by}
Super Secure ( 500 pts )
In this challenge we were provided with AES.py file and scripted file that contains ciphertext. Looking at the code tells us that it is the AES implementation. Provided code :
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from hashlib import md5
from os import urandom
from dummyflag import flag
pt = "my Algo is not something you can break; my upcoming project is gonna be much greater you can ever imagine, well you can have the flag for the time being - $flag".encode()
num_keys = 2
keys = [md5(urandom(3)).digest() for _ in range(num_keys)]
def secure(msg, iv1, iv2):
mssg = pad(msg, 32)
ciphers = get_Thanos(iv1, iv2)
ct = mssg
for cipher in ciphers:
ct = b''.join(i[16:] + fullxhor(i[:16], cipher.encrypt(i[16:])) for i in [ct[i:i+32] for i in range(0, len(ct), 32)])
return ct
def get_Thanos(sec0, sec2):
return [
AES.new(keys[0], mode=AES.MODE_CBC, iv=sec0),
AES.new(keys[1], mode=AES.MODE_CFB, iv=sec2, segment_size=8*16),
]
def fullxhor(ds, tg):
return bytes(i^j for i,j in zip(ds, tg))
suvo,suvo1 = urandom(16), urandom(16)
ct = secure(pt, suvo, suvo1)
ct = b":".join([x.hex().encode() for x in [suvo, suvo1, ct]])
open('scripted', 'wb').write(ct)
Lets understand the code by making a rough diagram as events are taking place:

- So there are two rounds of fiestal structure
- The key can be bruteforced
- Since we have both plain text and cipher text, can try known ciphertext attack.
Lets try making a decryptor :
from hashlib import md5
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
def xorring(x, y):
result = bytearray()
for i, j in zip(x, y):
result.append(i ^ j)
return bytes(result)
def get_Thanos(sec0, sec2):
return [
AES.new(keys[0], mode=AES.MODE_CBC, iv=sec0),
AES.new(keys[1], mode=AES.MODE_CFB, iv=sec2, segment_size=8*16),
]
def todecryptor(c: bytes, sec0: bytes, sec2: bytes) -> bytes:
ct = get_Thanos(sec0, sec2)
m = c
for cipher in reversed(ct):
m = b''.join(xorring(i[16:], cipher.encrypt(i[:16])) + i[:16] for i in [m[i:i+32] for i in range(0, len(m), 32)])
return unpad(m, 32)
with open('scripted', 'rb') as file:
data = file.read().strip().decode()
sec0, sec1, ct = [bytes.fromhex(i) for i in data.split(':')]
pt = b'my Algo is not something you can break; my upcoming project is gonna be much greater you can ever imagine, well you can have the flag for the time being - '
keys = []
for i in range(256):
for j in range(256):
for k in range(256):
data = bytes([i, j, k])
key = md5(data).digest()
keys.append(key)
keyOne = None
for i in keys:
encrypted = AES.new(i, AES.MODE_CBC, sec0).encrypt(pt[16:32])
if xorring(pt[:16], encrypted) == ct[:16]:
keyOne = i
break
keyTwo = None
for i in keys:
if xorring(AES.new(i, AES.MODE_CFB, sec1, segment_size=8*16).encrypt(ct[:16]), ct[16:32]) == pt[16:32]:
keyTwo = i
break
keys, flag = [keyOne, keyTwo], todecryptor(ct, sec0, sec1)[155:]
print("Flag is :",flag)
Flag: NCC{my_sec4rest_ever_made}
Meanwhile running the script on my PC feels like:

Thank you for reading my writeup! 🙌