Reversing CTF Solution
- Find the Anti-Debug techniques.
- Bypass the Anti-Debug techniques.
- Find the password for an example username “Benjamin”.
- Code C program that checks if a pair of username and password fit.
- My own bonus: Code C program that finds the password for a given username.
- x32/x64 dbg (A.k.a x96dbg)
- C coding
- Performing a dynamic analysis of the program.
- Patching the program in a way that all Anti-Debug techniques will be bypassed.
- Code the keygen mechanism in C
Let’s try entering “Benjamin” as the username and “1234” as the password.
Ok… now let’s dive into debugging it to find the password.
By throwing the program to x32dbg and running it there, the program happens not to run.
Smells like Anti-Debug techniques.
Let’s take a look in the Call Stack
Bispookeygen2.00402017 is from where we exited the program.
Let’s grab a look of what’s going on there.
Having ExitProcess twice is quite strange.
Let’s put a breakpoint on 0x00402000 and dynamically analyze from there.
I noticed something odd with this line.
Here is how the code looks before running line:
And here is how it looks like after it:
Notice how DialogBoxParamA changed to ExitProcess.
Let’s see what this strange function does (0x00402439).
Bingo. Here is the Anti-Debug.
- IsDebbugerPresent (i.e. IsBeingDebugged in PEB)
- Code integrity checks.
But wait, what is the function 0x00402498 up to?
Here is the 3rd Anti-Debug technique:
Checks for breakpoints in places that they are not needed to be present.
Anti-Debug Function: 0x00402439
Techniques:
- IsDebbugerPresent (i.e. IsBeingDebugged in PEB)
- Code integrity checks.
- Checks for breakpoints in places that they are not needed to be present.
In order to bypass these Anti-Debug techniques, let’s simply replace every call for this function with nops.
This is after nopping the call for this function out of the first line. Now let’s find all the other calls for this function and nop them. Let’s proceed to finding the password.
According to MSDN, the operation function of the dialog box is 0x00402029.
After some trial and error, the action area of the “Try” button in the function is here
Let μ be the length of username.
We can see that 4 ≤ μ ≤ 15
Additionally, the first character in the username can’t be a space.
The mechanism is divided into 4 steps.
This part encodes the username into a sequence of successive bytes and calculates a number that stored in edx.
The equivalent of this part in C will look as follows:
This part multiplies the number that was calculated and stored in edx with the first 4 bytes (int) of the sequential bytes from step 1 and saves this big number in the memory because it is larger than the size of a register.
The equivalent of this part in C will look as follows:
Let’s see what is the function 0x004023b9
Well, this part encodes each byte of the calculated big number from step 2 by xor-ing the byte 0xbe.
The equivalent of this part in C will look as follows:
Function call:
Let’s see what is in the function 0x004023da
This part takes the bytes from step 3 and changes every byte that is bigger than 0x8f and not equal to 0x93 to 0x1,
and every byte that is equal to 0x93 to 0x8d.
Finally, it adds to the end “-LEET”.
The equivalent of this part in C will look as follows:
Function call:
At the end, the program checks if the user inputted password is equal to the generated password based on the username.
I attached 2 C files.
- Check.c - checks if a username and password fit.
- pwn.c - find a correct password based on a given username.
In cmd, let’s run pwn.exe (that is compiled from pwn.c).
Enter “Benjamin” and the password is:
31147352329-LEET
Username: Benjamin
Password: 31147352329-LEET
Pwned!