# Reversible Logic `Reversible Logic` is a cryptography challenge based on the properties of the XOR operation. We are provided with a service that encrypts our input using a hidden flag as the key. ## Information Gathering We connect to the challenge service and are greeted with a prompt: ``` --- Secure XOR Encryption Service --- Enter a message to encrypt: ``` The description states: "This program implements a simple XOR cipher using a hidden flag as the key." Let's test it by sending a simple input, like "AAAA": ``` Enter a message to encrypt: AAAA Encrypted Result (Hex): 3a272d20 ``` ## Vulnerability Analysis The service implements a standard XOR cipher where: $$Ciphertext = Plaintext \oplus Key$$ We control the **Plaintext** (our input) and we receive the **Ciphertext** (the hex output). The **Key** is the hidden flag we want to recover. A fundamental property of the XOR operation is that it is its own inverse (reversible): $$A \oplus B = C \implies C \oplus B = A$$ Therefore, we can recover the Key by XORing the Ciphertext with our Known Plaintext: $$Key = Ciphertext \oplus Plaintext$$ To recover the full flag, we just need to send a plaintext that is at least as long as the flag. Since we don't know the exact length, sending a long string (e.g., 100 characters) ensures we cover it entirely. ## Solution We can automate this process with a Python script: 1. Connect to the server. 2. Send a long string of known characters (e.g., 100 'A's). 3. Receive the hex-encoded ciphertext. 4. Decode the hex and XOR it with our string of 'A's to reveal the flag. ### Solver Script ```python from pwn import * # Set the log level so we can see the "Opening connection" messages context.log_level = 'info' def main(): # 1. Connect to the challenge instance # (Matches the IP/Port from your previous message) io = remote('127.0.0.1', 1315) # 2. Handle the server prompts # We read until the server asks for input io.recvuntil(b"Enter a message to encrypt: ") # 3. Send our "Known Plaintext" # We send a long string of 'A's (0x41) to ensure we capture the full flag. # If the flag is longer than 100 chars, just increase this number. plaintext = b"A" * 100 io.sendline(plaintext) # 4. Receive the response io.recvuntil(b"Encrypted Result (Hex): ") # Read the hex string line and strip whitespace/newlines hex_output = io.recvline().strip().decode() log.info(f"Received Hex Ciphertext: {hex_output}") # 5. Decode the Hex cipher_bytes = bytes.fromhex(hex_output) # 6. XOR to recover the key # pwntools has a built-in xor() function that is very robust. # Logic: Key = Cipher ^ Plaintext recovered_key = xor(cipher_bytes, plaintext) # 7. Output the Flag # We use 'errors=ignore' just in case of weird bytes, # but for a text flag it should be clean. log.success(f"Recovered Flag: {recovered_key.decode('utf-8', errors='ignore')}") io.close() if __name__ == "__main__": main() ``` ### Execution Running the logic manually or via script reveals the flag. `{flag: xor_logic_is_reversible_123}` ```