I like puzzles, they keep your mind up2date! So I’ve just registered over at crackmes.de because it really looks like a lot of fun – and I like fun especially when it comes to reversing things. But isn’t it Off-Topic? No, because analyzing applications and breaking protections in AppSec is something that is closely connected to exploiting flaws: You need to find a way through the application flow, probably evading protection mechanisms and understand what the dev did wrong ;-), which leads – in the end – to an application level compromise of the protection and grants access for all those badboy pirates. These information can help the dev to implement a more secure registration/authentication process. Hardening is something that can be fun, even if you keep in mind that nothing is 100% secure!

Let’s reverse the keygeneration process of an entry-level KeyGenMe. To be solved: Greedy Fly’s KeyGenMe v1.6

greedyfly16-1

Where does the KeyGen – process start ?

Since there is no badboy – message (if you enter a wrong serial, the KeyGenMe exits silently) and the goodboy – message is unknown yet, you need to look for something else. A good starting point is the “Hi!!!” string: Having a look at the IDA strings window reveals:

The string can be found @ 0x0040301C which is located in the function “DialogFunc”:

Find the correct Control handles!

Scrolling down a bit below the function head, you discover the first interesting part:

The GetDlgItem function retrieves the handle to an control within the GUI. The famous tool ResourceHacker is able to reveal all assigned control handles:

greedyfly16-2

The Edit-Controls (called textboxes in the further article) have the handles 104 up to 107 but in a muddled order (from left to right):

  1. Textbox = 107
  2. Textbox = 106
  3. Textbox = 104
  4. Textbox = 105

This will become important later 😉 …and btw: the tool also reveals the goodboy message: “Yeaaaaah!!! Congratulations!!! You’re the best cracker!”

According to the first code snippet the third textbox is queried first by the GetDlgItem function which returns the handle for the control and stores it into EAX. The handle is copied to another location in memory, because EAX is used in the following SendMessageA CALL:

Using this SendMessage CALL the application is able to issue commands such as

…which is a WM_GETTEXT CALL directly to the handle “dword_403070” which contains the handle for the third textbox. After the SendMessage CALL, EAX contains the length of the string loaded from the third textbox which is afterwards MOVed to EBX. The next CALL is much more interesting:

The first challenge!

It’s the first “real” part of the Keygeneration process:

Deciphered: EBX holds the strlen of the 3rd part of the serial. At this point it’s incremented by 1:

Afterwards shifted left by 4, which is basically the same like multipliying with 16:

64 is added on top:

multiplied by 386:

and finally XCHGed with /  saved in ESI:

Back in the DialogFunc application flow, ESI is compared to the value “67936”:

But what’s that value ? To find out you have to reverse the last few commands which represent the following calculation:

Mathematically reversed:

This means: if strlen equals 6 the following jump will be taken, which is our goal:

greedyfly16-3

The next two parts are very similar. The strlen of the first textbox is compared to 6 (EDX, that is also pushed onto the Stack):

and strlen of the fourth textbox is compared to EDX, that contains the POPed value 6:

This means the strings from textboxes 3,1 and 4 (in this order) are compared in its lengths to 6. If that matches, the application takes “the right” jump. Up next: The string from the 4th textbox is PUSHed to the stack and the function “sub_4015D0” is CALLed. Thanks to IDA’s great possibility to rename functions, I’ll use the “addup_int_from_char” name for this function, because it’s used several times later again:

This functions addups all single chars in a loop and returns the value to EAX. To better visualize what this function does, I’ve commented my IDA dump:

greedyfly16-4

The value from EAX is then compared against decimal 500200, which means that the value from the 4th textbox has to be less or equal to this value:

The following four lines

and

compare the 4th and 6th char of the 4th textbox to two specific values 2 and 0. So what do we have so far for the 4th textbox:

  1. It must have a strlen of 6
  2. It must be less than 500200
  3. Its 4th char must be 2
  4. Its 6th char must be 0

The next part is quite simple. The strlen from the 2nd textbox is first decremented, then substituted by 5 and EAX is tested, which leads to a true condition if the strlen is again 6:

After that the values from the textboxes are pushed onto the stack:

The following loop tests if each char is between 0 and 9, which means only numeric chars are allowed in the serial:

greedyfly16-5

Then some specific single chars are compared against single values:

and

The final challenge!

Great work until here. But wait something is missing! Correct: 3rd textbox. Remember: The value from the first textbox is already present in EAX. So this is first saved (MOVed) to ESI for later usage:

The value from the 4th textbox is pushed onto stack for further usage in the addup_int_from_char function:

The function saves its return value to EAX, that is then MOVed to EDI:

Afterwards the values from ESI (contains value from first textbox) and EDI (contains value from 4th textbox) are ADDed and saved to ESI:

Last but not least: the value from the third textbox is compared against the addition from the 1st and 4th textboxes. If those values are the same the jump is taken to the successful – message:

The KeyGen!

So that’s the puzzle. Let’s write a KeyGen for it. What do we have so far?

1st textbox:

  • Its 2nd char must be 9
  • its 4th char must be 7
  • It must be less or equal decimal 499799

2nd textbox:

  • Its 1st char must be 8

3rd textbox:

  • Its value is the addition of the first and fourth textboxes

4th textbox:

  • It must have a strlen of 6
  • It must be less than 500200
  • Its 4th char must be 2
  • Its 6th char must be 0

The normal keygenner would write a small and nice-music-driven application,but since this is just a small KeyGenMe, I’ll waive ;-). Here’s a Python script as a PoC:

…and finally pwned:

greedyfly16-6

Solution for Greedy Fly’s KeyGenMe v1.6
Tagged on:     

Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload CAPTCHA.