Crackmes.cf For Fun — Level 1

Renan Leite
7 min readSep 14, 2018

--

After a long time, we are back!

Well, I’m just going through a lot in my life right now, and I just couldn’t fit some time to continue the articles.

Just changed radically my routine, and my new daily chores are just taking away alot of my time.

Yeah, this kind of contingency will probably happen with some frequency. I’m just not totally adapted to this new routine, and I’ll need a little bit of time to normalize everything.

I hope you guys understand 😕.

Well, enough have been said , and I’m starting to feel people fading away after this. Without further ado, lets get started!

First, I would like to mention that you’ll kinda need some previous knowledge to follow through this (but not that much, really). To be more specific, you’ll have to know:

  1. How to code;
  2. Some data structure basics (specifically, how memory stack works);
  3. Just a little bit of Assembly language (enough to understand what the heck is going on);
  4. VB6 (Visual Basic) basics;
  5. How to make some russian squat kicks (you can learn it with this tutorials: a) https://www.youtube.com/watch?v=Wy4FCVMXnXc ; b) https://www.youtube.com/watch?v=dQw4w9WgXcQ ).

It seems a lot to begin with, but you’ll see that this level it’s just not that hard to follow up.

First, let me introduce you to the crackme sample (You can find it in the crackmes.cf archives, by the way: http://crackmes.cf/archive/): dear readers, this is abex2 crackme (by abex), abex2 crackme, those are my readers!

The crackme specifications are:

Difficulty: 1 — Very easy, for newbies.

Platform: Windows (by the way, all the crackmes will run on windows).

Language: VB6.

I recommend you to follow through this step by step in a virtualized environment. If you want to run the crackme on your host system, just don’t want it anymore. There is no malicious stuff going on in the executable, but is never a good idea to experiment stuff in your host system. After all, VMs were made for us to screw it with our experiments, so lets use it, ok?! ☣☢

Create your VM, dude!

The tools we’ll use here are:

  1. DIE (Detect It Easy). You’ll find it here: https://ntinfo.biz/. This tool shows some information about files. I think it was originally made to be a packer identifier, but it gives you alot more information beyond that;
  2. x64dbg (x64 Debugger). You’ll find it here: https://x64dbg.com/. Basically, it is a PE (Portable Executable) debugger;

You can read/watch alot of stuff about this tools in the web. But everything that you’ll need to know I’ll teach you as we go through the tutorial.

Enough of descriptions. Let’s crack!

So, at the beginning of the analysis, we don’t know how this executable was compiled. In order to obtain more information about the software, we open it with DIE.

As you can see, we are dealing with a VB6 Native Code executable. If you don’t know the differences between P-Code and Native Code generated by VB in versions 5 or 6, I recommend you to take a look.

Resuming, Visual Basic P-Code is like a pseudo-code intermediate language that is interpreted at runtime, while Visual Basic Native Code is compiled to the native language of your machine (in this case, to x86 instructions).

Now that we know how this executable was compiled, let’s take a look in its Import Address Table (IAT).

abexcrackme2 IAT

If you know little to nothing about IATs, you can read about it here: http://sandsprite.com/CodeStuff/Understanding_imports.html.

As expected, this executable statically imports msvbvm60.dll, which is a DLL that provides functionality to VB6 programs. There are a lot of procedures imported in the listing, and we’ll focus on some of them as soon as we begin to reverse the executable.

Now, let’s run the program to see how it looks like before we start debugging.

The face of the devil!

After executing, this window pops up to us. The main objective of this crackme, at first glence, is to generate a correct serial number to a specific username. Let’s test to see if that’s what it is!

Yeah, that’s it! 🙃

So, know we are sure that we are dealing with a VB6 keygen crackme. Without further ado, let’s load it up in the debugger!

Fun entrypoint, right? 🤔

As soon as we load it, the entrypoint of the main module is a push instruction to ThunRTMain.

The address 0x401E14 pushed to the procedure ThunRTMain is a pointer to a VBHeader structure. This pattern of pushing the structure to that specific procedure is present in all VB6 executables, and you’ll find it everytime you reverse a program like this.

I will not dig deeper in this subject (i’m just arousing your curiosity), so let’s proceed in the challenge!

Let’s take a look at the string references in the main module.

Yep, this key is right?! hmmm… 🤪

We can see some good strings referenced in the module. As we want to get this key right, let’s follow in dissambler the address 0x40338A.

After following the address and scrolling up a little bit, we notice that we are inside the function triggered by the button Check.

As we know how function prologues are formed by compilers, we’ll look for the instruction push ebp in order to trace back the beginning of the function. After that, select every instruction (including push ebp) all the way to the instruction ret, and press the key G to form a Graph inside x64dbg. This way we can visualize the control flow in a much more friendly form.

Ahhh, that’s waaaay better!

Now that we have the function exposed in graph mode, let’s see what’s happening there.

Observing the control flow and function calls, we can take some conclusions at first glance.

First, there is a check to make sure that the user inserts a name with a minimum of 4 characters. This happens after the calls to _vbaLenVar (which checks the length of ‘Name’) and _vbaVarTstLt (which checks if the length of ‘Name’ is less then 4).

Next, we can observe a loop routine. There are alot of interesting calls to functions exported by msvbvm60.dll:

  1. The routine begins with a call to _vbaVarForInit, which return 1 to EAX in order to begin the loop.
  2. Inside the loop routine, there is a call to _vbaI4Var, which converts the object to a 4 bytes integer (in this case, it returns the loop counter converted to a 4 bytes integer).
  3. Inside the loop routine, there is a call to rtcAnsiValueBstr, which converts the character to its ASCII hexadecimal equivalent and returns it to EAX.
  4. Inside the loop routine, there is a call to _vbaVarAdd, which adds a variable value to another.
  5. Inside the loop routine, there is a call to rtcHexVarFromVar, which converts an integer variable to a wide string.
  6. Inside the loop routine, there is a call to _vbaVarCat, which concatenates strings.
  7. Inside the loop routine, there is a call to _vbaVarForNext, which continues the loop if the actual counter is less then the established maximum.

So, what interesting information we can obtain with this previous analysis? It looks like that we can assume that this crackme is doing a concatenation of values (_vbaVarCat), limiting itself to a specific amount of iterations (_vbaVarForNext, _vbaI4Var), and the values concatenated in the resultant string have some arithmetic involved (_vbaVarAdd) with the ASCII values in the ‘Name’ field (rtcAnsiValueBstr).

With this hypothesis in mind, after iterating through the loops, we can see that the value 0x64 is being added to the iterated character of the string inputed in ‘Name’, and the result of the addition is being concatenated to the end of a resultant serial. In fact, you can even see the referenced string in memory with the complete serial after the fourth loop has been iterated.

For the Name ‘heyhey’, we have a resultant serial ‘CCC9DDCC’ after the fourth iteration.

Now that we have the resultant serial in hands, let’s test it up to see if we are right!

It looks like we found the pattern! 🤯

Nice! Finally, we know what happens behind the software scenes. Now, to end it up well: let’s automate the keygen process!

Python script to generate the correct serial.

In order to create a script to generate a correct serial for specific names, you have to keep in mind what we discovered during our previous analysis.

Let’s use another name to generate another serial. After that, we will test it in the crackme to see if our script is returning a valid result.

Is it correct?! 😨
Yes! 😁

As you guys can see, our script is correct, and it’s generating a valid serial value! You can try to replicate it with another programming language, or make some other editions so you can make it more fun to you! (:

And that’s it for today! Hope you guys enjoyed!

If you have any suggestions or critics, please, let me know so I can increase the quality of the posts in the next series!

Bye! 👻

--

--