Added writeups
This commit is contained in:
102
reversible_logic.md
Normal file
102
reversible_logic.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# 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}`
|
||||
|
||||
```
|
||||
Reference in New Issue
Block a user