Field notes
Cyber Jawara Quals 2025 - Dior [836]
Reverse engineering a D language binary that encrypts a Dior challenge flag.

Challenge Overview
In this challenge, the description gave us a link to the D programming language download page and a zip file. After extracting the zip, there were two files: dior and flag.txt.dior.
Opening flag.txt.dior directly only showed unreadable bytes.
My first assumption was that dior was the program used to encrypt flag.txt. Running file confirmed that it was a 64-bit ELF executable, built from D and stripped.
Investigation and Discovery
I opened the binary in Ghidra and started from the entry point, then worked my way to the main function. The main routine showed a short pipeline: read the input, compress it, shuffle the bytes, XOR the result, create the output filename, and write the encrypted file.
Function breakdown:
-
FUN_00126450
Reads the input file into a 16-byte text/slice-like structure. It also checks the text encoding. If the input looks like UTF-16 or UTF-32, the program throws an exception instead of continuing. -
FUN_0014feb0
A wrapper around the compression step. From the D references and the surrounding calls, this lines up with zlib compression. -
FUN_001266c0
Shuffles the byte order inside the buffer using a PRNG-driven swap loop.
-
FUN_00126020
Encrypts the shuffled buffer with byte-by-byte XOR.
-
FUN_0014fec0
Copies data into a buffer and returns the slice used by the later pipeline. -
FUN_00126820
Builds the output filename. -
FUN_00126750
Writes the encrypted result to disk.
After reading the decompiler output, the encryption path became:
read file -> compress with zlib -> shuffle bytes -> XOR bytes -> write .dior file
So the decryptor needs to do the inverse:
read .dior file -> undo XOR -> undo shuffle -> decompress zlib -> recover plaintext
Decrypting the Message
Based on that pipeline, I wrote a solver that recreated the XOR stream, reversed the shuffle permutation, and then decompressed the result with zlib.
The important part is the order. Because the binary encrypts after shuffling, decryption must undo the XOR first. Only after the XOR layer is removed can the shuffled buffer be put back into its original order and decompressed.
# high-level solver flow
data = read_file("flag.txt.dior")
data = undo_xor(data)
data = undo_shuffle(data)
flag = zlib.decompress(data)
print(flag.decode())
The Flag
After running the solver, the flag from the notes was:
CJ{christian-dior-dior_1M-UP-IN-ALL-THE-5TORE5_rip-pop-smokeldc2 dior.d }
Resources
- D Programming Language Downloads
- std.algorithm.mutation - D Programming Language
- std.zlib - D Programming Language
- d - How do you skip a file’s BOM before parsing it? - Stack Overflow