Skip to main content
The Wide challenge is a simple reverse-engineering task. The description says: We’ve received reports that Draeger stashed a huge arsenal in the pocket dimension Flaggle Alpha. You managed to smuggle a discarded access terminal for the Widely Inflated Dimension Editor out of his headquarters, but the entry for the dimension is encrypted. Can you get in and take control? You get two files: db.exe and wide. I usually start with the file command to see what I’m dealing with.

Inspecting the files

As we can see the wide file is a linux binary and the db.exe is a data file. So lets try to read the content of db.exe

Inspecting db.ex

Looks like nothing special. Next, let’s see which strings the wide binary contains.

Inspecting wide (strings)

Looks like a little game - let’s try running it.

Running the binary

So, interesting… the Flaggle Alpha entry shows an encrypted field. I tried a random key and got the “Key was incorrect” message. Maybe we can decrypt that and get the flag. Time to fire up Ghidra and take a look at the decompiled binary.

Static analysis (Ghidra)

Ghidra.png After decompiling with Ghidra we get the following code. Let’s walk through it.

main() overview

At first glance, main expects two arguments. If db.ex isn’t passed it exits. The program prints the welcome messages, reads the database into memory, closes the file, displays the entries, and then calls a function called menu. Let’s check out menu.

menu() and entry parsing

Ghidra2.png
Niceeee :D this shows how the program handles encrypted entries. There’s a hardcoded decryption key: sup3rs3cr3tw1d3. If you enter that key, the program reveals the flag:
Easy, right? Truth is, lots of binaries contain hardcoded credentials which can make reversing quick. Let’s dig deeper and extract the flag without running the original binary. If you look closer, the following snippet contains the relevant logic:
The program reads input from stdin and compares it to the hardcoded key. If they match, it proceeds. You might wonder why the code checks for iVar1 == 0 - in C, wcscmp returns 0 when the strings are equal.
Return value of wcscmp Negative value if lhs appears before rhs in lexicographical order. Zero if lhs and rhs compare equal. Positive value if lhs appears after rhs in lexicographical order.
Now let’s reverse the loop. I’ll simplify the variable names because the decompiler’s names are slop.
  • Replace the local_1d4 variable with a simple i variable
  • The hexvalue 0x80 means 128 in decimal
  • (*(char *)((long)&local_98 + (long)(int)i) accesses the byte at position i starting from local_98. Although it looks complicated, it’s equivalent to local_98[i], which is why we can treat local_98 as a character array (or buffer).
So the loop condition can be rewritten as:
Now let’s rewrite the loop body to make the character logic obvious.
  • Replace local_1d4 with i.
  • Replace (byte *)((long)&local_98 + i) with local_98[i].
  • Convert 0x1b to 27 and 0xff to 255.
  • The expression (i * 27) + ((i * 27) / 255) calculates a key based on the current index.
  • ^ is the XOR operator, so each byte in local_98 is XORed with this key, decrypting (or encrypting) the string.
So the decrypted loop looks like this:

Decrypting the flag with custom C code

What we can do now is write a small C program that reproduces the decryption routine and extracts the flag without executing the original binary. Since we already understand the XOR algorithm, the only remaining task is to figure out what data is stored inside the local_98 buffer. local_98 is the buffer that gets decrypted by the following loop:
The loop itself does not generate any data, it only transforms the bytes that are already present in local_98. This means that the encrypted flag must be loaded into this buffer before the decryption happens. Looking further up in the function, we can see that local_98 is filled from data copied from param_1:
These assignments reconstruct a 128-byte buffer. The values come from the selected entry in the database. To understand where this data originates, we need to look at the main() function. There we find:
The program reads a database file into memory. Each entry has a fixed size of 0xb4 bytes (180 bytes). The structure of an entry can be reconstructed as:
The last 128 bytes are the data that eventually become local_98. So rather than running the original binary, we can read the database file, pull out the 128-byte field, run the XOR routine ourselves, and recover the plaintext flag. Once we know the correct key and the decryption algorithm, the check becomes irrelevant. We can bypass the program logic completely and reproduce only the interesting part: extracting the encrypted bytes and decrypting them ourselves.
Save the code snippet code.c to a file and compile it with gcc code.c -o decrypter . Now if we run the custom c code, we will get the flag

Conclusion

This was a compact exercise in static analysis and reproducing a decryption routine. By inspecting the binary we found a hardcoded key and the XOR-based transformation, then recreated that logic in a tiny C program to extract the flag without running the original executable. It’s a good reminder: embedding secrets in binaries makes them trivial to recover, avoid hardcoding keys and prefer proper secret management.