Files
HIP7CTF_Writeups/reversible_logic.md
m0rph3us1987 a79656b647 Added writeups
2026-03-08 12:22:39 +01:00

103 lines
3.1 KiB
Markdown

# 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}`
```