Reversing.kr - Easy Crack
1. Context
I’ve been working at Union Pacific for the network design team, so I have not had much practice with reverse engineering lately.
Since FLARE-On 2020 from FireEye is coming next weekend, I figure that I should do some reversing this weekend to prepare for it.
I have picked Reversing.kr to practice mainly because they have a lot of good Windows challenges for me to do. I have been trying to find them in normal CTFs, but most of them only makes reversing challenges for Linux machine.
It’s not that I hate reversing in Linux, but reversing Windows application just feels nicer for some reason.
So here is my attempt at solving the first challenge called Easy Crack.
Note: I’ll use mainly IDA Free and Binary Ninja during these reversing posts because I am too poor for IDA Pro and its decompiler.
2. Easy Crack
First, I run the executable to see its main functionality.
It seems like the program creates a modal dialog box that takes in some input. Let’s try typing in something and hit the submit button.
So we know that we must enter a password. If the password is wrong, a popup will appear notifying us that it is wrong.
Let’s open it in IDA. We know that the program must call DialogBoxParam to create the dialog box.
If we look for it, in function sub_401000(which is a typical starting point for Windows executable), we can see the call to DialogBoxParam with the field lpDialogFunc being the function DialogFunc!
Therefore, we can assume that DialogFunc is the function that checks the validity of the password we type in. Let’s analyze it!
From here, we see that the branch loc_40105E will be the branch to end when the dialog box closes. We can assume that loc_401049 is the main functionality because it is making a call to another function sub_401080 passing in hDlg from the closest push.
We know that hDlg is the handle to the dialog box, so by passing this handle into the function, it’s possible that the function will call functions such as GetDlgItemTextA to get the password from the dialog box that we type in.
Let’s see what’s in sub_401080.
We do see a call to GetDlgItemTextA! It seems like the call looks like this in C++.
GetDlgItemTextA(hDlg, 0x3E8, String);
From this, we know that this call writes the item in the dialog text box into the variable String! If we look at the stack variables of this function, we has String, var63, var62, and var60.
These variables are suspiciously close to each other according to their offset. It seems like String is the beginning of the password string that is retrieved from GetDlgItemTextA. var63 is 1 byte down from String, so var63 must be String[1]. Likewise, var62 is String[2], and var60 is String[4].
Let’s just rename them and move on!
Next, we see a comparison. The byte at index 1 of String is being compared with 0x61(which is the character a in ASCII). If this byte is 0x61, we move on. Else, we print out the “Incorrect Password” prompt at the loc_401135 branch, so let’s rename this branch to incorrect_pass. So we know the second character in our password is a.
Here, we see our string being pushed as the parameter for the sub_401150 function with the string “5y”. If this function returns 0, we move on, else we go to incorrect_pass. Note: the return value for x86 function calls is stored in eax.
Let’s analyze sub_401150 to see what it does.
First, we move the String[2] pointer to edi, then we move the string “5y” to esi.
Then, we call repe cmpsb. repe means this call will happens while the bytes are still equal. cmpsb is a byte comparision of the current value pointed to by esi and edi.
Here is the full definition of cmpsb.
Compares byte at address DS:(E)SI with byte at address ES:(E)DI and sets the status flags accordingly
Basically, once this call finishes, edi points to the first character in String[2] that differs from the string “5y”, and the same is with esi.
Next, we check if the bytes before the current edi and esi are equal to each other. If they are equals, ecx remains 0, else ecx is changed.
Then, ecx is written into eax as the return value for the function.
To wrap it up, this function just checks if the 2 bytes String[2] and String[3] are equal to “5y”. If they are, return 0, else return some other non-zero value!.
Since we want this to return 0, we must have these two characters from our password to be 5y.
Here is what our password looks like so far (* means wildcard).
*a5y
Let’s move on!
First, we see that the string “R3versing” is passed into esi, and the pointer String[4] is passed into eax. My assumption is that this is just a string comparison loop, but let’s walk through the assembly code to see what it is!
At the beginning of the loop, the bytes at both the pointers are passed into edx and ebx and compared. If they are not equal, we branch to loc_401102. This branch basically just loads 0xFFFFFFFF into eax.
Notice that this branch and loc_4010FE both branches into loc_401107, and loc_401107 checks if eax is 0. If eax is 0, we move on, else we branch to incorrect_pass.
So, let’s rename loc_401102 into str_cmp_fail and loc_4010FE into str_cmp_succeed.
So here, we compare each character from the two string one by one. If we reach the end of String[4] and we still haven’t branch into str_cmp_fail, we know that we have succeed and the strings are the same!
After every loop, the pointers are increment every time and the process occurs until we branch into either str_cmp_fail or str_cmp_succeed. So basically, like we assumed, this is just a string comparison loop!
Now, our current password should look like this.
*a5yR3versing
Let’s move forward.
Finally, we are comparing the first character of String with 0x45(which is the character E in ASCII). If they equal, we print “Incorrect Password”, else we print the congratulations message!!
So our final password is Ea5yR3versing!! Let’s run the program and type it in!
3. Recap
This reversing challenge is pretty simple, but it’s pretty good practice for me to start reading x86 Assembly and reversing again!