January 1999
"Icon Clock Version 4.0"
'Sniffing the registration number' 
W32 PROGRAM Code Reversing
by   N i X e 
Code Reversing For Beginners 

Program Details
Program Name: siclock5.exe
Program Type: Clock
Program Location: Here
Program Size: 257 Kb

Tools Used:
Softice - Win'95 Debugger
W32Dasm - Win'95 Disassembler
 
Rating  Easy ( )  Medium ( X )  Hard ( )  Pro ( ) 
Solving the puzzle
 
 
Introduction
 

Icon Clock Version 4.0 is a highly visible digital clock which conserves desktop space by minimizing either to an icon size clock or to the system tray.
 
About this protection system
 

This shareware will end up registered if you enter a name and a registration number

The following entries are created in the in a file called Icolck95.ini in the Icon Clock directory:

[clock]
reg=????????? (9 digits, no encryption)
name=????????? (at least 4 letters, no encryption)
Note: Use Filemon to find out what is written to/read from files.
 
The Essay
 

Try to run Icon Clock a couple of times and enter something in the registration screen.
Damn, we don't get the usual 'bad registration code' message. And in the deadlisting created by W32DAsm there are no references to strings like 'Thank you for registering'. Without a bad guy or good guy string we cannot use W32Dasm locate the check serial routine...

Well, let's have a try in SoftIce. Enter some reginfo and set a breakpoint at 'hmemcpy' (or GetWindowTextA) and trace your way around. After the second GetWindowTextA press F11 (now the program has read both our name and our serial) and then press F12 until the programs exits.
Repeat the same again, but do NOT press F12 the last two times. Then trace with F10. Repeat this until you locate the serial validation routine...
The serial validation routine must use the serial and maybe the name, so we are looking for a functions the reads our serial and/or name.

After a lot of debugging you will hopefully end up at ?:00401840 - the serial validation routine. Find it in the W32Dasm deadlisting and print it so you can add your comments.

Here is what I ended up with:

* Referenced by a CALL at Addresses: 00401257, :00401F00, :004021C4, :004022F9   
:00401840 6AFF                    push FFFFFFFF
:00401842 6818154200              push 00421518
.
.
.
:004018DF 0FBE08                  movsx ecx, byte ptr [eax]     ; first byte from name
:004018E2 51                      push ecx
:004018E3 E8088E0000              call 0040A6F0                 ; do some calculations on our name
:004018E8 83C404                  add esp, 00000004
:004018EB E8108E0000              call 0040A700                 ; do some calculations on our name
:004018F0 99                      cdq                           ; extend ax to eax
:004018F1 B909000000              mov ecx, 00000009
:004018F6 F7F9                    idiv ecx                      ; edx now contains the remainder from eax / 9 
:004018F8 8B442408                mov eax, dword ptr [esp+08]
:004018FC 0FBE4806                movsx ecx, byte ptr [eax+06]  ; 7th byte from serial
:00401900 83C230                  add edx, 00000030             ; add 30 hex to the 7th number in our serial
:00401903 3BD1                    cmp edx, ecx                  ; edx (from name) eual to ecx (from serial)?
:00401905 7406                    je 0040190D                   ; if equal skip next line
:00401907 893D28E14200            mov dword ptr [0042E128], edi ; set mem to zero (not good)
* Referenced by a (U)nconditional or (C)onditional Jump at Address: 00401905(C)
:0040190D E8EE8D0000              call 0040A700
:00401912 99                      cdq
:00401913 B909000000              mov ecx, 00000009
:00401918 F7F9                    idiv ecx
:0040191A 8B442408                mov eax, dword ptr [esp+08]
:0040191E 0FBE4803                movsx ecx, byte ptr [eax+03]  ;4th byte from serial
:00401922 83C230                  add edx, 00000030
:00401925 3BD1                    cmp edx, ecx                  ; equal ?
:00401927 7406                    je 0040192F                   ; if equal skip next line
:00401929 893D28E14200            mov dword ptr [0042E128], edi ; set mem to zero (not good)
* Referenced by a (U)nconditional or (C)onditional Jump at Address: 00401927(C)
:0040192F E8CC8D0000              call 0040A700
:00401934 99                      cdq
:00401935 B909000000              mov ecx, 00000009
:0040193A F7F9                    idiv ecx
:0040193C 8B442408                mov eax, dword ptr [esp+08]
:00401940 0FBE08                  movsx ecx, byte ptr [eax]     ;1th byte from serial
:00401943 83C230                  add edx, 00000030
:00401946 3BD1                    cmp edx, ecx                  ; equal ?
:00401948 7406                    je 00401950                   ; if equal skip next line
:0040194A 893D28E14200            mov dword ptr [0042E128], edi ; set mem to zero (not good)
.
.
.

Hmm, let's think about this. Do we see a pattern? Yes we do, and the pattern is that our serial is read 9 times. We probably need a 9 digit serial number!

The code line :00401903 cmp edx, ecx compares the 7th digit from our serial with some value derivered from our name.
Ecx, the 7th digit from our serial is compared to edx! This means that edx now contains the 7th digit of the REAL reg code!!!

Next, the 4th number in our serial is compared to edx, then the 1st number in our serial is compared to edx and so on. These 9 compares must all be equal or we will not end up registered!

The serial is processed one number at a time like this: number + 30 hex (0 -> 30 hex, 1 -> 31 hex and so on).
The Ascii value of '1' is 31 hex (49 decimal), so it's not encrypted.

Now you should be able to find the serial for you own name. Just remeber that our serial is not processed from 1-9.
 
Final Notes
 

It would be fun to write a key generator here, but I just don't have the time. Maybe you do?

This could have been harder if the programmer(s) had encrypted the registration number and used a diffent 'check valid serial no' routine and not just call the same routine every time. Many shareware programs calls the same 'check valid serial no' every time the serial is validated... so we only need to crack one routine:-)

An easier way to locate the 'serial validation routine' could be to use a breakpoint at memory access (bpm or bpr in SoftIce) on our entered serial or name.
 

Greetings/thanks to The Sandman, Razzia, Volatility, Eternal Bliss, and all other tutorial writers!
 
Ob Duh
 

I wont even bother explaining you that you should BUY this target program if you intend to use it for a longer period than the allowed one.
 


 
 
 Return