|Code Reversing For Beginners|
|Rating||Easy ( X ) Medium ( ) Hard ( ) Pro ( )||
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.
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.
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: :0041FC2D 50 push eax :0041FC2E 64892500000000 mov dword ptr fs:, 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:, 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:-)
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.
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.
and NOT stealing the software you use will ensure that these