January 1999
"Password Tracker Deluxe 3.56"
'Patching' 
W32 PROGRAM Code Reversing
by   N i X e 
Code Reversing For Beginners 

Program Details
Program Name: ptrack.zip
Program Type: Utility
Program Location: Here
Program Size: 1.03 Mb

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

We all know that using separate user names and passwords is smart computing. It is also smart to change your passwords frequently. Remembering all those user names and passwords, especially if you change them as often as you should, can be a real hassle. That was before Password Tracker Deluxe.

Password Tracker Deluxe solves the problem of trying to remember multiple user names and passwords for different programs. All you need to do is enter the information into Password Tracker Deluxe’s database, assign the program window where you want the information to go, and you’re done. The next time you need to enter user name and password information, just click on the Password Tracker Deluxe icon in the Windows 95/98/NT 4.0 System Tray, pick the correct "P-Track" and the data is automatically inserted into the program. And with the wizards in Password Tracker Deluxe, using Password Tracker Deluxe has never been easier.

Password Tracker Deluxe does even more than just track your passwords. Password Tracker Deluxe can even launch a program or URL. Also, Password Tracker Deluxe can even send your commonly typed text to programs.
 
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 windows registry:

[HKEY_CURRENT_USER\Software\CLR\Password Tracker\Install]
"MainDirectory"="C:\\Program Files\\Password Tracker Deluxe"
"RegistrationNameDeluxe"="My name" (not encrypted)
"RegistrationNumberDeluxe"="My serial number" (not encrypted)
Note: Use Regmon to find out what is written to/read from the Windows Registry.
 
The Essay
 

Try to run Password Tracker a couple of times and enter something in the registration screen.
Notice the 'Invalid registration number.' message! Write it down.

Create a deadlisting in W32Dasm and find the 'Invalid..' message you have written down. Now we must analyse the code before the string reference too see if we can avoid the bad guy message.
The routine containing the ref to 'Invalid..' has a 'call 0041FC20' followed by a 'cmp eax,1' just a few lines up. A call followed by a compare/test on eax should make a bell ring! 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 also does this?

Here is the interesting code:

:0041F66A 8B542404                mov edx, dword ptr [esp+04]
:0041F66E 8B442408                mov eax, dword ptr [esp+08]
:0041F672 52                      push edx
:0041F673 50                      push eax
:0041F674 E8A7050000              call 0041FC20         ; an interesting call - serial validation?
:0041F679 83C408                  add esp, 00000008
:0041F67C 83F801                  cmp eax, 00000001     ; compare eax and 1
:0041F67F 7509                    jne 0041F68A          ; if not equal jump to 'Invalid reg...'
ADD EAX,2  - 0502000000
:0041F681 8BCE                    mov ecx, esi
:0041F683 E8B17C0100              call 00437339
:0041F688 EB21                    jmp 0041F6AB
* Referenced by a (U)nconditional or (C)onditional Jump at Address: 0041F67F(C)
:0041F68A 6A00                    push 00000000
:0041F68C 6A30                    push 00000030
* Possible StringData Ref from Data Obj ->"Invalid registration number." ; our string!
.
.
.
* Referenced by a CALL at Addresses: 0041F674, 0041FB8F ; this function is called from 2 locations  
:0041FC20 6AFF                    push FFFFFFFF         ; start of validate name/serial routine
:0041FC22 6808954500              push 00459508
:0041FC27 64A100000000            mov eax, dword ptr fs:[00000000]
:0041FC2D 50                      push eax
:0041FC2E 64892500000000          mov dword ptr fs:[00000000], esp
:0041FC35 83EC14                  sub esp, 00000014
:0041FC38 8B442424                mov eax, dword ptr [esp+24]
:0041FC3C 56                      push esi
:0041FC3D 50                      push eax
:0041FC3E 8D4C2408                lea ecx, dword ptr [esp+08]
:0041FC42 E8E9FAFFFF              call 0041F730         ; calculations on name
:0041FC47 8B54242C                mov edx, dword ptr [esp+2C]
:0041FC4B 51                      push ecx
:0041FC4C 8BCC                    mov ecx, esp
:0041FC4E 8964242C                mov dword ptr [esp+2C], esp
:0041FC52 52                      push edx
:0041FC53 C744242800000000        mov [esp+28], 00000000
:0041FC5B E856B60100              call 0043B2B6         ; ?
:0041FC60 8D4C2408                lea ecx, dword ptr [esp+08]
:0041FC64 E827FCFFFF              call 0041F890         ; serial
:0041FC69 8D4C2404                lea ecx, dword ptr [esp+04]
:0041FC6D 8BF0                    mov esi, eax
:0041FC6F C7442420FFFFFFFF        mov [esp+20], FFFFFFFF
:0041FC77 E8C4FBFFFF              call 0041F840         ; if this return esi<>1 then 
                                                        ; we get the 'Invalid reg..' message
:0041FC7C 8B4C2418                mov ecx, dword ptr [esp+18]
:0041FC80 8BC6                    mov eax, esi          ; move return code to eax
:0041FC82 64890D00000000          mov dword ptr fs:[00000000], ecx
:0041FC89 5E                      pop esi
:0041FC8A 83C420                  add esp, 00000020
:0041FC8D C3                      ret
 

Hey, let's fire up SoftIce and try to follow the call to 0041FC20. Yes, here are a lot of calculations on memory addresses, our name, and our serial. This IS the validate serial function. Let's crack it...

I tried to figure out the real serial... and failed.

I tried to find the real serial... and failed.

I tried to patch the 'is valid serial' routine (0041FC20) but that is pretty tricky because we have a lot of pointers being manipulated here and there are no place to insert the extra assembler statement needed. I tried but then some of the registers was affected... which resulted in all kinds of strange page faults and a lot of reboots. So I failed here too.

Then I patched the call to 0041F840 so it allways returned 1. Nope, this routine is called from several locations and if it allways returns 1 you will get an error when closing the application. Failure again:-(

After some debugging and taking notes I found that the call to 0041FC20 returned with eax = FFFFFFFF if reg no not valid and eax = 1 if reg no valid. There must be somewhere we can we make our patch? Hm, there are two references to 0041FC20: From a CALL at addresses 0041F674 and 0041FB8F. After the call both routines have this code:

:0041F674 E8A7050000              call 0041FC20         ; validate name/serial
:0041F679 83C408                  add esp, 00000008     ; adjust stack pointer
:0041F67C 83F801                  cmp eax, 00000001     ; compare eax (FFFFFFFF) and 1
:0041F67F 7509                    jne XXXXXX            ; if not equal we are not registered
:0041F681 8BCE                    mov XXXXXX

Here we actually have 5 bytes we can use (cmp eax, 00000001 and jne XXXXXX). "mov eax,1" takes up exactly 5 bytes:-)
Now we are back on track. We can patch the two calling routines so they think the call to 0041FC20 returned eax=1.
The following patch removes a compare and makes a conditional jump unconditional. It does not change any register values other than eax. Make your patch as small as possible:

Before the fix:
:0041F674 E8A7050000              call 0041FC20         
:0041F679 83C408                  add esp, 00000008
:0041F67C 83F801                  cmp eax, 00000001     ; compare eax and 1
:0041F67F 7509                    jne 0041F68A          ; if not equal jump to 'Invalid reg...'
.
.
.
:0041FB8F E88C000000              call 0041FC20
:0041FB94 83C408                  add esp, 00000008
:0041FB97 83F801                  cmp eax, 00000001     ; compare eax and 1
:0041FB9A 7514                    jne 0041FBB0          ; if not equal jump to 'Invalid reg...'


After this fix
:0041F674 E8A7050000              call 0041FC20         
:0041F679 83C408                  add esp, 00000008     
:0041F67C B801000000              mov eax, 00000001     ; eax allways 1 and no jump
.
.
.
:0041FB8F E88C000000              call 0041FC20
:0041FB94 83C408                  add esp, 00000008     
:0041FB97 B801000000              mov eax, 00000001     ; eax allways 1 and no jump

Finally we are registered - even after restarting the application.

All name/serial combinations are now accepted:-)
 
Final Notes
 

This protection system fooled me a bit. Usually it's best to patch the 'check valid serial' routine but in this case I found that the easiest crack was to patch the two calling routines...

Nice protection system but it all depends on the two compares. Just a little more protection and I would not have solved this puzzle and found something easier to play with.
 
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