January 1999
  

"AtomTime98 2.1a"
'memory echo' 
W32 PROGRAM
Code Reversing 
by   N i X e 
Code Reversing For Beginners

Program Details
Program Name: atmtm21a.exe
Program Type: Time sync utility
Program Location: Here
Program Size: 520 Kb

Tools Used:
Softice - Win'95 Debugger
W32Dasm - Win'95 Disassembler

Rating 

Easy ( X )  Medium ( )  Hard ( )  Pro ( )
 

Solving the puzzle
 
Introduction
 

AtomTime98 syncronizes time on multiple computers.
 
About this protection system
 

This shareware will end up registered if you enter a name, a the correct license key.

The name and reg key are saved in the registry:
HKEY_CURRENT_USER\Software\Adelsman\AtomTime\License\Code
HKEY_CURRENT_USER\Software\Adelsman\AtomTime\License\Date
HKEY_CURRENT_USER\Software\Adelsman\AtomTime\License\Key
HKEY_CURRENT_USER\Software\Adelsman\AtomTime\License\Name

Note: Use Regmon to find out what is written to/read from the Windows Registry.
 
The Essay
 

Try to run AtomTime and enter something in the registration screen.
Notice the 'License data is invalid' message you get when entering an invalid key! Write it down.

Create a deadlisting in W32Dasm and find the 'License data is invalid' message. Study the surrounding code. Just a few lines before the 'License data is invalid' we have the god guy string reference 'Thank you for registering'. Pay special attention to the jumps that lead to the bad guy/good guy messages so we can find out how to avoid the bad guy message and get the good guy message instead. Just before the bad guy message we got a 'Referenced by a (U)nconditional or (C)onditional Jump at Address:0040654F(C)'. Let's have a closer look at this:

:00406548 E881400000              call 0040A5CE ; check license key
:0040654D 85C0                    test eax, eax ; is eax = 0 ?
:0040654F 0F8488000000            je 004065DD   ; if eax = 0 jump to 'License data is invalid
:00406555 8D8BE0050000            lea ecx, dword ptr [ebx+000005E0]
:0040655B E83C0D0000              call 0040729C
:00406560 89C6                    mov esi, eax
:00406562 898D30FCFFFF            mov dword ptr [ebp+FFFFFC30], ecx
:00406568 E835480000              call 0040ADA2
:0040656D 89C7                    mov edi, eax
:0040656F 8D4DD0                  lea ecx, dword ptr [ebp-30]
:00406572 51                      push ecx
:00406573 8B8D30FCFFFF            mov ecx, dword ptr [ebp+FFFFFC30]
:00406579 E814400000              call 0040A592
:0040657E 8B8D30FCFFFF            mov ecx, dword ptr [ebp+FFFFFC30]
:00406584 E8C2480000              call 0040AE4B
:00406589 85F6                    test esi, esi
:0040658B 745E                    je 004065EB
:0040658D 8D4DE8                  lea ecx, dword ptr [ebp-18]
:00406590 E8BF920100              call 0041F854
:00406595 C745FC07000000          mov [ebp-04], 00000007
* Possible StringData Ref from Data Obj ->"License validated.  Thank you " ; good guy message
                                        ->"for registering!"
:0040659C 6822434300              push 00434322
:004065A1 8D4DE8                  lea ecx, dword ptr [ebp-18]
:004065A4 E8FF950100              call 0041FBA8
:004065A9 85FF                    test edi, edi
:004065AB 740D                    je 004065BA
:004065AD 6851434300              push 00434351
:004065B2 8D4DE8                  lea ecx, dword ptr [ebp-18]
:004065B5 E862980100              call 0041FE1C
* Referenced by a (U)nconditional or (C)onditional Jump at Address: 004065AB(C)
:004065BA 6A00                    push 00000000
:004065BC 6A00                    push 00000000
:004065BE 8D4DE8                  lea ecx, dword ptr [ebp-18]
:004065C1 E862DFFFFF              call 00404528
:004065C6 50                      push eax
:004065C7 E81C2C0200              call 004291E8
:004065CC C745FC06000000          mov [ebp-04], 00000006
:004065D3 8D4DE8                  lea ecx, dword ptr [ebp-18]
:004065D6 E809940100              call 0041F9E4
:004065DB EB0E                    jmp 004065EB
* Referenced by a (U)nconditional or (C)onditional Jump at Address:0040654F(C)
:004065DD 6A00                    push 00000000 ; if eax was 0 we come here :-(
:004065DF 6A00                    push 00000000
* Possible StringData Ref from Data Obj ->"License data is invalid.  Either " ; bad guy message
                                        ->"the data was not entered correctly"
:004065E1 68C5434300              push 004343C5

This ':0040654F je 004065DD' is performed right after a call and a test eax,eax. Many programs uses a serial validation function that returns with eax=0 if the reg code was invalid and eax=1 if correct reg code. Maybe this program does this too?

We could patch the following jump after the call to the 'is serial valid' routine but maybe this routine is called from several locations and so it woulden't be enough to patch one location. Therefore it is better to patch the 'is serial valid' routine than the code after the call.

Let's have a look at that 'is serial valid' routine just before the test eax, eax:

* Referenced by a CALL at Addresses: 0040495D, :00406548   ; this routine is called from 2 locations
:0040A5CE 55                      push ebp
:0040A5CF 8BEC                    mov ebp, esp
:0040A5D1 53                      push ebx
:0040A5D2 56                      push esi
:0040A5D3 89CB                    mov ebx, ecx
:0040A5D5 8D4B04                  lea ecx, dword ptr [ebx+04] ; ecx is a pointer to our name
:0040A5D8 E8DFCDFFFF              call 004073BC
:0040A5DD 85C0                    test eax, eax
:0040A5DF 7512                    jne 0040A5F3
:0040A5E1 8D4B08                  lea ecx, dword ptr [ebx+08] ; ecx is a pointer to the date
:0040A5E4 E8D3CDFFFF              call 004073BC
:0040A5E9 85C0                    test eax, eax
:0040A5EB 7506                    jne 0040A5F3
:0040A5ED 837B0C00                cmp dword ptr [ebx+0C], 00000000 ; is our serial blank?
:0040A5F1 750F                    jne 0040A602
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:0040A5DF(C),0040A5EB(C)
:0040A5F3 6A00                    push 00000000
:0040A5F5 89D9                    mov ecx, ebx
:0040A5F7 E8C9060000              call 0040ACC5
:0040A5FC 31C0                    xor eax, eax                  ; set eax to 0
:0040A5FE 5E                      pop esi
:0040A5FF 5B                      pop ebx
:0040A600 5D                      pop ebp
:0040A601 C3                      ret; name/date/serial was empty (License info invalid)
* Referenced by a (U)nconditional or (C)onditional Jump at Address:0040A5F1(C)
:0040A602 8BCB                    mov ecx, ebx
:0040A604 E839000000              call 0040A642 
:0040A609 89C6                    mov esi, eax                  ; the REAL serial
:0040A60B 8B4B0C                  mov ecx, dword ptr [ebx+0C]   ; our serial
:0040A60E 3BCE                    cmp ecx, esi
:0040A610 7516                    jne 0040A628
:0040A612 89D9                    mov ecx, ebx
:0040A614 E883CCFFFF              call 0040729C
:0040A619 85C0                    test eax, eax
:0040A61B 7414                    je 0040A631
:0040A61D 6A01                    push 00000001
:0040A61F 89D9                    mov ecx, ebx
:0040A621 E89F060000              call 0040ACC5
:0040A626 EB09                    jmp 0040A631
* Referenced by a (U)nconditional or (C)onditional Jump at Address:0040A610(C)
:0040A628 6A00                    push 00000000
:0040A62A 8BCB                    mov ecx, ebx
:0040A62C E894060000              call 0040ACC5
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:0040A61B(C), :0040A626(U)
:0040A631 8B4B0C                  mov ecx, dword ptr [ebx+0C]
:0040A634 3BCE                    cmp ecx, esi          ; ecx = our serial, esi = REAL serial
:0040A636 B801000000              mov eax, 00000001     ; set eax to 1
:0040A63B 7401                    je 0040A63E           ; if ecx=esi jump over the next line
:0040A63D 48                      dec eax               ; set eax to 0
* Referenced by a (U)nconditional or (C)onditional Jump at Address:0040A63B(C)
:0040A63E 5E                      pop esi
:0040A63F 5B                      pop ebx
:0040A640 5D                      pop ebp
:0040A641 C3                      ret
 

Start AtomTime in SoftIce. Fill in the registration info (I chose 'site license') and set a breakpoint at 00406548 (call 0040A5CE). Trace into the call with F8. Step over the lines in this function with F10 and display the register values and memory contents for all pushed values, registers changed after a call, and registers which are compared...

Notice the 'cmp ecx, esi' at the end of the function. It compares our entered serial (ecx) with a number (esi) and if they are not equal we'll get the 'bad guy' message. The other number in esi must be the REAL serial!!!

Yes. If I change the serial to the number in esi and press OK again I get registered.
The real serial consists of 8 characters and is a hex number!
 
 
Final Notes
 

This protection system is fairly easy to crack. An hour or two should do it!

This program compares the serials unencrypted (as numeric values, not as strings). If the serial had been encrypted the program would have been harder to crack.
 

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