Thanks for the challenge.

When reversing any application, we will want to see how it behaves to gain as many clues as we can so we know where to start. Run the application.

We get a string `Invaild key!`

so let’s search for the string. Make sure you get the (in)correct spelling.

Now we’ll need to find references to the string and locate the function(s) where they are used.

We can see that this is a small subroutine which doesn’t provide much information to us. We’ll backtrack to where this function is called.

We can instantly see another set of good and bad boys. What gives? Have a look at the jump instruction before them and the required condition. The `eax`

register is compared with `1`

but how do we get `eax`

? Take a careful look while we trace it.

```
call 0x0C23440
add esp, 4
mov BYTE [ebp - 1], al
...
mov BYTE [ebp - 3], al ; <--- irrelevant
movzx eax, BYTE [ebp - 1]
cmp eax, 1
jnz 0x0C2437D
```

What we see is that this conditional is only affected by the call to `0x0C23440`

so we can assume that the function we initially found is irrelevant. We will need to check this assumption later (we should *always* check our assumptions) after we analyse more parts of the binary.

Let’s now shift our focus to the beginning of the bad boy which has been highlighted. Note the locations which lead to the instruction. One is from the condition we have just examined, the other is from the top of the current function. Take a look at the condition there

```
cmp DWORD [esp + 8], 2
jnz 0x0C2437D
```

and recognise that it is comparing the first parameter of this function with `2`

. When you reverse engineer enough applications, your Spidey senses will fire up and instantly assume that this a possible comparison to check for a valid `argc`

of `main`

. Of course, we will need to verify this assumption and we can do so if we step the instructions there if we add in a command line argument. We will see that this jump is *not* taken if we add it. Now that we’ve cleared this assumption, we know that we are currently in `main`

.

Now, let’s step into the function which decides the good or bad boy (`0x0C23440`

).

Due to the size of the function, I have decided to cut it into two smaller sections. This first one represents an inlined `strlen`

which essentially decompiles into this:

```
char *p = input + 1; // + 1 to remove the counted null terminator
while (*input++)
i++;
size_t len = (input + i) - p; // length = final address - first address
if (len != 0x1E) // 0x1E == 30
return 0; // false
```

The jump instruction goes too far down to be included into this section, but trust me, it does return 0, or possibly `false`

since this is a C++ application.

The following is the second section of this function which checks the validity of the key.

There are a lot of conditionals here so we need to note down what each of them are (see my comments). Again, with enough experience, we can tell this is probably a for loop. This loop checks each character of the input in groups of 5 (note the modulo 5), sums them together and then checks a buffer for a valid combination. It repeats this 6 times to satisfy the string length of `0x1E`

. Decompiling this would resemble something like so:

```
unsigned int buffer = { 0xC9, 0xFF, 0x9C, 0xB7, 0xA6, 0xB6 };
for (unsigned int sum = 0, int i = 1; i < 0x1F; i++) {
char c = input[i];
// check if alphanumeric
if (c < '0' || c > 'z')
return 0;
if (c > '9' || c < 'A')
return 0;
if (c > 'Z' || c < 'a')
return 0;
// verify in 5-byte groups
sum += c - '0';
if (i % 5 == 0) {
if (buffer[i/5] != sum)
return 0;
sum = 0;
}
}
return 1;
```

How do we generate a key from this? An easy way is to iterate the verification buffer and for each element, apply the following algorithm:

```
1. Choose an alphanumeric X
2. Y = (buffer[i/5] + 0x30 * 5) - (X * 4) where Y is also alphanumeric
3. 5-byte group for buffer[i/5] = XXXXY
4. Repeat until 30 characters have been generated
```

Example: aaaa5aaaakEEEExLLLLwKKKKjKKKKz

This will only provide a subset of the entire possible range.