# Bi0sCTF 2024

Only one challenge writeup this time, really tough multi-part questions and only had time to solve this one all the way through.

### A Block and a Hard Place (28 Solves)

#### Description:

Are you the Far Lands because you're a Maze? Or are you a Maze because you're the Far Lands?

#### Solution:

We're given only a server to netcat to and nothing else. Once connected, we can move with either wasd or WASD to jump over walls.

```
─$ nc 13.201.224.182 30961                                                                                    130 ⨯
Welcome to The Far Lands! You're free to explore. 
You can move around using wasd (lowercase). 
If you hit a wall, you can jump over them using WASD (uppercase). 
You can't jump if there's no wall in front of you. 
Lastly, you're placed in a random position in the maze. 
Do your best to figure out it's secrets!

2000> w
Moved!
1999> w
You can't move there!
1998> W
Jumped over a wall!
1997> w
Moved!
...
```

Once we get to the boundary (at the top when trying w/W), neither option will work. To map out the entire maze, I wrote the following to go to the upper left corner, and then zig-zag right and left through the maze.

```python
import socket
import time

HOST = '13.201.224.182'
PORT = 32127

# Create a socket, connect to the server, and return the socket
def create_socket_and_connect(host, port):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((host, port))
    return s

# Send a command to the server and return the response
def send_command(sock, command):
    ret = sock.recv(4096).decode('utf-8')
    sock.sendall(f"{command}\n".encode('utf-8'))
    ret = sock.recv(4096).decode('utf-8')
    #print(command, ret) # print out command outputs for debugging
    return ret

# Navigate to the upper-left corner of the maze
def navigate_to_upper_left_corner(sock):
    while True:
        response = send_command(sock, 'w')
        if "can't move there" in response:
            response = send_command(sock, 'W')
            if "can't move there" in response:
                break

    while True:
        response = send_command(sock, 'a')
        if "can't move there" in response:
            response = send_command(sock, 'A')
            if "can't move there" in response:
                break

# Move to the right until the boundary is hit
def explore_right(sock):
    row = []
    while True:
        response = send_command(sock, 'd')
        if "can't move there" in response:
            response = send_command(sock, 'D')
            if "can't move there" in response:
                break
            else:
                row.append("#")
        else:
            row.append(".")
    print(row)
    
# Move to the left until the boundary is hit
def explore_left(sock):
    row = []
    while True:
        response = send_command(sock, 'a')
        if "can't move there" in response:
            response = send_command(sock, 'A')
            if "can't move there" in response:
                break
            else:
                row.append("*")
        else:
            row.append(".")
    print(row)

def main():
    with create_socket_and_connect(HOST, PORT) as sock:
        # Receive and print the welcome message
        print(sock.recv(4096).decode('utf-8'))
        time.sleep(1)

        # Navigate to the upper-left corner of the maze
        navigate_to_upper_left_corner(sock)
        
        # Skip a few rows that had no walls, found earlier
        response = send_command(sock, 's')
        response = send_command(sock, 's')
        response = send_command(sock, 's')
        
        # Go down one, move to the right, go down one, move to the left
        while True:
            response = send_command(sock, 's')
            if "can't move there" in response:
                break
            explore_right(sock)
            response = send_command(sock, 's')
            if "can't move there" in response:
                break
            explore_left(sock)

if __name__ == "__main__":
    main()

```

This will print out the rows, with a # for if there was a wall. Since we're going backwards every other row, I have \* in the output to make a note to flip it. I did that by copy pasting the output to a text file, and in vim selecting the row (V) and then reversing it (:%!rev). Then find/replace \* with # and deleting all characters other than # and space. See the final output below.

```
. . . # . . . . . . # # . # # # # # . . # . . . # # . . . . . . # . . .
. . . # # . . . . # # # . # . # # . . . # . # . . # # . . . . # # . . .
. . . # # # . . # # # . # . # . # # . . . # # # # # # # . . # # # . . .
. . . # # # . . # # # . # # # . # . # # # . # . . # # # . . # # # . . .
. . . # # # . . # # # . . . . . . . . # # # . # . # # # . . # # # . . .
. . . # # . . . . # # # . . # # . # . # . # . . . # # . . . . # # . . .
. . . # . . . . . . # # # # # # # # # # # # # # # # . . . . . . # . . .
. . . . . . . . . . . # # . # # . . # . # . # . # . . . . . . . . . . .
. . . . . . # . # # # . # . . . # # . # # . # # . . . # . . # . # . . .
. . . # # # # . # # # . # # # # . # . . . . # . # . # . . # # . # . . .
. . . # # # . . . . # # . # # . . # # . . . . # # # . # # . . # # . . .
. . . # . . . # . . . . . # . # . . . . . . # . # . . # # # . . # . . .
. . . . # # . # # # . . # # # . # # # . # # # . # # # . # # # . . . . .
. . . # # . . # . # # # . . . # . . . # . # # . # . . . # . . . . . . .
. . . # # # . . . . # # . # # . . . . . # # . # . # # . . . . . . . . .
. . . # . # # . # . . # # . # # . # # . # . # . # . # . # . . . # . . .
. . . . . # # . # . # . . . # . # # # # . # # . . . . # . # # # # . . .
. . . # . # . # # . . # # . . # # . . . # . # . # . # # # # # # # . . .
. . . # . # . # . . # # # . # # . . # # . # . # # # . . # . . # . . . .
. . . # # . # . # . . . # # # # # # . # . . # # # # . . # # . # . . . .
. . . . # . . . . . . # . # # # . # # . # # # # . . . . # . . . . . . .
. . . . . . . . . . . . # . # # . # # . . # . # # . . # . # . # # . . .
. . . # . . . . . . # . # # . # . # . . # . . . # # # # # # . # . . . .
. . . # # . . . . # # . # . . # . . . . # # . # # . . # # # # # # . . .
. . . # # # . . # # # # . . . # # . # . # # . # . . . . # # # # # . . .
. . . # # # . . # # # # # # . . # # . . . . . # # # # # . # . . # . . .
. . . # # # . . # # # . # . # . . # . . # # # # . . # . # . . # . . . .
. . . # # . . . . # # . # # . # . . . . # . . # # . # . # # # . . . . .
. . . # . . . . . . # . . . . # . # # . . . . # . . . # . # # # . . . .

```

This looks like a QR code but not quite, and this is because this is just a representation of where the horizontal walls are. Picturing a black and white QR code, each horizontal wall should signify a switch from white to black, and vice versa. Therefore, every time a # is encountered, it's actually a toggle. The below code fixes this.

```python
def toggle_square_array(input_lines):
    # Initialize the output lines list
    transformed_lines = []

    # Process each input line
    for line in input_lines:
        current_char = '.'  # Start with '.' as the initial output character
        transformed_line = ""
        for char in line.split():  # Assuming characters are separated by spaces
            if char == '#':
                # Toggle the current character when a '#' is encountered
                current_char = '.' if current_char == '#' else '#'
            transformed_line += current_char + " "
        transformed_lines.append(transformed_line.strip())

    return transformed_lines

# Input lines
input_lines = [
    ". . . # . . . . . . # # . # # # # # . . # . . . # # . . . . . . # . . .",
    ". . . # # . . . . # # # . # . # # . . . # . # . . # # . . . . # # . . .",
    ". . . # # # . . # # # . # . # . # # . . . # # # # # # # . . # # # . . .",
    ". . . # # # . . # # # . # # # . # . # # # . # . . # # # . . # # # . . .",
    ". . . # # # . . # # # . . . . . . . . # # # . # . # # # . . # # # . . .",
    ". . . # # . . . . # # # . . # # . # . # . # . . . # # . . . . # # . . .",
    ". . . # . . . . . . # # # # # # # # # # # # # # # # . . . . . . # . . .",
    ". . . . . . . . . . . # # . # # . . # . # . # . # . . . . . . . . . . .",
    ". . . . . . # . # # # . # . . . # # . # # . # # . . . # . . # . # . . .",
    ". . . # # # # . # # # . # # # # . # . . . . # . # . # . . # # . # . . .",
    ". . . # # # . . . . # # . # # . . # # . . . . # # # . # # . . # # . . .",
    ". . . # . . . # . . . . . # . # . . . . . . # . # . . # # # . . # . . .",
    ". . . . # # . # # # . . # # # . # # # . # # # . # # # . # # # . . . . .",
    ". . . # # . . # . # # # . . . # . . . # . # # . # . . . # . . . . . . .",
    ". . . # # # . . . . # # . # # . . . . . # # . # . # # . . . . . . . . .",
    ". . . # . # # . # . . # # . # # . # # . # . # . # . # . # . . . # . . .",
    ". . . . . # # . # . # . . . # . # # # # . # # . . . . # . # # # # . . .",
    ". . . # . # . # # . . # # . . # # . . . # . # . # . # # # # # # # . . .",
    ". . . # . # . # . . # # # . # # . . # # . # . # # # . . # . . # . . . .",
    ". . . # # . # . # . . . # # # # # # . # . . # # # # . . # # . # . . . .",
    ". . . . # . . . . . . # . # # # . # # . # # # # . . . . # . . . . . . .",
    ". . . . . . . . . . . . # . # # . # # . . # . # # . . # . # . # # . . .",
    ". . . # . . . . . . # . # # . # . # . . # . . . # # # # # # . # . . . .",
    ". . . # # . . . . # # . # . . # . . . . # # . # # . . # # # # # # . . .",
    ". . . # # # . . # # # # . . . # # . # . # # . # . . . . # # # # # . . .",
    ". . . # # # . . # # # # # # . . # # . . . . . # # # # # . # . . # . . .",
    ". . . # # # . . # # # . # . # . . # . . # # # # . . # . # . . # . . . .",
    ". . . # # . . . . # # . # # . # . . . . # . . # # . # . # # # . . . . .",
    ". . . # . . . . . . # . . . . # . # # . . . . # . . . # . # # # . . . ."
]

# Transform the input
transformed_lines = toggle_square_array(input_lines)

# Print the transformed lines
for line in transformed_lines:
    print(line)
```

This gives us the fixed map, but it's in ASCII so one more program to convert it to a QR image.

```python
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image

# QR pattern from the previous code
qr_code_pattern = """
. . . # # # # # # # . # # . # . # . . . # # # # . # # # # # # # . . . .
. . . # . . . . . # . # # . . # . . . . # # . . . # . . . . . # . . . .
. . . # . # # # . # . . # # . . # . . . . # . # . # . # # # . # . . . .
. . . # . # # # . # . . # . # # . . # . # # . . . # . # # # . # . . . .
. . . # . # # # . # . . . . . . . . . # . # # . . # . # # # . # . . . .
. . . # . . . . . # . # # # . # # . . # # . . . . # . . . . . # . . . .
. . . # # # # # # # . # . # . # . # . # . # . # . # # # # # # # . . . .
. . . . . . . . . . . # . . # . . . # # . . # # . . . . . . . . . . . .
. . . . . . # # . # . . # # # # . # # . # # . # # # # . . . # # . . . .
. . . # . # . . # . # # . # . # # . . . . . # # . . # # # . # # . . . .
. . . # . # # # # # . # # . # # # . # # # # # . # . . # . . . # . . . .
. . . # # # # . . . . . . # # . . . . . . . # # . . . # . # # # . . . .
. . . . # . . # . # # # . # . . # . # # . # . . # . # # . # . . . . . .
. . . # . . . # # . # . . . . # # # # . . # . . # # # # . . . . . . . .
. . . # . # # # # # . # # . # # # # # # . # # . . # . . . . . . . . . .
. . . # # . # # . . . # . . # . . # . . # # . . # # . . # # # # . . . .
. . . . . # . . # # . . . . # # . # . # # . # # # # # . . # . # . . . .
. . . # # . . # . . . # . . . # . . . . # # . . # # . # . # . # . . . .
. . . # # . . # # # . # . . # . . . # . . # # . # . . . # # # . . . . .
. . . # . . # # . . . . # . # . # . . # # # . # . # # # . # # . . . . .
. . . . # # # # # # # . . # . # # . # # . # . # # # # # . . . . . . . .
. . . . . . . . . . . . # # . # # . # # # . . # . . . # # . . # . . . .
. . . # # # # # # # . . # . . # # . . . # # # # . # . # . # # . . . . .
. . . # . . . . . # . . # # # . . . . . # . . # . . . # . # . # . . . .
. . . # . # # # . # . # # # # . # # . . # . . # # # # # . # . # . . . .
. . . # . # # # . # . # . # # # . # # # # # # . # . # . . # # # . . . .
. . . # . # # # . # . . # # . . . # # # . # . # # # . . # # # . . . . .
. . . # . . . . . # . . # . . # # # # # . . . # . . # # . # . . . . . .
. . . # # # # # # # . . . . . # # . # # # # # . . . . # # . # . . . . .
"""

# Converting the QR code pattern into a binary matrix
pattern_lines = qr_code_pattern.strip().split("\n")
binary_matrix = [[0 if char == '#' else 1 for char in line.split()] for line in pattern_lines]

# Converting the binary matrix into an image
binary_matrix = np.array(binary_matrix, dtype=np.uint8) * 255  # Convert to 0 and 255
qr_image = Image.fromarray(binary_matrix, mode='L')  # 'L' mode for grayscale

# Display the generated QR code image
plt.imshow(qr_image, cmap='gray')
plt.axis('off')  # Hide axes
plt.show()

```

<figure><img src="/files/9K7rIG4wTsBeeviZaoYa" alt=""><figcaption></figcaption></figure>

Using a QR reader, we get the flag!

```
bi0sctf{Vkh5P76p4h8kemCI4TXOBw==}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ctf.krauq.com/bi0sctf-2024.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
