Description
A harder version of Virtual Machine 0. Instead of a simple two-gear system, this challenge hides a multi-stage bevel gear train inside a COLLADA (.dae) 3D model. Open the model in Blender, count the teeth on every gear in the train, compute the compound ratio, and submit the output rotation to a remote server to receive the flag.
Download and extract the challenge archive to get the .dae model file. Get the files from the challenge page on CyLab Security Academy (formerly play.picoctf.org).
Install Blender (free, from blender.org) to open the COLLADA model.
Connect to the remote server when you are ready to submit your answer.
unzip vm1# Open the .dae file in Blender: File -> Import -> Collada (.dae)nc <HOST_FROM_INSTANCE> <PORT_FROM_INSTANCE>Solution
Want to try it yourself first?
The guided walkthrough reveals hints one step at a time.
Step 1Open the model in Blender and expose the gear train
ObservationThe download is a COLLADA (.dae) model, so the puzzle lives in a mechanical assembly. Blender's COLLADA importer plus Edit Mode is the way to inspect it and count teeth.Import the .dae file into Blender. The scene contains a multi-stage bevel gear train surrounded by casing parts. Select and delete non-gear objects (the housing, axle shafts, decorative pieces) to reveal all gears clearly. You need to count the teeth on every gear in the chain from the red input axle to the blue output axle.bash# In Blender:bash# File -> Import -> Collada (.dae) -> select the model filebash# Click a housing object, press X -> Delete to remove itbash# Orbit the camera to inspect each gear stagebash# Count teeth by slowly rotating each gear in Edit ModeWhat didn't work first
Tried: Trying to read the gear tooth counts directly from the COLLADA XML with a text editor or grep instead of opening the model in Blender.
COLLADA stores raw vertex coordinates, not a tooth-count attribute. The file is thousands of floats with nothing marking where one tooth ends and the next begins. Edit Mode in Blender lets you orbit the rendered mesh and count peaks directly, which is the only practical route.
Tried: Using FreeCAD or another 3D viewer instead of Blender to inspect the model.
FreeCAD opens .dae files, but it often mishandles scenes with instanced objects and can collapse the whole gear train into one merged mesh, leaving no individual gears to identify. Blender's importer keeps the scene hierarchy, so you can isolate each object from the Outliner.
Learn more
COLLADA (.dae) is an XML-based 3D interchange format. Blender imports it via File -> Import -> Collada. The Virtual Machine 1 model is a Lego-style mechanical assembly with bevel gears at multiple stages, meaning gears whose axes are not parallel (bevel gears transfer rotation between shafts at an angle, like the gears in a car differential).
The gear ratio for each meshing pair is simply the tooth count of the driven gear divided by the tooth count of the driving gear. A compound gear train multiplies the ratios of every stage together. If stage 1 gives 7:1, stage 2 gives 191:1, and stage 3 gives 7:1, the total ratio is 7 x 191 x 7 = 9359. That means one full turn of the input axle produces 9359 full turns of the output axle.
Step 2Calculate the compound gear ratio
ObservationIn Blender the model turns out to hold several bevel stages, not one pair. Multiply the stage ratios together to get the compound ratio before you talk to the server.Walk every gear mesh from input to output and record the driven/driving tooth ratio at each stage. Multiply all the stage ratios together. For this challenge the gear train works out to a compound ratio of 9359.pythonpython3 - <<'PY' # Example of how to combine per-stage gear ratios: # Stage 1: driving gear has D1 teeth, driven gear has d1 teeth -> ratio = d1 / D1 # Repeat for every stage, then multiply all ratios. stages = [ (8, 56), # stage 1: 56-tooth driven by 8-tooth -> 7x (1, 191), # stage 2: 191-tooth driven by 1-tooth -> 191x (adjust to match your count) (8, 56), # stage 3: 56-tooth driven by 8-tooth -> 7x ] ratio = 1 for driving, driven in stages: ratio *= driven / driving print(f"Compound ratio: {ratio}") # should be 9359 PYExpected output
Compound ratio: 9359.0
What didn't work first
Tried: Dividing the driving tooth count by the driven tooth count instead of the other way around, producing a fractional ratio less than 1.
The ratio is driven over driving, output over input. More teeth on the driven gear means the output turns slower; fewer teeth means it turns faster. Flip the fraction and instead of 9359 you compute roughly 0.000107, which the server rejects.
Tried: Assuming the chain has only two gear stages because two gears are most visible after removing the housing.
This model is a three-stage compound train, and one intermediate stage hides behind the main bevel pair if the housing is only partly removed. Miss it and you multiply two ratios instead of three, landing on the wrong count. Move every non-gear object to a hidden collection and look from several angles before committing.
Learn more
The ratio of 9359 comes from a three-stage bevel gear train. Each bevel gear pair works the same way as a spur gear pair for counting purposes: divide the driven tooth count by the driving tooth count. The challenge authors chose numbers whose product (9359) is large enough that you cannot guess it but small enough to count by hand or with Blender's vertex inspector.
If your count differs from 9359, re-examine each stage. A common mistake is confusing which gear is driving and which is driven (the ratio inverts), or missing a stage hidden inside the housing. Move every non-gear object to a hidden collection in Blender so nothing obstructs your view.
Step 3Connect to the server and answer the rotation question
ObservationThe server asks how many times the output axle turns for a randomly chosen input count. Multiply whatever integer it gives you by the compound ratio of 9359.The remote server presents a large input rotation count and asks how many times the output axle will rotate. Multiply the input by the gear ratio (9359) and submit the result. The server validates the answer and prints the flag.bashnc <HOST_FROM_INSTANCE> <PORT_FROM_INSTANCE>bash# Server prompt example:bash# How many times does the output rotate if the input rotates 22039 times?bash# Answer: 22039 * 9359 = 206263001What didn't work first
Tried: Submitting the gear ratio itself (9359) as the answer instead of multiplying it by the server-provided input rotation count.
The server asks for output rotations given a specific input count, not for the ratio itself, and it picks a fresh random input every session. Submit 9359 on its own and it is wrong. Read the integer out of the prompt and multiply.
Tried: Hard-coding the example host and port (saturn.picoctf.net:<PORT_FROM_INSTANCE>) into the socket script instead of using the values from your own challenge instance.
picoCTF spins up per-team instances, so a host and port copied from anywhere else belong to someone else's session and are probably already closed. Take them from your own challenge panel and paste them into the command.
Learn more
The server generates a random input value each session, so you will not see 22039 every time. The computation is always the same:
output = input * 9359. The Python snippet below handles arbitrarily large numbers (picoCTF often uses big-integer inputs):import re import socket RATIO = 9359 HOST, PORT = "saturn.picoctf.net", 51650 # replace with your instance values with socket.create_connection((HOST, PORT)) as s: data = s.recv(4096).decode() print(data) # Pull the input rotation count out of the prompt: it is the only integer, # and it is not the last token (the line ends in "times?"). n = int(re.findall(r"\d+", data)[-1]) answer = str(n * RATIO) s.sendall((answer + "\n").encode()) print(s.recv(4096).decode())This challenge demonstrates that "reverse engineering" is not limited to binary analysis. Understanding the mechanism of a physical machine, whether real or simulated in a 3D model, is also reverse engineering. The gear train is the "program" and counting teeth is the "disassembly."
Interactive tools
- File Magic IdentifierIdentify file types from magic numbers. Paste hex bytes or drop a file to detect PNG, JPEG, ZIP, PDF, ELF, PCAP, SQLite, and dozens of other formats.
- Hex ViewerView text or raw hex bytes as a xxd-style hex dump with byte offset, hex columns, and ASCII sidebar. Highlights printable characters and null bytes.
- Strings ExtractorPull printable text from any binary, library, or image. ASCII and UTF-16 detection, configurable minimum length, flag-like highlight, no command line needed.
Flag
Reveal flag
picoCTF{m0r3_g34r5_3g4d_...}
The compound gear ratio is 9359. Multiply the server-provided input rotation count by 9359 and submit the result to receive the flag.