_____  ___  /_______
                              __  / / /  __/  ___/
                              _  /_/ // /_ / /__
                              _\__, / \__/ \___/

Target Info

Name       : Aareus IconCommander
URL        : http://www.telusplanet.net/public/brbi/aareus/software/
Protection : Serial protection, crippled in unregistered version.


Hi there!

At first looks, I thought that this program is going to be a tough one,
since the buttons, windows and other stuffs doesn't look normal to me.
But, after disassembling it, I realized that it uses custom controls, 
written in VC++ (this is what IDA gave me). From their site, you can
obtain the source codes for writing custom controls in win32asm.

Okay, tutorial time ;).

Tools Needed

Softice v3.x
IDA Pro v3.x
Asm compiler (for writing the keygen - optional)

The Essay

First of all, this program breaks on hmemcpy, so using it and tracing   
through, you will land yourself right after a call to SendMessageA at   
.text:1000679Fh. Notice that there's two more SendMessageA calls, so,      
simple deduction will tell you that these are the functions to get your
text from the registration dialog.

After the third SendMessageA call, it takes the first letter of your name
and compares it with zero, followed by a conditional jump, jz. This routine
checks if you entered anything into the 'Name' edit box, jumping to 'bad
serial' if you didn't put in any. Obviously, it only does the check to your
name, which means the 'Company' edit box can be left empty.

Next, you see it pushing the offsets of your name, company and password.
Then followed by a call to 1000B9F0h. Hmm...fishy. Lets take a look inside
this call.

Well, you find three calls to GlobalAlloc, then you find out that the
details you entered are being copied around. If you use IDA and look at
this section, you'll see call _memcpy. Isn't IDA just simply amazing? ;)

After all this copying around, you see another call, which is followed by
three calls to GlobalFree. Yup, this call must be the password generating
routine ;). So, what are we waiting for??

Step into the call, and whoa! Lots and lots of codes! Don't worry, just
keep tracing =). Lets see, a call to GlobalAlloc, then a RegOpenQueryExA,
two RegQueryValueExA and three lstrcpyA. Hmm..then you see your details
are being manipulated around. Here's a short snippet.

mov     esi, [ebp+var_38]     ; put location of password in esi
mov     al, [esi]             ; put first letter of password in al
cmp     al, 0                 ; cmp with 0
jz     _text_1000BC49         ; jump if 0, meaning password has ended
sub     al, 14h               ; subtract 14h from your password
mov     [esi], al             ; replace letter with the new value
inc     esi                   ; increase pointer of password
jmp     _text_1000BC35        ; loop
mov     eax, [ebp+var_38]     ; put location of password in eax
push    eax                   ; push location of password
call    _atoi                 ; converts decimal string to hex in eax

OK, looks simple enough. Subtracts every character of your password with
14h, then convert it to hex. Meaning, your converted password MUST be
a decimal string (because of the call to _atoi). So, what about your 
UNCONVERTED password? It would be decimal number + 14h. So, lets find 
out the range of alphabets which is valid for use as password. The 
hex value for the smallest digit value, 0 (zero) is 30h, so, 30h+14h=68h, 
which is D. The hex value for the biggest digit value, 9 (nine) is 39h, 
so 39h+14h=77h, which is M. So our password consists of letters ranging 
from D to M.

OK, lets continue with the routine.

call    _atoi                 ; convert decimal string to hex in eax
add     esp, 4                ; move stack pointer
mov     [ebp+var_20], eax     ; saves converted password
mov     eax, [ebp+var_14]     ; takes location of name
mov     [ebp+var_1C], eax     ; saves it
mov     eax, [ebp+var_C]      ; takes location of company
mov     [ebp+var_30], eax     ; saves it
mov     eax, [ebp+var_8]      ; takes location of string "DefaultIcon"
mov     [ebp+var_4], eax      ; saves it
mov     eax, [ebp+var_20]     ; moves eax with converted password
rol     eax, 3                ; rotate left 3 bits
mov     edi, [ebp+var_4]      ; takes location of string "DefaultIcon"
mov     edx, [edi]            ; move hex values to edx
xor     eax, edx              ; xor it with the rol-ed converted password
ror     eax, 7                ; rotate right the result 7 bits
mov     esi, [ebp+var_30]     ; takes location of company
mov     edx, [esi]            ; moves hex values to edx
ror     edx, 2                ; rotate right it 2 bits
xor     eax, edx              ; xor it with the result from previous calculation on password
mov     edi, [ebp+var_1C]     ; takes location of your name
cmp     eax, [edi]            ; compare the calculated result with hex values of name
jz      _text_1000BC95        ; jump to 'good_guy' if equal

If you don't know what ror, rol and xor are for, you better check with
your asm manual. I'm not going to explain such matters here ;).
Anyway, back to our code. Here's a summary of what it is doing.

1. Subtract 14h from each letter of your password to get decimal string.
2. Convert the decimal string to a hex value at eax.
3. ROL the hex value of your converted password 3 bits.
4. XOR it with hex values of the first 4 bytes in the string "DefaultIcon".
5. ROR the result 7 bits.
6. Takes the first 4 bytes of your company and ROR it 2 bits.
7. The result is XORed with result from step 5.
8. Final result is compared with the first 4 letters of your name.

Hmm...looks like there's some reversing to do ;). Beginning this part, I
would like to express my thanks to josephCo of MexElite for helping me
with this part.

Ok, so lets start thinking. The opposite of ROL is ROR, and vice versa.
The opposite of XOR is also XOR. Now, start working the calculation routine
the other way round.

1. Result in step 8 is your name, which is calculated from the XORed values
   of results from step 5 and step 6. The result of step 6 is a constant
   and doesn't need any reversing. By XORing our name with result of step 6
   will give us result for step 5.
2. For the constant, it's RORing the first 4 bytes of your company 2 bits.
3. ROLing 7 bits the result of step 5 will give us result for step 4.
4. XORing it with hex values from first 4 bytes of string "DefaultIcon" will
   give us result for step 3.
5. RORing this result 3 bits will give us our hex value of our converted 
6. Converting this hex value to string and adding 14h to each hex value
   will give us our valid serial.

Now, to write out the asm routine for a key generator. It should look 
like this.

DEFAULTICON db "DefaultIcon",0

NAME db 5 dup (?)       ; we only use the first 4 digits, so 5 spaces
                        ; is sufficient to include the NULL too.
COMPANY db 5 dup (?)    ; also only first 4 digits
PASSWORD db 15 dup (?)  ; lets give slightly more space for the password,
                        ; since we don't know how long our password is
                        ; supposed to be.

; I'm only beginning with the actual calculation routine. I won't
; include the get text part and whatsoever here, since you might
; want to write it out for DOS or win32 (by the way, I'm a great fan
; of win32asm ;).

mov edx, dword ptr [COMPANY]
ror edx, 2
mov eax, dword ptr [NAME]
xor eax, edx
rol eax, 7
mov edx, dword ptr [DEFAULTICON]
xor eax, edx
ror eax, 3
...                     ; some parameters for the hex2dstring routine 
...                     ; to store string in PASSWORD
call hex2dstring        ; get this routine from Stone's Webnote
mov esi, offset PASSWORD
xor ecx, ecx
movzx eax, byte ptr [PASSWORD+ecx]
cmp al, 0
je done
add al, 14h
mov byte ptr [PASSWORD+ecx], al
inc ecx
jmp loop_routine
...                     ; some parameters to display the password
call displaycode

Modify the above routine anyway you like to suit your source code.

Final Notes

Once again, I would really want to express my thanks to josephCo for
guiding and helping me in reversing this calculation routine. josephCo,
you're the best! ;)

Well, that's all for now. ytc_, signing off...