January 1999
|
"AtomTime98
2.1a"
'memory echo' |
W32 PROGRAM
Code Reversing |
by N i X e | ||
Code Reversing For Beginners | ||
Program Details
|
||
Tools Used:
|
||
Rating |
Easy ( X ) Medium ( )
Hard ( ) Pro ( )
|
Solving the puzzle |
Introduction |
AtomTime98 syncronizes time on multiple
computers.
|
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.
|
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!
|
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!
|
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 |