Black Box Hunter
Black Box Hunter
Platform: CUSTOM | Category: Reversing | Type: Challenge | Difficulty: Medium | OS: N/A | **Author: XESXOR Techniques: bytecode_reverse_engineering, deterministic_optimization, pickle_deserialization, pyc_disassembly
Summary
Walkthrough of the CUSTOM Reversing Black Box Hunter. Task: Reverse engineer Python 3.12 .pyc and pickle files to understand black box reward function. Solution: Extract optima and state sequence from pickle, reconstruct Gaussian reward formula from byte
Description
"Нравятся черные ящики? Засунь туда что-нибудь и получи награду." (Like black boxes? Shove something in and get a reward.)
Given archive source.tar.gz with files:
baseline.py— baseline hunter implementationblack_box.pkl— pickle withSecretBlackBoxobjectblack_box_core.pyc— compiled Python 3.12 bytecode
Server accepts CSV with parameters, calculates total reward over 500 steps. Threshold: reward > 1500.
Analysis
1. Examining baseline.py
python read-only • copy alloweddef load_black_box(): # Loads pickle and pyc with open('black_box.pkl', 'rb') as f: box = pickle.load(f) # Loads black_box_core from .pyc ...
Interface: black box accepts 3 parameters in range [-5, 5], returns reward.
2. Analyzing pickle file
Loading with stub class to extract attributes:
python read-only • copy allowedclass SecretBlackBox: pass with open('black_box.pkl', 'rb') as f: box = pickle.load(f) print(box.__dict__)
Extracted parameters:
n_states = 5— number of stateschange_interval = 37— state change intervalnoise_level = 0.1— noise leveloptima— 5x3 array with optimal coordinates for each statesigmas— 5x3 array with variancesseed— seed for deterministic noisestate_sequence— array of 1000 elements with state sequence
Optima:
State 0: [3.035, 3.777, -0.672]
State 1: [-2.600, -1.448, 3.385]
State 2: [-0.619, -1.718, -3.066]
State 3: [-1.279, -3.460, 2.111]
State 4: [-3.382, 3.386, 1.431]
3. Reverse Engineering .pyc (Python 3.12)
uncompyle6 doesn't support Python 3.12. Used Docker:
bash read-only • copy alloweddocker run -it --rm -v $(pwd):/work python:3.12 python3 -c " import dis, marshal with open('/work/black_box_core.pyc', 'rb') as f: f.read(16) # skip header code = marshal.load(f) dis.dis(code) "
Reconstructed code:
python read-only • copy alloweddef black_box_core(params, hidden_state): params = np.asarray(params).flatten() n_states, change_interval, noise_level, optima, sigmas, call_count, seed, state_sequence = hidden_state # Determine current state if call_count < len(state_sequence): current_state = state_sequence[call_count] else: current_state = 0 # Gaussian reward: maximum 10.0 when params == optima[current_state] diff = params - optima[current_state] weighted = np.sum((diff / sigmas[current_state]) ** 2) result = 10.0 * np.exp(-0.5 * weighted) # Deterministic noise rng = np.random.RandomState((seed + call_count + 1000) % 4294967296) noisy = result + rng.normal(0, noise_level) call_count += 1 new_state = (n_states, change_interval, noise_level, optima, sigmas, call_count, seed, state_sequence) return (noisy, new_state)
Key insight: Reward is a Gaussian function with maximum 10.0 at point optima[current_state]. State is determined by state_sequence[call_count].
Solution
1. Generating optimal CSV
Knowing state_sequence and optima, for each step we select the exact optimum:
python read-only • copy allowed#!/usr/bin/env python3 import pickle import numpy as np class SecretBlackBox: pass with open('black_box.pkl', 'rb') as f: box = pickle.load(f) optima = box.optima state_sequence = box.state_sequence # Generate CSV for 500 steps with open('submission_optimal.csv', 'w') as f: f.write('step,param1,param2,param3\n') for step in range(500): state = state_sequence[step] opt = optima[state] f.write(f'{step},{opt[0]},{opt[1]},{opt[2]}\n')
2. Local verification
bash read-only • copy alloweddocker run -it --rm -v $(pwd):/work python:3.12 python3 /work/verify.py # Total reward: 4995.83
3. Submitting to server
bash read-only • copy allowedcurl -X POST http://HOST:PORT/check -F "file=@submission_optimal.csv"
Response: MIPT{REDACTED}
Key Takeaways / Lessons
- Mastering bytecode_reverse_engineering, deterministic_optimization, pickle_deserialization, pyc_disassembly was key to this challenge.
- Always check for common misconfigurations and verify assumptions.
Crafted by XESXOR Research • 2026-03-14 • CUSTOM • Black Box Hunter • Difficulty: Medium