Tags: misc 

Rating: 5.0

cheater mind

Category: misc
Solves: 4
Points: 997
Author: deuterium

Hey, I dont want you to win. Mind if i cheat a little bit?

nc misc.zh3r0.cf 1111

Download - cheater_mind.tar.gz

Overview

We just have to win 6 rounds of Mastermind, with a small twist.

Basically there's some secret string we have to guess. After each guess, the server will reply with just two numbers:

  1. Number of correct chars in the correct position
  2. Number of correct chars in the wrong position (the server will tamper with this value to make life harder for us)

If we exceed the maximum number of guesses, then we lose.

from random import randint, random
from collections import Counter


class Agent:
    def __init__(self, N, K, mutation, guess_limit):
        self.N = N
        self.K = K
        self.mutation = mutation
        self.guess_limit = guess_limit
        self.secret = [randint(1, N) for i in range(K)]
        print(f"secret = {self.secret}")

    def play(self, guess):
        if guess == self.secret:
            return self.K, 0

        # This is where the server tampers with the values
        mutated = [
            i if random() > self.mutation else randint(1, self.N) for i in self.secret
        ]

        bulls = sum(a == b for a, b in zip(mutated, guess))
        cows = Counter(mutated) & Counter(guess)
        return bulls, sum(cows.values()) - bulls

    def game(self):
        try:
            for guess_no in range(self.guess_limit):
                guess = list(
                    map(
                        int,
                        input("enter your guess as space separated integers:\n")
                        .strip()
                        .split(),
                    )
                )
                bulls, cows = self.play(guess)
                print(bulls, cows)
                if bulls == self.K:
                    return True
            return False
        except:
            print("Error, exiting")
            exit(1)


# N, K, mutation, guess_limit
# First three rounds are just normal Mastermind games.
# Last three rounds have a small probability of mutation, providing unreliable
# feedback.
LEVELS = [
    [6, 6, 0, 7],
    [8, 6, 0, 8],
    [8, 8, 0, 9],
    [6, 6, 0.05, 10],
    [8, 6, 0.05, 11],
    [6, 6, 0.1, 12],
]

print(
    """Can you beat me at mastermind when I am not so honest?
      https://en.wikipedia.org/wiki/Mastermind_(board_game)"""
)

for level, (N, K, mutation, guess_limit) in enumerate(LEVELS, start=1):
    print(
        "Level {}, N={}, K={}, mutation={}, guess limit={}".format(
            level, N, K, mutation, guess_limit
        )
    )
    if Agent(N, K, mutation, guess_limit).game():
        print("level passed, good job")
    else:
        print("You noob, try again")
        exit(1)


from secret import flag
print("you earned it :", flag)

Solution

Short version

  1. Find this paper: Efficient solutions for Mastermind using genetic algorithms (maybe a genetic algorithm can handle the unreliable feedback?)
  2. Find this implementation: https://github.com/dogatuncay/mastermind
  3. Patch it to interact with the server (Elixir is hard ?)
  4. Tweak the parameters and evolution loop to handle unreliable feedback better
  5. Win rate: 0.8% (each attempt takes about 1 minute)
  6. Start 10 looped instances in parallel
  7. Take a 2 hour nap
  8. Wake up and get the flag

Long version

See the next section

Patch for Mastermind solver: cheat_mind.patch
Pwntools wrapper script: client.py

Output:

[+] Opening connection to misc.zh3r0.cf on port 1111: Done
[DEBUG] Received 0xce bytes:
    b'Can you beat me at mastermind when I am not so honest?\n'
    b'      https://en.wikipedia.org/wiki/Mastermind_(board_game)\n'
    b'Level 1, N=6, K=6, mutation=0, guess limit=7\n'
    b'enter your guess as space separated integers:\n'
[*] Level 1, N=6, K=6, mutation=0.0, guess limit=7
[+] Starting local process '/bin/sh' argv='timeout 45 mix run_genetic_algorithm 6 6 0.0 7' : pid 547096
[DEBUG] Received 0x4b bytes:
    b'Genetic Algorithm guesses : [3, 1, 2, 4, 6, 2]\n'
...
    b'Genetic Algorithm guesses : [5, 4, 1, 1, 1, 5]\n'
    b'I guess:\n'
    b'[5, 4, 1, 1, 1, 5]\n'
    b'Enter move results:\n'
[DEBUG] Sent 0xc bytes:
    b'5 4 1 1 1 5\n'
[DEBUG] Received 0x63 bytes:
    b'6 0\n'
    b'level passed, good job\n'
    b'you earned it : zh3r0{wh3n_3asy_g4m3s_b3come_unnecessarily_challenging}\n'
[*] Beat level 6

Note: The author's solution was to encode it as a maxSAT instance: authors_solution.py

Timeline

  • Saturday 09:45 PM - 11:00 PM

  • Saturday 11:00 PM - 11:50 PM

    • Try a bunch of shitty Mastermind solvers from GitHub
    • Find this implementation that actually works: https://github.com/dogatuncay/mastermind
  • Saturday 11:50 PM - Sunday 01:00 AM

    • Modify the genetic algorithm to play interactively
    • Fix bug that makes it get stuck in an infinite loop
  • Sunday 01:00 AM - 01:30 AM

    • Write Python wrapper to interact with the challenge server and Mastermind solver
    • Test results:
Level 1: 6 x 6, 0.00% mutation,  7 guesses : Solves within 30 seconds
Level 2: 8 x 6, 0.00% mutation,  8 guesses : Solves within 45 seconds
Level 3: 8 x 8, 0.00% mutation,  9 guesses : Solves within 2 minutes
Level 4: 6 x 6, 0.05% mutation, 10 guesses : Often gets trapped in infinite loop
Level 5: 8 x 6, 0.05% mutation, 11 guesses : Often gets trapped in infinite loop
Level 6: 6 x 6, 0.10% mutation, 12 guesses : Often gets trapped in infinite loop
  • Sunday 01:30 AM - 03:20 AM

    • Tweak genetic algorithm until it can solve levels with unreliable feedback with about 20% of winning, so it has an 0.8% chance of solving the last three levels in succession. Good enough.
  • Sunday 03:20 AM - 04:20 AM

    • Modify script to handle failures and run continuously
    • Deploy 10 instances and pray that one of them will pass all six levels
  • Sunday 04:20 AM - 06:10 AM

    • Sleep
  • Sunday 06:10 AM (20 min before CTF ends)

    • Check progress on solvers
    • Turns out 3 instances passed all six levels ?
    • Submit flag
Original writeup (https://github.com/qxxxb/ctf/tree/master/2021/zh3r0_ctf/cheater_mind).