$cat esotera.mdMiscHacknite 2.0
Esotera
A file that looks empty is a program written only in spaces, tabs and line breaks. It prints a second program, which prints a third, which prints the flag.
$man esotera
What this one teaches:
- Spotting invisible characters in a file that looks empty.
- What esoteric programming languages are, and how to recognise Whitespace, Brainfuck and Malbolge.
- Solving in layers. When a program prints another program, run that one too.
$hint --one-at-a-time
Stuck? Open one hint, then go back and try again before reading the next.
Hint 1 of 3show
The file isn't empty. Check its size, or open it in an editor that can show spaces and tabs.
Hint 2 of 3show
The task's name is a pun. Search for "esoteric programming languages".
Hint 3 of 3show
The first program's output is another program, in a different language. Keep going until something looks like a flag.
Task description
Ivica tells me this is the source code of his program. To me it looks like there’s nothing here, let alone code.
The original was in Croatian; this is my translation.
A file that looks empty
The task comes with ezoterija.txt. Opened in a text editor, it shows a blank page. But the file is 22,788 bytes, and blank files don’t weigh anything. Counting the characters inside gives:
| Character | Count |
|---|---|
| Space | 11,799 |
| Tab | 7,948 |
| Line break | 3,041 |
There is nothing else in the file, and all three are invisible, which is why the page looks empty. Most code editors can show them: in VS Code turn on View → Appearance → Render Whitespace, and in Notepad++ use View → Show Symbol → Show All Characters.
The task’s name points at what this is. Ezoterija is Croatian for esotericism, and esoteric programming languages are languages made as jokes, puzzles or experiments, never meant for real work. One of them is called Whitespace. Its programs are written using only spaces, tabs and line breaks, which is exactly what this file contains.
Layer 1: Whitespace
Here is the start of the file with the invisible characters written out, the usual way Whitespace code is shown: S for a space, T for a tab and L for a line break (line feed).
SSSSTSTSTTL
TL
SSSSSSTSTSTTL
TL
Whitespace reads the characters in small groups, each forming one instruction. The first few mean:
| Characters | Meaning |
|---|---|
SS |
Put a number on the stack (the program’s scratch pile of numbers). |
S |
The number is positive. |
STSTSTT |
The number in binary, with S as 0 and T as 1: 0101011, which is 43. |
L |
End of the number. |
TLSS |
Print the top number on the stack as a character. |
Every character on a computer has a number, and 43 is the number for +. The whole file is that same pair of instructions repeated 1,519 times: put a number on the stack, then print it. So it prints 1,519 characters.
You don’t need to decode it by hand. Paste the file into an online interpreter such as dcode’s Whitespace tool and run it. The output is one long line that starts like this:
++++[++++>---<]>+.[-->+<]>+++++.-[--->+<]>--.
Layer 2: Brainfuck
A line made only of + - < > [ ] . is another well-known esoteric language, Brainfuck. It works on a long row of memory cells, each holding a number, and it has eight one-character commands:
| Command | What it does |
|---|---|
> < |
Move one cell right or left. |
+ - |
Add or subtract 1 in the current cell. |
[ ] |
Repeat the commands between them until the current cell is 0. |
. |
Print the current cell as a character. |
, |
Read a character of input (this program doesn’t use it). |
The loops are a compact way to multiply. The first 18 commands, ++++[++++>---<]>+., leave the number 68 in a cell and print it, and 68 is the code for D. The rest of the program works the same way, one character at a time.
Run it in dcode’s Brainfuck interpreter. The output is shorter, and it looks like random punctuation:
D'`$#p8![54Fix65R@2>qp_'&+k6YEgf|{@c?a<N)sxwYutslqpi/gOedibaf_%cbDC_^W\UyYXWV
(That’s the first part of it; the full output continues in the same style.)
Layer 3: Malbolge
This last layer is Malbolge, an esoteric language from 1998 named after the eighth circle of hell in Dante’s Inferno. It was designed to be as hard to program in as possible. What an instruction does depends on where it sits in memory as well as on its character, and each instruction scrambles itself after it runs. Its programs are almost always generated by tools rather than written by people, which is why they look like noise.
Running it is still easy. Paste the text into dcode’s Malbolge interpreter, and this time the output is a short line in the CTF2021[...] format. That’s the flag.
If you’d rather not paste task files into a website, small open-source interpreters exist for all three languages, and they can be chained so each one’s output feeds into the next.
$cat flag.txt reveal
CTF2021[682388997751]