$ cat writeup.md…
$ cat writeup.md…
avitoctf
Task: A static honeycomb game exposes fixed coordinates, reward bytes, and its decoder in a public JavaScript asset. Solution: Reproduce the coordinate mixing and xorshift32 XOR routine locally, decode all levels, and concatenate their rewards.
А вот кстати и первый самый лёгкий флаг — до него можно дошагать несколькими способами.
The target presents a honeycomb browser game. The apparent goal is to finish its levels, but the real objective is to inspect the client-side implementation and recover the reward generated for each level.
Requesting the HTTP URL returns a 303 redirect to HTTPS. The HTTPS root is a static page that loads /assets/firststeps.js. There are no API calls or server-side game-completion endpoints involved in producing the reward.
The standard discovery file is also a dead end:
User-agent: * Disallow: /
Thus, robots.txt neither discloses the reward nor points to a hidden endpoint. Its blanket disallow rule does not prevent direct inspection of the JavaScript asset.
The served source contains everything required to reproduce the reward calculation:
LEVEL_ORDER fixes the processing order as easy, medium, then hard.LEVEL_REWARD_LENGTHS gives the number of characters produced for each level.LEVEL_REWARD_DATA stores the encoded reward bytes.levelReward(level) implements the complete decoder.For a selected level, levelReward() starts with a 32-bit state derived from fixed constants, the level index, and the board dimensions. It then mixes every hole's linear cell index into that state with Math.imul() and an 11-bit rotation.
For each output character, the function advances a xorshift32 generator using shifts of 13, 17, and 5 bits. It selects the level's lane from the interleaved reward array and XORs that byte with the low byte of the updated state. JavaScript's unsigned >>> 0 behavior must be retained so that every operation remains within 32 bits.
The game eventually calls the same public function after marking levels complete. Because its inputs and algorithm are already available to the browser, reproducing the function locally gives exactly the same result without playing the game.
/assets/firststeps.js asset.levelReward() into a standalone Node.js script.LEVEL_ORDER.avito{...} format.The complete, verified solver is preserved as tasks/avitoctf/pervye_shagi/solve.js. It mirrors the served function directly, including Math.imul(), rotations, xorshift32 updates, lane selection, and unsigned coercions.
Run it from the task directory:
node solve.js
Verification output:
avito{REDACTED}
robots.txt enumeration: the file contains only a blanket disallow directive and no useful path.$ cat /etc/motd
Liked this one?
Pro unlocks every writeup, every flag, and API access. $9/mo.
$ cat pricing.md$ grep --similar