team-logo
Published on

BITSCTF 2025 - REV challenges

Authors

Introduction

We solved 4 out of 5 tasks.

Table of contents

Baby rev

baby rev

Writeup author: Cappybara

Followed it in debugger or solution below:

Solution:

import zlib
import base64
import re

def unpack_data(encoded_data):
    return zlib.decompress(base64.b64decode(encoded_data[::-1]))



#x-iteration ...

data=b'==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'

while True:
    try:
        # Rozpakowanie danych
        data = unpack_data(data)
        decoded_data = data.decode('utf-8')
        print(decoded_data)
        print()
        

        # Wyszukiwanie wyrażenia `exec((_)(b'...'))` i wyodrębnianie zakodowanych danych
        match = re.search(r"exec\(\(_\)\(b'(.*?)'\)\)", decoded_data)
        if match:
            # Wyodrębnianie zakodowanych danych
            encoded_part = match.group(1)
            data = encoded_part.encode('utf-8')
        else:
            print("Nie znaleziono więcej zakodowanych danych.")
            break

    except Exception as e:
        # Przerwanie pętli, jeśli nie można już rozpakować
        print(f"Nie udało się rozpakować: {e}")
        break

Flag: BITSCTF{obfuscation_and_then_some_more_obfuscation_4a4a4a4a}

Loginator

Loginator

Writeup author: Cappybara

Solution:

#!/usr/bin/env python3
import subprocess

def uruchom_program(nazwa_programu, argument):
    try:
        wynik = subprocess.run(
            [nazwa_programu, argument],
            capture_output=True,  
            text=True,           
            check=True            
        )
        return wynik.stdout, wynik.stderr
    except subprocess.CalledProcessError as e:
        # W przypadku błędu możemy przechwycić stdout i stderr
        return e.stdout, e.stderr

if __name__ == '__main__':
    wynik = "02 92 a8 06 77 a8 32 3f 15 68 c9 77 de 86 99 7d 08 60 8e 64 77 be ba 74 26 96 e7 4e"
    poczatek = "BITSCTF{"
    
    for i in range(20):
        for char in range(32,127):
            nazwa_programu = "./loginator.out"
            argument = poczatek + chr(char)
            stdout, stderr = uruchom_program(nazwa_programu, argument)
            #print(argument, stdout)
            #print(stdout)
            if stdout.strip() in wynik:
                poczatek+=chr(char)
                break
        print(poczatek)

Flag: BITSCTF{C4ND4C3_L0G1C_W0RK?}

Praise Our RNG gods

alt text

Writeup author: clev1L

Solution:

import random
from randcrack import RandCrack
from tqdm import tqdm
rc = RandCrack()

def fun(data,i):
    ret=(data//2969596945)//((i ^ 195894762) ^ 322420958)
    return ret
from pwn import *
p=remote("chals.bitskrieg.in",7007)
for i in tqdm(range(624)):
    p.recvuntil("> ")
    p.sendline("0")
    p.recvuntil("are ")
    data=int(p.recvuntil(" away").decode().replace(" away","").strip())
    initdata=fun(data,i+1)
    rc.submit(initdata)

ret=(rc.predict_getrandbits(32) * ((625 ^ 195894762) ^ 322420958)) * 2969596945
p.recvuntil("> ")
p.sendline(str(ret))
print(p.recv())
print(p.recv())
print(p.recv())
print(p.recv())
print(p.recv())

Flag: BITSCTF{V4u1t_cr4ck1ng_w45_345y_0384934}

Appreciation of Art

Appreciation of Art

Writeup author: kerszi

Here, we got the first blood. alt text The solution turned out to be easy, but few teams solved it. It was enough to dump the memory from the debugger. However, I think the correct solution is different.
# gdb ./a.art
pwndbg> start
pwndbg> vmmap
pwndbg> r

Interrupt program (Ctrl+c)

What is the name of the character hiding in this binary (lowercase with underscores if needed): ^C
Program received signal SIGINT, Interrupt.

Check address of memory

pwndbg> vmmap
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
             Start                End Perm     Size Offset File
          0x400000           0x401000 r--p     1000      0 /mnt/d/moje_programy/CTF/ctftime/2025-bitskrieg/rev-Appreciation of Art/a.art
          0x401000           0x442000 r-xp    41000   1000 /mnt/d/moje_programy/CTF/ctftime/2025-bitskrieg/rev-Appreciation of Art/a.art
          0x442000          0x4443000 rw-p  4001000  42000 /mnt/d/moje_programy/CTF/ctftime/2025-bitskrieg/rev-Appreciation of Art/a.art
    0x7ffff7ff9000     0x7ffff7ffd000 r--p     4000      0 [vvar]
    0x7ffff7ffd000     0x7ffff7fff000 r-xp     2000      0 [vdso]
    0x7ffffffde000     0x7ffffffff000 rw-p    21000      0 [stack]

Dump memory:

pwndbg> dump memory pie.dmp 0x442000 0x4443000
Search 'B' in notepad... And later copy and strip. alt text

Flag: BITSCTF{1_l0v3_0bfu5c4t1ng_thi1ng5_r4nd0mly_0e54826a}