Hey everyone! In the previous blog (part 2 of the “Intro to Software Reverse Engineering”), we covered a walk-through of a challenge from crackmes.one. We’ll be continuing our series on software reverse engineering with a walkthrough of another challenge from crackmes.one.
The description of this challenge is as follows:
Guess the password without brute-forcing. No obvious strings in the file either.
We’ll use OllyDBG again for reversing this x86 binary. This one is relatively more challenging and contains an anti-reversing technique which we will have to bypass.
We’ll start as usual by running the executable binary.
The application seems to ask for a password, performs a check for the correct password and if incorrect, prints an incorrect message along with a number of tries counter.
We’ll load up the binary in OllyDBG and start by searching for all referenced strings.
We don’t see any familiar strings. They seem to be encrypted somewhere. For now, we’ll step over each instruction till we find the instruction where the program accepts our input password string and set a breakpoint there.
Navigate to Debug > Restart and press F9 to run the program till our software breakpoint. Step into the function with F7 and then keep stepping over instructions.
We can see a fgets call which reads the user input. Set a new breakpoint here. Observe the call instruction at address 004028E1, which we will step into.
Once inside the function, take note of the instruction at 0040154C which call the time function, which in C returns the time as seconds elapsed since midnight, January 1, 1970, or -1 in the case of an error. This is effectively a timestamp. This value is returned to EAX register and then assigned to a variable at instruction 00401556. On moving forward, we can notice a loop starting at address 00401590.
On going through the instructions and observing the stack, this seems to be an xor encryption routine performed on our input string. The xor key is moved byte by byte to EAX register at instruction 00401590. Each character of our input string is xored with a new key byte each time. (We’ll come back to this xor key again later). Also note that the EBX register counts the number of characters in our input string (“test123” in this case).
The following screenshot is the stack at the beginning of the loop at the call to strlen function.
The following screenshot is the stack towards the end of the loop at the call to strlen function.
Once we are out of the loop, notice the instruction at 004015C7, which calls the time function again, compares it with our previous timestamp and if the difference is more than 5, terminate the program. This is a common anti-debugging trick employed by software to make reverse engineering more difficult.
If we continue stepping over, the jump instruction at address 004015D0 causes a jump to address 004015E0, which eventually terminates the program. One method to bypass this check is to patch the jump instruction by right clicking the instruction and navigating to Binary > Fill with NOPs.
The assembly code should now look similar to the below screenshot. We have modified the instructions and now, the flow of code will be the same irrespective of the time difference.
Once we come out of the function, keep stepping over until instruction 0040291A.
The EDX register contains the length of our input string. It is being compared with 15 (which is 21 in decimal). We can infer that the actual password should be 21 characters long. If it does not match, the incorrect message gets printed and the program loops again and asks us for the input once more. Let’s now enter a 21-character string and keep on following the instruction until we reach the xor loop. From our observation earlier, each byte of the key is moved to EAX register at address 00401590. We’ll 00401595 and resume the program till we reach the address 00401595.
When the breakpoint is reached, observe the current value of EAX register.
Even more importantly, the data is moved to EAX register as seen in the instruction.
MOVZX EAX,BYTE PTR SS:[ESP+EDI+29]
The data in EDI register is 00000000 and that of ESP register is 0060FD80.
EDI register is incremented in each run of the loop.
We can examine the address [ESP+EDI+29] in the stack and the consecutive values (In little endian order) to figure out the key.
This xor encryption key is in fact the same data that’s pushed into memory just before the start of the xor loop, as seen in the screenshot below (from address 0040154E to 00401584).
Since we already know that the password length is 21 characters, we can extract the same number of xor key bytes sarting from the memory address [ESP+EDI+29] which equals 0060FDA9.
XOR KEY 6138686632333866676E657274323361736574686E
Once we have the xor key, we can now proceed with the program execution till the password validity check takes place, which is at address 00402928. This is a loop which compares our input string which was xor encrypted earlier, and the actual encrypted password one character at a time. If any character does not match, the instruction at address 00402935 sets EDX to 1 and the incorrect message gets printed.
If we inspect the registers now, we can see that EAX is now 0.
Thus, we need to observe address 0060FE46 (0060FDE0+0+66), which contains the encrypted password.
Encrypted Password 024A0905595E5D1549010B173D4167091627111B1A
Now that we have obtained both the key as well as the encrypted string, we just need to decrypt the string by xoring them again. An online tool can be used to perform this operation.
We found the decrypted password, which is “crackmes.oneIsTheBest”
We can test this out by running the application again on a new terminal.
In this blog, we came across a common time-based anti-reversing technique, learned how to patch binaries on the fly, and successfully found the password required by the binary application. Stay tuned for more blogs and walkthroughs in our ” Intro to Software Reverse Engineering” series.
By partnering with Redfox Security, you’ll get the best security and technical skills required to execute an effective and thorough penetration test. Our offensive security experts have years of experience assisting organizations in protecting their digital assets through penetration testing services. To schedule a call with one of our technical specialists, call 1-800-917-0850 now.
Redfox Security is a diverse network of expert security consultants with a global mindset and a collaborative culture. With a combination of data-driven, research-based, and manual testing methodologies, we proudly deliver robust security solutions.
“Join us on our journey of growth and development by signing up for our comprehensive courses, if you want to excel in the field of cybersecurity.”