Post

QLotto

HackTheBox QLotto machine writeup — reconnaissance and enumeration walkthrough.

QLotto

Challenge Information

  • Name: QLotto
  • Category: Quantum
  • Difficulty: Easy
  • Host: 83.136.252.32:31179

Challenge Description

“They call it QLotto — a dazzling new quantum lottery table provided by Qubitrix that lauders millions at the casino, where quantum draws decide your fate. If you can predict their draws, you can beat the system and clean out their coffers. Rig the jackpot, Operative. Every stolen coin funds their empire — and every coin you steal funds our fight.”

Initial Reconnaissance

Analyzing the Provided Files

The challenge provides a single file: server.py. Let’s examine its contents:

1
cat server.py

The server implements a quantum lottery system using Qiskit (IBM’s quantum computing framework). Key observations:

  1. Quantum Circuit: Uses 2 qubits (indices 0 and 1)
  2. Initial State: Qubit 0 starts in superposition via circuit.h(0)
  3. User Input: Players provide quantum gate instructions
  4. Measurement: Both qubits are measured 36 times
  5. Number Generation: 6 lottery numbers are extracted from the measurements

Understanding the Code Flow

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def generate_circuit(self, instructions: str):
    circuit = QuantumCircuit(2)
    circuit.h(0)  # Qubit 0 in superposition
    
    instructions = instructions.split(";")
    for instr in instructions:
        parts = instr.split(":")
        gate, params = parts
        params = [ int(p) for p in params.split(",") ]
        
        # CRITICAL VALIDATION
        if any(p == 0 for p in params):
            print("[Dealer] Hey, don't tamper with the house card — that's forbidden.")
            return None

Key Restriction: The validation if any(p == 0 for p in params) prevents us from using index 0 in our gate parameters.

Available Gates

Single-qubit gates (1 parameter):

  • H - Hadamard gate
  • S - Phase gate
  • T - T gate
  • Z - Pauli-Z gate

Two-qubit gates (3 parameters: angle, qubit1, qubit2):

  • RXX - Ising XX coupling gate
  • RYY - Ising YY coupling gate
  • RZZ - Ising ZZ coupling gate

Understanding the Lottery Mechanism

1
2
3
4
5
6
7
8
9
10
11
12
13
def extract_numbers(self, memory):
    for i in range(0, len(memory), 6):
        bits = memory[i : i + 6]  # 6 measurements
        
        lotto_number = ""
        testing_number = ""
        
        for testing_bit, lotto_bit in bits:
            lotto_number += str(lotto_bit)      # From qubit 0
            testing_number += str(testing_bit)  # From qubit 1
        
        lotto_number = int(lotto_number, 2) % 42 + 1
        testing_number = int(testing_number, 2) % 42 + 1

Important Details:

  • Each measurement produces a 2-bit string (e.g., “01”)
  • In Qiskit’s bit ordering: rightmost bit = qubit 0, leftmost bit = qubit 1
  • testing_numbers come from qubit 1 (shown to player)
  • lotto_numbers come from qubit 0 (hidden, must be guessed)
  • 6 bits are combined to form each number: int(binary, 2) % 42 + 1

Win Condition Analysis

1
2
3
4
5
6
7
8
9
if lotto_numbers == testing_numbers:
    print("[Dealer] Trying to mirror the house's numbers, are we?")
    return

print(f"[Dealer] Your draws are: {testing_numbers}")
guess_numbers = input("[Dealer] Place your six bets on the table : ")

if guess_numbers == lotto_numbers:
    print(f"[Dealer] Your jackpot: {JACKPOT}")

Requirements:

  1. lotto_numbers must NOT equal testing_numbers (anti-mirror check)
  2. We see testing_numbers after circuit execution
  3. We must predict lotto_numbers to win

The Problem

We face a paradox:

  • Qubit 0 (lottery) and Qubit 1 (testing) are independent by default
  • We cannot use index 0 in our gate parameters
  • We need to correlate the qubits to predict lottery numbers
  • With only 2 qubits, any two-qubit gate must involve qubit 0
  • But we can’t reference qubit 0… or can we?

🔒

Premium Content

The full exploitation walkthrough, privilege escalation, and flags are available exclusively for members.

Unlock Full Writeup →
This post is licensed under CC BY 4.0 by the author.