PicoCTF 2025 Reverse Engineering—Perplexed Writeup

Back again with another writeup. This time, I’m breaking down Perplexed, a Reverse Engineering challenge from picoCTF. It’s one of those puzzles that look simple on the surface but demand a sharp eye and solid fundamentals in binary analysis. I’ll walk through how I approached the challenge, what stood out, and the techniques I used to get to the flag. If you’re into reverse engineering or just looking to sharpen your skills, this one’s worth dissecting.

At first, the lack of a description or hint made me think this would be a tough one—something along the lines of Homeworkarrow-up-right. But surprisingly, it turned out to be much more straightforward than expected. Let's get started!

Let's execute the code first to see its behavior

It's simply asking for the password, nothing more. We didn't gather enough information by running the binary, so let's open up Ghidra to dive deeper and analyze what's going on underneath.

After decompiling, this is the main function

This main function initializes a 256-byte buffer, prompts the user to enter a password, and reads the input using fgets. It then passes the input to a function called check, and based on the result, prints either "Correct!! :D" if the password is valid or "Wrong :(" if it's not. The return value reflects whether the correct password was entered.

Let's visit the check function

The function clearly enforces that the password must be exactly 27 characters long—if not, it immediately exits without doing any further validation. The local_58 array acts like a reference pattern, and each bit of the input is compared against it through a series of bit-level operations. This is essentially a custom verification mechanism that checks the input against a hidden "bitmask hash." If even a single bit doesn't align during the comparison, the function returns early, marking the input as incorrect.

Rather than analyzing the exact bit logic in depth, a more practical route was attempted: starting with a test string that followed the picoCTF{...} format and padding the rest with filler characters like 'A'. Observing how far the check progressed gave hints that some parts were correct. From there, a brute-force approach was taken—testing characters one by one and monitoring if the function moved on to the next comparison byte—eventually reconstructing the full flag by confirming each correct character incrementally.

To solve the challenge, we can brute-force the correct password one character at a time by exploiting how the check() function compares each bit of the input against a hardcoded reference array. Since the function checks bit-by-bit and stops at the first mismatch, we can modify or replicate the function to track how many characters have been successfully matched before a failure occurs. By testing each possible printable character at each position and observing which one allows the function to progress further, we can gradually reconstruct the entire 27-character password.

I implemented the solution using the C.

Compile then execute and it will give us the flag!

We've successfully solved Perplexed!!

Last updated