Crackme Writeup 1
Vasa's Very Easy CrackMe
Vasa's Very Easy CrackMe is a beginner-friendly reverse engineering challenge. Written in C/C++ for the Windows x86-64 platform with a difficulty rating of 1.4, this should be fairly easy and give insight on how to navigate compiled code, understand program logic, and potentially bypass simple checks. Typically, the program asks for a password, and your task is to either find the correct password by analysing the code or modify the program to accept any password (by patching or injecting code).
For this challenge, I will be using x64dbg, an efficient, lightweight reverse engineering tool with powerful features. Since the challenge is designed for the x86-64 platform, I will be using the x64 version. First, we need to find the entry point of the executable. We can do this by selecting the "Break at Entry" option from the Debug menu (Debug > Break at Entry). x64dbg will pause at the entry point before executing any code. It uses typical prologue instructions (push rbp), (mov rbp, rsp), which are common at the start of functions, especially for main or initializer functions.
We can now examine the instructions using the available graph in x64dbg. Graph is an important tool to help visualize the control flow of a function or block of code. In the disassembly view, right-click on the code area and select Graph View from the context menu.
By examining the instruction we can deduct that the program requires a username and password from the user, concatenate both input which are then checked against some condition we do not understand yet. A deeper dive through the block of instructions and we can get a better understanding.

We spot an interesting value 0x32446B666A7830 being moved into the rax register. The value is 8 bytes long and is stored in little-endian format, meaning the bytes are reversed. When reversed, it becomes 30 78 6A 66 6B 44 32. Interpreting this as an ASCII string, it translates to 0xjfkD2. This is likely a hardcoded password that will be used for comparison later in the program.
This section begins by calling puts to prompt the user for a username. The address of the buffer for storing the username at [rbp-30] (30 is hexadecimal, meaning the username is located 48 bytes below the base pointer) is then loaded into rdx . Next, the address of a format string at 7FF7A06C4011, used for reading input, is loaded into rcx. A function call is then made to crackme.7FF7A06C2600, which appears to handle reading the username input from the user. By double-clicking on this line in x64dbg, we can examine the function to confirm its purpose. This process is repeated to prompt for and read the password input from the user.
Function call at address 7FF7A06C2600 includes two standard library function calls, __acrt_iob_func and __stdio_common_vfscanf. The first function, __acrt_iob_func, accesses standard input/output streams such as stdin, stdout, and stderr. The second function, __stdio_common_vfscanf, handles formatted input operations, similar to scanf or fscanf, for reading data from these streams. Both functions are part of the C runtime library, with __stdio_common_vfscanf specifically managing formatted input from standard input .

By inspecting the rdx register we can see the hardcoded password (0xjfkD2) in clear text .
The instructions set here loads the address of the username, stored at [rbp-30] (48 bytes below the base pointer), into the rdx register. It then loads the address of a destination buffer, located at [rbp-70] (112 bytes below the base pointer), into the rax register. The value of rax is moved into the rcx register. Finally, the strcpy function is called, which copies the username from the location pointed to by rdx (the source) into the buffer pointed to by rcx (the destination).
This section loads the address of the hardcoded password buffer, located at [rbp-8], into the rdx register, loads the address of the user-entered username buffer, located at [rbp-70], into the rax register, moves the address in rax into the rcx register to prepare for the function call, and finally calls the strcat function to concatenate the username (pointed to by rcx) to the hardcoded password (pointed to by rdx).

As we proceed further into the instructions, we observe that the username entered by the user and the stored password have been concatenated and are now present in the rax register.
The subsequent block of instructions is responsible for comparing the user-input password with the hardcoded password using the strcmp function. The address of the user-input password located at [rbp-70] is loaded into the rdx register, while the address of the hardcoded password, located at [rbp-50], is loaded into the rax register.
A check is performed to determine if the result of the comparison is zero by executing the instruction test eax, eax. This operation examines the Zero Flag (ZF) in the CPU's flags register, indicating that the strings match if the flag is set. If the strings do not match, the program will jump to display a failure message.
Now that we understand how the program works and know the password, we can enter any username of our choice followed by the string we found in the rax register (0xjfkD2) to bypass the password check.
We can simply enter our username, and then use our username combined with the password we found earlier as the password to successfully complete the challenge. But wait, is there another way to complete this challenge? I'm glad you asked!
We can simply modify the instruction jne crackme.7FF7A06C14FD to je crackme.7FF7A06C14FD. By changing the instruction to je (Jump if Equal), the logic is reversed. Now, if the two strings are equal, it jumps to crackme.7FF7A06C14FD. If they are not equal, it will continue to the next instruction without jumping.
With this modification, the patched version of the executable bypasses the string comparison entirely, allowing the user to enter any value without performing a validation check.
We have successfully bypassed the password check and can now enter any password of our choice. This marks the completion of this crackme challenge. I hope the process was not overwhelming and that you found the information useful. Now, the real question is how do you uncover a password if it is encoded or encrypted? Welcome to the world of obfuscation!

Last updated
