Posted on :: Tags:

Hi Readers! I played UMDCTF 2023 which was happened from 29 Apr to 01 May. I played it with the team Invaders0x1.

These are the writeups for the challenges I solved.

Crypto

CBC-MAC1

cbcmac1

Attached Files : cbc-mac1.py

cbc-mac1.py

import socket
import threading
from _thread import *
from Crypto import Random
from Crypto.Cipher import AES
from binascii import hexlify, unhexlify
HOST = '0.0.0.0'  # Standard loopback interface address (localhost)
PORT = 60001        # Port to listen on (non-privileged ports are > 1023)
FLAG = open('flag.txt', 'r').read().strip()
MENU = "\nWhat would you like to do?\n\t(1) MAC Query\n\t(2) Forgery\n\t(3) Exit\n\nChoice: "
INITIAL = "Team Rocket told me CBC-MAC with arbitrary-length messages is safe from forgery. If you manage to forge a message you haven't queried using my oracle, I'll give you something in return.\n"
BS = 16 # Block Size
MAX_QUERIES = 10
def cbc_mac(msg, key):
    iv = b'\x00'*BS
    cipher = AES.new(key, AES.MODE_CBC, iv=iv)
    t = cipher.encrypt(msg)[-16:]
    return hexlify(t)
def threading(conn):
    conn.sendall(INITIAL.encode())
    key = Random.get_random_bytes(16)
    queries = []
    while len(queries) < MAX_QUERIES:
        conn.sendall(MENU.encode())
        try:
            choice = conn.recv(1024).decode().strip()
        except ConnectionResetError as cre:
            return
        # MAC QUERY
        if choice == '1':
            conn.sendall(b'msg (hex): ')
            msg = conn.recv(1024).strip()
            try:
                msg = unhexlify(msg)
                if (len(msg) + BS) % BS != 0:
                    conn.sendall(f'Invalid msg length. Must be a multiple of BS={BS}\n'.encode())
                else:
                    queries.append(msg)
                    t = cbc_mac(msg, key)
                    conn.sendall(f'CBC-MAC(msg): {t.decode()}\n'.encode())
            except Exception as e:
                conn.sendall(b'Invalid msg format. Must be in hexadecimal\n')
        # FORGERY (impossible as I'm told)
        elif choice == '2':
            conn.sendall(b'msg (hex): ')
            msg = conn.recv(1024).strip()
            conn.sendall(b'tag (hex): ')
            tag = conn.recv(1024).strip()
            try:
                msg = unhexlify(msg)
                if (len(msg) + BS) % BS != 0:
                    conn.sendall(f'Invalid msg length. Must be a multiple of BS={BS} bytes\n'.encode())
                elif len(tag) != BS*2:
                    conn.sendall(f'Invalid tag length. Must be {BS} bytes\n'.encode())
                elif msg in queries:
                    conn.sendall(f'cheater\n'.encode())
                else:
                    t_ret = cbc_mac(msg, key)
                    if t_ret == tag:
                        conn.sendall(f'If you reach this point, I guess we need to find a better MAC (and not trust TR). {FLAG}\n'.encode())
                    else:
                        conn.sendall(str(t_ret == tag).encode() + b'\n')
            except Exception as e:
                conn.sendall(b'Invalid msg format. Must be in hexadecimal\n')
        else:
            if choice == '3': # EXIT
                conn.sendall(b'bye\n')
            else: # INVALID CHOICE
                conn.sendall(b'invalid menu choice\n')
            break
    if len(queries) > MAX_QUERIES:
        conn.sendall(f'too many queries: {len(queries)}\n'.encode())
    conn.close()
if __name__ == "__main__":
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.bind((HOST, PORT))
        s.listen()
        while True:
            conn, addr = s.accept()
            print(f'new connection: {addr}')
            start_new_thread(threading, (conn, ))
        s.close()

The remote challenge is at nc 0.cloud.chals.io 12769. The challenges is Generating a Message Authentication Code [Tag] For the given input message. The message should be in hex format and the length of the message has to be multiple of 16.

mj0ln1r@AHLinux:~/cbc0mac1$ nc 0.cloud.chals.io 12769
Team Rocket told me CBC-MAC with arbitrary-length messages is safe from forgery. If you manage to forge a message you haven't queried using my oracle, I'll give you something in return.

What would you like to do?
	(1) MAC Query
	(2) Forgery
	(3) Exit

Choice: 1
msg (hex): 6162636465666768696a6b6c6d6e6f70
CBC-MAC(msg): f670f2abb9159a15a82a5779adbfb7bc

What would you like to do?
	(1) MAC Query
	(2) Forgery
	(3) Exit

Choice: 1
msg (hex): 6162636465666768696a6b6c6d6e6f706162636465666768696a6b6c6d6e6f70
CBC-MAC(msg): 2836413262109e028fe4e00452f60f53

What would you like to do?
	(1) MAC Query
	(2) Forgery
	(3) Exit

Choice: 

The program is taking the variable length message as input, this is a flag in cbc-mac.

cbcmac11

So, The MAC or Tag is the last encrypted plaintext in the CBC Mode of AES. As the program allowing us to input variable length message we can generate a new message M2 with the same tag t1 which is the tag of M1. To do this I choosed M2 with 2 blocks of plaintext with 16 characters each. The new_M2 = (last block of M2) xor t1 This new_M2 will have the same tag t1. This is how we can forge the message. Here is the automated script for the challenge.

from pwn import *
from Crypto.Util.strxor import strxor

conn = remote('0.cloud.chals.io',12769)
conn.recvuntil(b'Choice: ')
conn.sendall(b'1')
conn.recvuntil(b'msg (hex): ')

m1 = "abcdefghijklmnop"
m2 = "abcdefghijklmnopqrstuvwxyz123456"

m1_hex = ''.join(hex(ord(c))[2:] for c in m1)
m2_hex = ''.join(hex(ord(c))[2:] for c in m2)

conn.sendline(m1_hex.encode())
conn.recvuntil(b'(msg): ')

tag1 = conn.recvline().strip()
x = strxor(m2_hex[32:].encode(),tag1)
new_m2 = m2_hex[:32]+x.decode()
conn.recvuntil(b"Choice: ")
conn.sendline(b"2")
conn.recvuntil(b"msg (hex): ")
conn.sendline(new_m2.encode())
conn.recvuntil(b"tag (hex): ")
conn.sendline(tag1)
flag = conn.recv()
print(flag)

Flag : UMDCTF{Th!s_M@C_Sch3M3_1s_0nly_S3cur3_f0r_f!xed_l3ngth_m3ss4g3s_78232813}

Pokecomms

pokecomms

The challenge had this txt file.

 CHU! PIKA CHU! PIKA CHU! PIKA CHU! PIKA
 CHU! PIKA CHU! CHU! PIKA PIKA CHU! PIKA
 CHU! PIKA CHU! CHU! CHU! PIKA CHU! CHU!
 CHU! PIKA CHU! CHU! CHU! CHU! PIKA PIKA
 CHU! PIKA CHU! PIKA CHU! PIKA CHU! CHU!
 CHU! PIKA CHU! CHU! CHU! PIKA PIKA CHU!
 CHU! PIKA PIKA PIKA PIKA CHU! PIKA PIKA
 CHU! PIKA CHU! PIKA CHU! CHU! CHU! CHU!
 CHU! CHU! PIKA PIKA CHU! CHU! CHU! PIKA
 CHU! PIKA CHU! CHU! PIKA CHU! PIKA PIKA
 CHU! CHU! PIKA PIKA CHU! PIKA CHU! CHU!
 .
 .
 CHU! CHU! PIKA PIKA CHU! PIKA CHU! CHU!

The first thing I did is eliminated the duplicate lines in text file. Then I saw that there are only 8 words in every line. And the The words are only CHU! PIKA with random sequence. So, I changed CHU! to 1 and PIKA to 0. Got the binary bits then converted it to ascii to get the flag.

The solution script is

with open("pokecomms.txt","r") as f:
    l = f.readlines()
m = []
for i in l:
    m.append(i.strip())
s = list(set(m))
byte=[]
for i in m:
    bits=[]
    for j in i.split():
        if j == "CHU!":
            bits.append('0')
        elif j == "PIKA":
            bits.append('1')
        else:
            print("else")
    oneb = "".join(bits)
    byte.append(int(oneb,2))

for i in byte:
    print(chr(i),end="")

#UMDCTF{P1K4CHU_Once_upon_a_time,_there_was_a_young_boy_named_Ash_who_dreamed_of_becoming_the_world's_greatest_Pokemon_trainer._He_set_out_on_a_journey_with_his_trusty_Pokemon_partner,_Pikachu,_a_cute_and_powerful_electric-type_Pokemon._As_Ash_and_Pikachu_traveled_through_the_regions,_they_encountered_many_challenges_and_made_many_friends._But_they_also_faced_their_fair_share_of_enemies,_including_the_notorious_Team_Rocket,_who_were_always_trying_to_steal_Pikachu._Despite_the_odds_stacked_against_them,_Ash_and_Pikachu_never_gave_up._They_trained_hard_and_battled_even_harder,_always_looking_for_ways_to_improve_their_skills_and_strengthen_their_bond._And_along_the_way,_they_learned_valuable_lessons_about_friendship,_determination,_and_the_power_of_believing_in_oneself._Eventually,_Ash_and_Pikachu's_hard_work_paid_off._They_defeated_powerful_opponents,_earned_badges_from_Gym_Leaders,_and_even_competed_in_the_prestigious_Pokemon_League_tournaments._But_no_matter_how_many_victories_they_achieved,_Ash_and_Pikachu_never_forgot_where_they_came_from_or_the_importance_of_their_friendship._In_the_end,_Ash_and_Pikachu_became_a_legendary_team,_admired_by_Pokemon_trainers_around_the_world._And_although_their_journey_may_have_had_its_ups_and_downs,_they_always_knew_that_as_long_as_they_had_each_other,_they_could_overcome_any_obstacle_that_stood_in_their_way}


Rev

Welcome to Python

welcome

Challenge had this binary file chall

As it is a ELF file I decompiled it to Pyc then Pyc to py file. My teammates found that python generated ELF can be decompiled to pyc with pyinstxtractor. It generated a pyc file then used online pyc decompiler to decompile to the py file.

The decompiled chall.py is

# Source Generated with Decompyle++
# File: chal.pyc (Python 3.10)
from math import sqrt, sin, cos
from ctypes import c_uint32, c_float
from sys import exit as exit_
source = [
    672662614,
    741343303,
    495239261,
    744259788,
    722021046,
    0xA70AA247,
    1053692,
    0xA8050035,
    0xA982A820,
    624689,
    0xA90D20BC,
    41134,
    295340,
    0xA0028102,
    622681,
    576469,
    671170814,
    0x8041086E,
    765,
    680595550,
    0x80200166,
    698368102,
    2437137,
    0x8042C1EE,
    570966112,
    4612341,
    0x800008D4,
    0xA94D02CE,
    16484,
    2103301,
    136226,
    9438506,
    663820758,
    0x8013523B,
    8405532,
    0xA4000875,
    0x80030A78,
    136768]
seed = 64
def wandom(x):
    return x * x * cos(x) * sin(x) / 1000
def evil_bit_hack(y):
    return int(c_uint32.from_buffer(c_float(y)).value)
print('==========================================')
print('Professional flag checker service (v 97.2)')
print('==========================================')
flag = input('Show me the flag: ')
lf = len(flag)
ls = len(source)
l = lf if lf < ls else ls
for i in range(seed, seed + l):
    w = wandom(i)
    c = ~(~ord(flag[i - seed]) ^ evil_bit_hack(wandom(wandom(w))) & evil_bit_hack(w)) + 1
    if source[i - seed] != c:
        print("Uh oh! We don't think your flag is correct... :(")
        exit_(1)
if lf == ls:
    print('Your flag is correct!')
# None('Some of your flag is correct...')

Points I observed

  • The seed is 64
  • source values are known
  • c is generated by XORing flag char with evil_bit_hack(wandom(wandom(w))) & evil_bit_hack(w) and 1 is added at the end.

So, I just need to reverse this line c = ~(~ord(flag[i - seed]) ^ evil_bit_hack(wandom(wandom(w))) & evil_bit_hack(w)) + 1 To print the flag.

Interesting, lets do it

res = (source[i-seed]-1)^ evil_bit_hack(wandom(wandom(w))) & evil_bit_hack(w) Will be the reversed function.

And here is the solution script to print the flag.

# Source Generated with Decompyle++
# File: chal.pyc (Python 3.10)

from math import sqrt, sin, cos
from ctypes import c_uint32, c_float
from sys import exit as exit_
source = [
    672662614,
    741343303,
    495239261,
    744259788,
    722021046,
    0xA70AA247,
    1053692,
    0xA8050035,
    0xA982A820,
    624689,
    0xA90D20BC,
    41134,
    295340,
    0xA0028102,
    622681,
    576469,
    671170814,
    0x8041086E,
    765,
    680595550,
    0x80200166,
    698368102,
    2437137,
    0x8042C1EE,
    570966112,
    4612341,
    0x800008D4,
    0xA94D02CE,
    16484,
    2103301,
    136226,
    9438506,
    663820758,
    0x8013523B,
    8405532,
    0xA4000875,
    0x80030A78,
    136768]
seed = 64

def wandom(x):
    return x * x * cos(x) * sin(x) / 1000

def evil_bit_hack(y):
    return int(c_uint32.from_buffer(c_float(y)).value)
flag = 38 * 'A'
lf = len(flag)
ls = len(source)
l = lf if lf < ls else ls

for i in range(seed, seed + l):
    w = wandom(i)
    x = evil_bit_hack(wandom(wandom(w))) & evil_bit_hack(w)
    c = ~(~ord(flag[i - seed]) ^ evil_bit_hack(wandom(wandom(w))) & evil_bit_hack(w)) + 1
    res = (source[i-seed]-1)^x
    print(chr(res),end="")
#UMDCTF{0_0+-+eXP-eLLiARm_us_!!!-12345}

Flag : UMDCTF{0_0+-+eXP-eLLiARm_us_!!!-12345}


Hardware

beep1

beep

The attached files are Beep1.circ which is a xml file and a flag.enc file.

Beep1.circ is

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project source="3.8.0" version="1.0">
  This file is intended to be loaded by Logisim-evolution v3.8.0(https://github.com/logisim-evolution/).

  <lib desc="#Wiring" name="0">
    <tool name="Pin">
      <a name="appearance" val="classic"/>
    </tool>
  </lib>
  <lib desc="#Gates" name="1"/>
  <lib desc="#Plexers" name="2"/>
  <lib desc="#Arithmetic" name="3"/>
  <lib desc="#Memory" name="4"/>
  <lib desc="#I/O" name="5"/>
  <lib desc="#TTL" name="6"/>
  <lib desc="#TCL" name="7"/>
  <lib desc="#Base" name="8"/>
  <lib desc="#BFH-Praktika" name="9"/>
  <lib desc="#Input/Output-Extra" name="10"/>
  <lib desc="#Soc" name="11"/>
  <main name="main"/>
  <options>
    <a name="gateUndefined" val="ignore"/>
    <a name="simlimit" val="1000"/>
    <a name="simrand" val="0"/>
  </options>
  <mappings>
    <tool lib="8" map="Button2" name="Poke Tool"/>
    <tool lib="8" map="Button3" name="Menu Tool"/>
    <tool lib="8" map="Ctrl Button1" name="Menu Tool"/>
  </mappings>
  <toolbar>
    <tool lib="8" name="Poke Tool"/>
    <tool lib="8" name="Edit Tool"/>
    <tool lib="8" name="Wiring Tool"/>
    <tool lib="8" name="Text Tool"/>
    <sep/>
    <tool lib="0" name="Pin"/>
    <tool lib="0" name="Pin">
      <a name="facing" val="west"/>
      <a name="output" val="true"/>
    </tool>
    <sep/>
    <tool lib="1" name="NOT Gate"/>
    <tool lib="1" name="AND Gate"/>
    <tool lib="1" name="OR Gate"/>
    <tool lib="1" name="XOR Gate"/>
    <tool lib="1" name="NAND Gate"/>
    <tool lib="1" name="NOR Gate"/>
    <sep/>
    <tool lib="4" name="D Flip-Flop"/>
    <tool lib="4" name="Register"/>
  </toolbar>
  <circuit name="main">
    <a name="appearance" val="logisim_evolution"/>
    <a name="circuit" val="main"/>
    <a name="clabelup" val="north"/>
    <a name="simulationFrequency" val="8.0"/>
    <comp lib="0" loc="(140,300)" name="Clock">
      <a name="label" val="clk"/>
    </comp>
    <comp lib="0" loc="(350,220)" name="Splitter">
      <a name="fanout" val="8"/>
      <a name="incoming" val="8"/>
    </comp>
    <comp lib="0" loc="(440,460)" name="Splitter">
      <a name="facing" val="west"/>
      <a name="fanout" val="8"/>
      <a name="incoming" val="8"/>
      <a name="spacing" val="2"/>
    </comp>
    <comp lib="0" loc="(460,130)" name="Splitter">
      <a name="facing" val="west"/>
      <a name="fanout" val="8"/>
      <a name="incoming" val="8"/>
    </comp>
    <comp lib="0" loc="(670,190)" name="Bit Extender">
      <a name="out_width" val="7"/>
      <a name="type" val="one"/>
    </comp>
    <comp lib="1" loc="(290,380)" name="NOT Gate">
      <a name="facing" val="north"/>
    </comp>
    <comp lib="1" loc="(300,340)" name="Controlled Buffer"/>
    <comp lib="1" loc="(320,540)" name="NOR Gate">
      <a name="facing" val="west"/>
      <a name="inputs" val="8"/>
    </comp>
    <comp lib="4" loc="(320,300)" name="Counter">
      <a name="appearance" val="classic"/>
    </comp>
    <comp lib="4" loc="(340,290)" name="ROM">
      <a name="appearance" val="classic"/>
    </comp>
    <comp lib="5" loc="(140,370)" name="Button">
      <a name="label" val="rst"/>
    </comp>
    <comp lib="5" loc="(710,200)" name="TTY">
      <a name="cols" val="40"/>
    </comp>
    <comp lib="5" loc="(710,260)" name="Button">
      <a name="label" val="tty_rst"/>
    </comp>
    <wire from="(140,300)" to="(160,300)"/>
    <wire from="(140,370)" to="(310,370)"/>
    <wire from="(160,300)" to="(160,340)"/>
    <wire from="(160,340)" to="(280,340)"/>
    <wire from="(290,350)" to="(290,380)"/>
    <wire from="(290,410)" to="(290,540)"/>
    <wire from="(290,540)" to="(320,540)"/>
    <wire from="(300,320)" to="(300,340)"/>
    <wire from="(300,340)" to="(330,340)"/>
    <wire from="(310,320)" to="(310,370)"/>
    <wire from="(320,300)" to="(340,300)"/>
    <wire from="(330,230)" to="(330,340)"/>
    <wire from="(330,230)" to="(690,230)"/>
    <wire from="(350,220)" to="(350,270)"/>
    <wire from="(350,270)" to="(590,270)"/>
    <wire from="(370,120)" to="(370,140)"/>
    <wire from="(370,120)" to="(480,120)"/>
    <wire from="(370,150)" to="(420,150)"/>
    <wire from="(370,160)" to="(380,160)"/>
    <wire from="(370,170)" to="(440,170)"/>
    <wire from="(370,180)" to="(390,180)"/>
    <wire from="(370,190)" to="(390,190)"/>
    <wire from="(370,200)" to="(380,200)"/>
    <wire from="(370,210)" to="(370,220)"/>
    <wire from="(370,220)" to="(420,220)"/>
    <wire from="(380,140)" to="(380,160)"/>
    <wire from="(380,140)" to="(430,140)"/>
    <wire from="(380,200)" to="(380,210)"/>
    <wire from="(380,210)" to="(400,210)"/>
    <wire from="(380,500)" to="(390,500)"/>
    <wire from="(380,510)" to="(400,510)"/>
    <wire from="(380,520)" to="(410,520)"/>
    <wire from="(380,530)" to="(420,530)"/>
    <wire from="(380,550)" to="(420,550)"/>
    <wire from="(380,560)" to="(410,560)"/>
    <wire from="(380,570)" to="(400,570)"/>
    <wire from="(380,580)" to="(390,580)"/>
    <wire from="(390,160)" to="(390,180)"/>
    <wire from="(390,160)" to="(440,160)"/>
    <wire from="(390,190)" to="(390,200)"/>
    <wire from="(390,200)" to="(440,200)"/>
    <wire from="(390,470)" to="(390,500)"/>
    <wire from="(390,470)" to="(420,470)"/>
    <wire from="(390,580)" to="(390,600)"/>
    <wire from="(390,600)" to="(420,600)"/>
    <wire from="(400,180)" to="(400,210)"/>
    <wire from="(400,180)" to="(440,180)"/>
    <wire from="(400,490)" to="(400,510)"/>
    <wire from="(400,490)" to="(420,490)"/>
    <wire from="(400,570)" to="(400,590)"/>
    <wire from="(400,590)" to="(420,590)"/>
    <wire from="(410,510)" to="(410,520)"/>
    <wire from="(410,510)" to="(420,510)"/>
    <wire from="(410,560)" to="(410,570)"/>
    <wire from="(410,570)" to="(420,570)"/>
    <wire from="(420,130)" to="(420,150)"/>
    <wire from="(420,130)" to="(440,130)"/>
    <wire from="(420,190)" to="(420,220)"/>
    <wire from="(420,190)" to="(440,190)"/>
    <wire from="(420,600)" to="(420,610)"/>
    <wire from="(430,140)" to="(430,150)"/>
    <wire from="(430,150)" to="(440,150)"/>
    <wire from="(440,130)" to="(440,140)"/>
    <wire from="(440,210)" to="(440,220)"/>
    <wire from="(440,220)" to="(480,220)"/>
    <wire from="(440,460)" to="(590,460)"/>
    <wire from="(460,130)" to="(590,130)"/>
    <wire from="(480,120)" to="(480,220)"/>
    <wire from="(580,350)" to="(590,350)"/>
    <wire from="(590,130)" to="(590,190)"/>
    <wire from="(590,190)" to="(630,190)"/>
    <wire from="(590,270)" to="(590,350)"/>
    <wire from="(590,350)" to="(590,460)"/>
    <wire from="(670,190)" to="(710,190)"/>
    <wire from="(690,200)" to="(690,230)"/>
    <wire from="(690,200)" to="(710,200)"/>
    <wire from="(710,260)" to="(720,260)"/>
    <wire from="(720,230)" to="(720,260)"/>
    <wire from="(720,230)" to="(730,230)"/>
    <wire from="(730,210)" to="(730,230)"/>
  </circuit>
</project>

The solution, the header contains the github link to the logisim software. Downloaded the logisim-evolution-3.8.0-all.jar file and runned it locally. And Opened the beep1.circ file in the software and loaded the flag.enc file in the ROM. And started the simmulation then the flag is displayed in the TTY.

Flag: UMDCTF{w3lc0me_t0_l0g1s1m_yeet}

clutter

clutter

The challenge has two files clutter.vsp and a pdf about the installation of VeSP software.

The clutter.vsp is

2000
0000
2001
0000
2001
0003
2000
0052
0000
315B
0000
2001
0008
2000
0045
0000
3285
0000
...
..
and upto 215 lines

Solution,

Installed and started the VeSP

mj0ln1r@AHLinux:~/clutter$ wget https://user.eng.umd.edu/\~yavuz/teaching/courses/enee350/vesp-source-code/vesp1.1X/main.cpp -o vesp1_1.cpp
mj0ln1r@AHLinux:~/clutter$ cpp vesp1_1.cpp -o vesp1_1
mj0ln1r@AHLinux:~/clutter$ ls
vesp1_1
mj0ln1r@AHLinux:~/clutter$ ./vesp1_1
Welcome to Vesp 1.1


Type 
 0 to enter a program
 1 to display registers
 2 to display memory: 

Okay, I followed the instructions and loaded the clutter.vsp file in the vesp1_1 program. After running the program with long trace(in verbose mode). I found some memory storage locations in every instruction execution like this Memory[0001] = 000A. After observing all the same memory location values I got to know that flag characters are stored in memory locations other than 0000 and 0001. I couldn't found any way to store the output of the program to a file so I wrote this automated script using pwntools. Cool, Right!

solve.py

from pwn import *
import re

target = process("vesp/vesp1_1")

target.recv()
target.sendline(b"0")
target.sendline(b"002")
target.sendline(b"1")
target.sendline(b"clutter/clutter.vsp")
target.sendline(b"0")
target.sendline(b"1")

output = target.recvuntil(b"The number of clock cycles used = 396").decode('utf-8')

regex = "Memory\[\w+\] = .{4}"

match = re.findall(regex,output)
for i in match:
    if ("0000" not in i) and ("0001" not in i):
        x = i[15:]
        di = int(x,16)
        print(chr(di),end="")

# UMDCTF{Ux13-us3-m3m0ry-w1p3!}

Flag: UMDCTF{Ux13-us3-m3m0ry-w1p3!}


Forensics

Fire Type Pokemons Only

firetype

Attached file : fire-type-pokemon-only.pcapng.zip

Without opening the pcap file I know that I had to look for FTP packets in the file. So I extracted the zip and opened the pcap file in wireshark.

Solution

  • Opened the pcap in wireshark
  • Filtered FTP packets in wireshark
  • Followed the TCP stream of FTP data
  • Found a password piku
  • Some Images are transfered over network

So, I just exported the FTP-DATA saved the files. The files are Diglett.png , secretpic1.png, hmmmm and secret.zip

The zip is password protected, I used piku as the password for the zip. A video file is extracted, the flag is diplayed in the video.

firetype

Flag : UMDCTF{its_n0t_p1kachu!!}

No. 352

352

A hide-n-seek.jpg file is attached

Used Steghide immediately

  • First password kecleon (from google search)
  • Second password timetofindwhatkecleonishiding
mj0ln1r@AHLinux:~/no352$ steghide extract -sf hide-n-seek.jpg
Enter passphrase : kecleon
extracted data kecleon.jpg
mj0ln1r@AHLinux:~/no352$ steghide extract -sf kecleon.jpg
Enter passphrase : timetofindwhatkecleonishiding
extracted data wrote to flag.txt
mj0ln1r@AHLinux:~/no352$ cat flag.txt
UMDCTF{KECLE0NNNNN}

Flag : UMDCTF{KECLE0NNNNN}

Mirror Unknown

mirror

The attached image is

mirror1

Solution,

Did a reverse image search on google images. And found the letters associated with the symbols.

Image reverse search result

The Alphabets associated with symbols are - HOJNISSNIUR

Reversed the letters as the challenge says it mirror - SINJOHRUINS

Found that Sinjoh ruins is a place, It might be the correct flag and it is.

Flag : UMDCTF{SINJOHRUINS}


OSINT

Gone Missing 1

gone1

The link attached hosted this location image

Again did a reverse image search search

Image reverse search result

Found that it is Royal Palace, Oslo

Selected the Royal palace in the map given at the bottom right corner, got the flag.

Flag : UMDCTF{I_b3t_rainbolt_c0uld_g3t_th1s_!n_thr33_s3c0nd5}


Web

Treps Ticket System

tts

The attached URL hosted a form like this,

tts1

Inputed the Test creds name = test email = test@gmail.com

It loaded a ticket with the URL https://tts.chall.lol/ticket?num=12

tts2

Tried IDOR in the URL. changed the num=0 and recieved the flag.

Flag : UMDCTF{d0nt_b3_@n_id0r_@lw@ys_s3cur3_ur_tick3ts}