Sitemap
Ciphernom@d04

Ciphernom@d04

Crackme’s Lantern01

3 min readOct 10, 2026

--

OBJECTIVE OF CHALLENGE

The objective of this challenge was to understand how a program validates a password and recover the correct password by analyzing its compiled binary.

As a beginner in reverse engineering, I used Binary Ninja to inspect the program, follow the execution flow, understand the validation function, and investigate how XOR was used to hide the expected password.

INITIAL RECONNAISSANCE

I started by exploring the binary in Binary Ninja to understand how the password validation worked.

My first approach was to look for the strcmp function. I thought the program might directly compare the password entered by the user with a hardcoded string. However, I did not find anything particularly interesting there, so I decided to investigate further.

Next, I searched for the string "PASSWORD". This led me to the main() function, where I noticed the following logic:

if (!sub_140001000(&var_98))
puts("Incorrect password. Try again.");
else

This was an important clue. The program was calling sub_140001000() to validate the password. If the function returned false, the program displayed an incorrect-password message.

Naturally, I navigated to sub_140001000() to understand how the validation worked.

Inside the function, I noticed that the program was performing an XOR operation on the input characters before comparing them with values stored in memory. This suggested that the expected password was not being compared directly, but was instead being checked using a simple transformation.

Since I was still learning reverse engineering, I used AI to help me understand the XOR operation and the logic behind the function. I used it as a learning aid to understand what I was looking at, rather than simply treating the result as a solution.

METHODOLOGY / IDENTIFYING CORE VULNERABILITY

After examining the validation function, I identified three important details:

  • The password had to be exactly 13 characters long.
  • Each input character was XORed with the hexadecimal value 0x37.
  • The transformed characters were compared with bytes stored at data_140018320.

The relevant comparison looked like this:

if ((arg1[i] ^ 0x37) != data_140018320[i])
break;

This explained why searching for a direct password comparison had not revealed the answer. The program transformed each character before comparing it with the stored data.

Understanding the XOR operation

XOR is reversible. If a value is XORed with a key, applying XOR with the same key again recovers the original value.

Get Ciphernom@d04’s stories in your inbox

Join Medium for free to get updates from this writer.

Therefore, I could reverse the password transformation by XORing the stored bytes with 0x37.

Inspecting the memory

The decompiler initially showed this declaration:

char const data_140018320[0x6] = "TXGGRE";

At first, this gave me only six visible characters, while the validation function required 13 characters. I needed to investigate the surrounding memory to understand where the remaining values might be located.

I navigated to 0x140018320 in Binary Ninja and inspected the bytes in the Hex Editor. The dump showed the following sequence at the beginning of the memory region:

54 58 47 47 52 45 1A 58 40 5B 1A 03 05

The first six bytes represented TXGGRE, and the seven following bytes were present in the same memory dump. This gave me 13 bytes to investigate.

Because the declared array was only six bytes long, I also needed to consider whether the comparison intentionally accessed the additional bytes or whether the decompiler’s interpretation of the data was incomplete.

Recovering the Password

After identifying the XOR operation and extracting the 13 bytes from memory, I understood that I needed to XOR each byte with 0x37 to recover the original characters.

Since I was still a beginner and wanted to understand the result, I used AI to perform the XOR calculations on the extracted bytes and explain how the transformation could be reversed.

The recovered bytes were converted back into characters and combined in their original order, producing the candidate password:

copper-owl-42

The result contained 13 characters, matching the length required by the validation function. This helped me understand how XOR-based obfuscation works and how memory inspection can reveal data that is not immediately visible in a binary.

Press enter or click to view image in full size

CONCLUSION

As a beginner, I learned that when a password is not directly visible in a binary, examining the validation logic and the data it references can reveal how the password is stored or transformed. AI also helped me understand the unfamiliar parts of the code while I worked through the analysis myself.

--

--