> For the complete documentation index, see [llms.txt](https://zwique.gitbook.io/zwique_notes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://zwique.gitbook.io/zwique_notes/writeups/random-ctf-writeup/local/the-first-half-reloaded.md).

# The First Half: Reloaded

## Problem

This code represents a challenge where the goal is to deduce a secret "flag" value using a partially leaking encryption process.

#### **The Encryption Process:**

1. **Flag Setup:**
   * A flag is fetched from the environment variable `flag`, defaulting to a placeholder value if not set.
   * The flag is stored as a byte-encoded string.
2. **Leak Function:**
   * The function `leak(i)` takes an index `i` and returns the XOR of the `i`-th byte of the flag with a randomly chosen byte from the string `MUSTCTF`.
3. **User Interaction:**
   * The program accepts user input `i` to specify the index of the flag byte to leak.
   * Leaks are restricted to the first half of the flag (`len(flag) // 2`).
4. **Termination:**
   * An unexpected input or exception breaks the loop, terminating the process.
5. **Remote Access:**
   * Players interact with the challenge through a remote service using the command:

     ```
     nc 139.162.5.230 10169
     ```

```python
import os

flag = os.environ.get('flag', 'MUSTCTF{fake_flag_for_testing}').encode()

def leak(i):
    from random import choice
    return flag[i] ^ choice(b'MUSTCTF')


while True:
    try:
        i = int(input('i = '))
        assert i < len(flag) // 2  # Sorry. Only first half is leaked
        print('Leak:', leak(i))
    except Exception:
        print('Unexpected error')
        break
```

## Solution

This Python script uses the **Pwntools** library to communicate with the remote server and deduce the flag:

1. **Setup:**
   * Establishes a remote connection to the provided address.
   * Initializes an empty `flag` array to store deduced bytes.
   * Defines `allowed_chars` as the byte string `b"MUSTCTF"`.
2. **Deduction Logic:**
   * A helper function `deduce_flag_byte` iterates over possible byte values (0–255) and determines which matches the leaked XORed values.
   * A byte is deemed correct if XORing it with each leaked value produces a valid character from `allowed_chars`.
3. **Leaking Flag Bytes:**
   * For each index in the last half of the flag (`-32` to `0`):
     * Sends the index to the remote service multiple times to gather leak values.
     * Uses `deduce_flag_byte` to find the actual flag byte.
     * Maps the deduced byte to the correct position in the `flag` array.
4. **Error Handling:**
   * Handles EOF errors gracefully, ensuring the connection is closed cleanly.
5. **Output:**
   * Prints the partially or fully reconstructed flag, replacing undeduced bytes with a `?`.

```python
from pwn import *

io = remote("139.162.5.230", 10169)

flag = [None] * 40

allowed_chars = b"MUSTCTF"

def deduce_flag_byte(leaks):
    for char in range(256):
        if all((char ^ leak) in allowed_chars for leak in leaks):
            return char
    return None

try:
    for i in range(-32, 0):
        leaks = []
        for _ in range(100):
            io.sendlineafter(b"i = ", str(i).encode())
            io.recvuntil(b"Leak: ")
            leak_value = int(io.recvline().strip())
            leaks.append(leak_value)

        flag_byte = deduce_flag_byte(leaks)
        
        positive_index = 32 + i
        
        if flag_byte is not None:
            flag[positive_index] = flag_byte
            print(f"Flag[{positive_index}] = {chr(flag[positive_index])}")
        else:
            print(f"Could not deduce Flag[{positive_index}]")

except EOFError:
    print("Connection closed by the server.")
finally:
    io.close()

print("Flag:", "".join(chr(c) if c else '?' for c in flag))
```
