Introduction

This write-up takes you through how I solved two challenges at Apoorv CTF. Both the challenges were cryptography

Genjutsu Labyrinth (crypto)

Genjutsu Labyrinth was a grid-based puzzle where I had to move from the top-left corner to the bottom-right using XOR operations. I could only move down (S) or right (D), and my goal was to optimize the final XOR value.

I just used the same control order till I hit the point and there was the flag.

Flag: apoorvctf{G3NJUTSU_M4ST3R}

Kowareta Cipher (crypto)

For this one, we had to connect to chals1.apoorvctf.xyz on port 4001. It wanted a hex input and returned ciphertext. My teammate had started solving it, and I jumped in to tweak and improve the script.

Here’s the updated script:

                        
                        from pwn import * 
                    import time
                
                BLOCK_SIZE = 64
                known_flag = b""
                
                def recover_flag_byte(i):
                pad_length = BLOCK_SIZE - (i + 1)
                prefix = b"A" * pad_length
                
                p = remote("chals1.apoorvctf.xyz", 4001)
                
                try:
                p.recvuntil(b"Enter your input: ")
                print(f"Recovering byte {i + 1}/{BLOCK_SIZE}...")
                
                p.sendline(prefix.hex().encode())
                p.recvuntil(b"Ciphertext: ")
                ciphertext_ref = bytes.fromhex(p.recvline().strip().decode())
                
                for b in range(256):
                test_input = prefix + known_flag + bytes([b])
                p.sendline(test_input.hex().encode())
                p.recvuntil(b"Ciphertext: ")
                ciphertext_test = bytes.fromhex(p.recvline().strip().decode())
                
                if ciphertext_test[:BLOCK_SIZE] == ciphertext_ref[:BLOCK_SIZE]:
                print(f"Recovered: {known_flag.decode(errors='ignore')} + {chr(b)}")
                return bytes([b])
                
                return None
                except EOFError:
                print("Connection dropped. Retrying...")
                return None
                finally:
                p.close()
                
                for i in range(BLOCK_SIZE):
                while True:
                byte = recover_flag_byte(i)
                if byte:
                known_flag += byte
                break
                else:
                time.sleep(2)
                
                print("\nRecovered Flag:", known_flag.decode(errors="ignore"))
                        
                    

Boom! The script successfully recovered the flag:

Flag: apoorvctf{3cb_345y_crypt0_br43k}