Task of the Ancient Rus
Task of the Ancient Rus
Platform: CUSTOM | Category: Reversing | Type: Challenge | Difficulty: Medium | OS: N/A | **Author: XESXOR Techniques: transform_inversion, archive_password_recovery, trailer_carving, red_herring_elimination, binary_diffing, slack_space_decoding
Summary
Walkthrough of the CUSTOM Reversing Task of the Ancient Rus. Task: a multi-stage archive challenge mixes an AES-encrypted ZIP, fake ancient-style C source, a decoy assembly file, an MP3 with an appended clue, and a modified NASM executable. Solution: invert the
Description
Задание древних Русов
English summary: the archive contains several layers of misdirection: obfuscated fake-C code, an AES-encrypted ZIP, a decoy assembly file, an MP3 with hidden trailing data, and a modified nasm.exe. The goal is to separate real clues from red herrings and recover the final CODEBY{...} flag.
Analysis
Challenge Summary
This is a multi-stage reverse challenge built around progressive clue validation. The real path is:
- reverse the fake C checker to recover the password for
flag.zip, - ignore the decoy
flag.asm, - inspect the MP3 trailer for a plaintext hint,
- compare the bundled
nasm.exewith the official NASM release, - decode the altered bytes hidden in PE slack space.
Reconnaissance
The initial ZIP contained:
flag.zipancientslavic.hnot_important.cИз архива истории.mp3
Early file triage showed that flag.zip was AES-encrypted, so the most likely starting point was the nearby source code.
ancientslavic.h defines Russian/Cyrillic macros and exposes a 32-byte constant array through бронь1..бронь32. not_important.c uses those macros to disguise a simple byte-by-byte checker.
Solution
Step 1: Reverse the fake C checker and recover the ZIP password
The checker reads user input, transforms each byte, and compares the result to the hardcoded array прав.
The effective forward transform for byte x at position i is:
text read-only • copy allowedx ^= 3 x += 7 x += 7 x -= 9 x ^= 9 x += i x ^= i x ^= i x ^= prev prev = x
The two consecutive x ^= i operations cancel out, but they are still present in the source and help sell the obfuscation.
The exact reference array is:
python read-only • copy allowedcorrect = [ 0x71,0x33,0x4d,0x65,0x11,0x27,0xa2,0xee, 0x9e,0xf2,0xc9,0xa3,0xd7,0x55,0x32,0x43, 0x3b,0x56,0x06,0x87,0xe0,0x9b,0xf9,0x86, 0xdf,0x47,0xc1,0xb5,0xef,0x7f,0xff,0xd9, ]
Reversing the transform yields the original password bytes:
python read-only • copy allowed#!/usr/bin/env python3 correct = [0x71,0x33,0x4d,0x65,0x11,0x27,0xa2,0xee,0x9e,0xf2,0xc9,0xa3,0xd7,0x55,0x32,0x43,0x3b,0x56,0x06,0x87,0xe0,0x9b,0xf9,0x86,0xdf,0x47,0xc1,0xb5,0xef,0x7f,0xff,0xd9] prev = 0 out = [] for i, c in enumerate(correct): t = c ^ prev t = (t - i) & 0xff t = t ^ 9 orig = ((t - 5) & 0xff) ^ 3 out.append(orig) prev = c print(bytes(out))
Output:
text read-only • copy allowedb'p@s$w0rD_f0R_tHe_S1aViC_@rcH1ve\n'
The trailing newline comes from fgets, so the actual ZIP password is:
text read-only • copy allowedp@s$w0rD_f0R_tHe_S1aViC_@rcH1ve
Step 2: Extract the nested archive
Use the recovered password to unpack flag.zip:
bash read-only • copy allowed7z x -y -p'p@s$w0rD_f0R_tHe_S1aViC_@rcH1ve' flag.zip
This extracts:
flag.asmnasm.exeФрагмент летописи.txt
Step 3: Confirm that flag.asm is a decoy
Reading flag.asm and concatenating the mov al, <num> immediates produces:
text read-only • copy allowedTh1S_1S_n0T_@_fl@G
So flag.asm is explicitly a red herring. It is worth checking because it looks like a classic assembly-encoded flag, but the recovered string directly tells us not to trust it.
Step 4: Inspect the MP3 and recover the hidden clue from the trailer
The MP3 does not contain the final flag directly.
exiftoolonly shows theme-like metadata.ffmpeg/ffprobeshow that the audio decodes, but the file ends with invalid trailing data.
That is the important clue: the audio itself is fine, but there is extra data appended after the legitimate MP3 stream.
Near the end of the file, at offset 436543 in a 436583-byte file, the last 40 appended bytes contain plaintext:
text read-only • copy allowedLook for ancientslavic.h on the Internet
This trailer clue explains the challenge design:
- the MP3 is not the flag container,
flag.asmis not the real payload,- the author wants the solver to stop chasing decoys and focus on the fake ancient-source theme and the hidden tooling logic around it.
Step 5: Compare nasm.exe with the official NASM build
The extracted nasm.exe is a PE32+ Windows console executable. It is clearly not a stock binary.
The reference build used for comparison was the official NASM 2.16.01 Windows x64 package:
text read-only • copy allowedhttps://www.nasm.us/pub/nasm/releasebuilds/2.16.01/win64/nasm-2.16.01-win64.zip
Hashes:
- local
nasm.exe:a5a61b4ab76b51acec376539364e7245a757607b2467d9ac56987de931c3d164 - official
nasm.exe:edd81d22451246758450f1d5bd7f4c64937ed6cee06f3c2bbbba82401b32c6d4
Only 65 bytes differ, all near raw offset 0x4ecb0 inside .data slack space. That is a classic sign of a minimally patched legitimate binary used as a hidden flag carrier.
Step 6: Decode the hidden blob from .data slack
The interesting region starts at 0x4ecb0 and contains this 37-byte blob:
text read-only • copy allowed413d44434227493f5eb09f0f633e542d544051392d6652103b2d3156125f541045525f644b
The decoding logic is simple:
python read-only • copy allowed#!/usr/bin/env python3 blob = bytes.fromhex( '413d44434227493f5eb09f0f633e542d544051392d6652103b2d3156125f541045525f644b' ) print(bytes((((b + 0x99) & 0xff) ^ 0x99) for b in blob))
Output:
text read-only • copy allowedCODEBY{REDACTED}
This is the real flag.
Key Takeaways / Lessons
- Mastering transform_inversion, archive_password_recovery, trailer_carving, red_herring_elimination, binary_diffing, slack_space_decoding was key to this challenge.
- Always check for common misconfigurations and verify assumptions.
Crafted by XESXOR Research • 2026-04-06 • CUSTOM • Task of the Ancient Rus • Difficulty: Medium