Part I: Dongle Protection
I don't know, I don't undertand.
Anyway I'm happy to host this essay by our schoolmate +Aitor and I agree TOTALLY with his philosophy: "We have (now) our target working fine -without the dongle- but we are not satisfied. We don't want to crack this program, we are reversing it in order to learn more ... real knowledge will be our unique satisfaction..."
Rrright so +crackers! (and now let's hope that +Aitor's other essays of a series of at least three will follow rash :-)
That's how the light gets in
I've chosen this program because it has got three levels of protection:
1) Program is dongle protected, that is, once you have installed it won't run without plugging in the dongle.
2) With the program are included *ALL* the toolboxes (sold apart at very expensive prices, believe me) but they're not mentioned anywhere. These are InstallShield packed .Z files that cannot be unpacked by the InstallShield file compressor because they are *ENCRYPTED* ... all the .Z files in the Matlab 5 CD are encrypted.
3) Once you have built a little decryptor, and all the forbidden toolboxes are unpacked, a license check appears ...
This essay (the 1st of a series of at least three) deals with the 1st level of protection ...
Dongle, hardware key, security plug, motxila ... words that sound terrible to many crackers (mainly beginners) out there. The main aim of this essay is to show how a hardware key protected commercial application can be cracked in less than a minute, as easily as you do with many other shareware targets, and if you give yourself a few more seconds you'll be able to crack the entire ready made (probably commercial) protection system.
+-------------------------------------+ + 1st APPROACH + + Fast non-ZEN one-minute-crack + +-------------------------------------+First thing we need is installing our target ... a minimal installation will be enough.
Aurrera with our job! Fire up Soft-iCE and run matlab.exe. Inmediately you are warned with a fatal error box: "Error checking out MATLAB". Without closing this box pop up Soft-iCE and check the list of window handles, you'll see something like this: Window Handle hQueue SZ QOwner Class Name Window Proc. ------------- ------ -- ------ --------------- ------------ 0268(1) 262f 32 MATLAB #32770 (Dialog) 17e7:4757 026c(2) 262f 32 MATLAB Button 17e7:102e ... an so on.
Yes, they are our error box and its OK-button. Let's make Soft-iCE break the program execution at the moment when the error box is destroyed. Doing so we'll be able to locate the calling instructions that make our box appear (this is true in 95% of the protections you'll find, incredible, isn't it?) only by PRETing within Soft-iCE. Ok, let's put our BREAKPOiNT:
bmsg 268 wm_destroyand let the program run. After pressing the OK-button Soft-iCE pops up again:
---USER!GETDLGCTRLiD+0017-------------------------------------- 17e7:4757 push bp 17e7:4758 mov bp,sp 17e7:475a push 4793 ... -------------------------------USER(08)------------------------
A few PRET commands from here until we land on the program code:
137:41adc0 call 6b093c 137:41adc5 add esp,14 137:41adc8 mov [ebp-20],eax 137:41adcb cmp dword ptr [ebp-20],0 137:41adcf jz 41adff 137:41add1 cmp dword ptr [6ed6f0],0 137:41add8 jz 41addf 137:41adda call 441544 137:41addf push 10 137:41ade1 mov eax,6c1486 137:41ade6 push eax 137:41ade7 mov eax,6c1492 137:41adec push eax 137:41aded push 00 137:41adef call cs:[8d0ae4] ;fatal error box --> 137:41adf6 mov dword ptr [ebp-24],0 ;bad guy 137:41adfd jmp 41ae06 ;go out! 137:41adff mov dword ptr [ebp-24],1 ;good guy, go ahead!
Incredible, eh? Can you hear it ? ... it's saying 'crack me' ;-). Don't think it twice and try a fast non-ZEN patch:
137:41adcf jz 41adff -> 137:41adcf jmp 41adff
After live testing patching code in memory (it works fine), will be easy to patch the code on disk:
MATLAB.EXE, 3.457.536 bytes (tiny, uhm?) Search : 74 2e 83 3d Replace : eb -- -- --
Now run the program and test it with a few samples and demos, everything works well ... isn't it?!
+-------------------------------------------------+ + 2nd APPROACH + + Breaking down the protection system itself + +-------------------------------------------------+We have our target working fine without the dongle, but we are not satisfied. We don't want to crack the program, we are reversing it in order to learn more ... real knowledge will be our unique satisfaction (apart from destroying Micro$oft and see Mr. Bill Fakes crucified, of course).
Let's take a look at the program again, and see more deeply how the protection system works. For doing this we must restore the original unpatched matlab.exe file. Now we are ready to begin, take a look at the code previous to our first patch:
137:41adb2 push 23 137:41adb4 push dword ptr [ebp-1c] 137:41adb7 push dword ptr [ebp-18] 137:41adba push dword ptr [ebp-14] 137:41adbd push dword ptr [ebp-10] 137:41adc0 call 6b093c 137:41adc5 add esp,14 137:41adc8 mov [ebp-20],eax 137:41adcb cmp dword ptr [ebp-20],0 137:41adcf jz 41adff 137:41add1 cmp dword ptr [6ed6f0],0 137:41add8 jz 41addf 137:41adda call 441544 137:41addf push 10
Pay attention and tell me what's could be happening in the code above. A series of values is been located in the heap, then a routine is called, and finally the EAX value returned from that routine is used to check our access to the program. Let's put a breakpoint at 137:41adc0 and trace the called routine code. After tracing a little we land here: -->137:94118a push ebp 137:94118b mov ebp, esp 137:94118d push ebx 137:94118e push esi 137:94118f push edi 137:941190 mov eax,[ebp+18] 137:941193 push eax 137:941194 mov eax,[ebp+14] 137:941197 push eax 137:941198 mov eax,[ebp+10] 137:94119b push eax 137:94119c mov eax,[ebp+C] 137:94119f push eax 137:9411a0 mov eax,[ebp+8] 137:9411a3 push eax 137:9411a4 call 941525 137:9411a9 add esp,14 137:9411ac jmp 9411B1 137:9411b1 pop edi 137:9411b2 pop esi 137:9411b3 pop ebx 137:9411b4 leave 137:9411b5 ret 14
This piece of code iS NOT from MATLAB itself ... where could it be located? Take a look at our MATLAB\bin directory: Directorio de C:\MATLAB\bin BCCENG~1 BAT 1.426 21/11/96 15:58 bccengmatopts.bat BCCOPTS BAT 1.632 21/11/96 15:58 bccopts.bat CMEX BAT 2.274 21/11/96 15:58 cmex.bat FMEX BAT 2.274 21/11/96 15:58 fmex.bat LIBENG DLL 29.696 22/11/96 9:51 libeng.dll LIBMAT DLL 60.416 21/11/96 12:05 libmat.dll LIBMX DLL 40.960 21/11/96 12:05 libmx.dll LIBUT DLL 40.960 21/11/96 12:05 libut.dll MATLAB EXE 3.457.536 06/01/98 7:24 matlab.exe MEX BAT 18.152 21/11/96 15:58 mex.bat MEDIT EXE 144.896 04/12/96 13:43 medit.exe MEXOPTS BAT 1.721 21/11/96 15:58 mexopts.bat MFC42 DLL 1.013.520 21/11/96 12:05 mfc42.dll MIPC50 DLL 248.320 21/11/96 12:05 mipc50.dll MLAPP TLB 2.789 21/11/96 12:06 mlapp.tlb ML_16 DLL 14.708 21/11/96 12:05 ml_16.dll MLPTOOL EXE 42.496 21/11/96 12:05 mlptool.exe MSCTOF DLL 31.744 21/11/96 12:05 msctof.dll MSFOPTS BAT 1.649 21/11/96 15:58 msfopts.bat MSVCEN~1 BAT 1.701 21/11/96 15:58 msvcengmatopts.bat MSVCIRT DLL 74.752 21/11/96 12:05 msvcirt.dll MSVCOPTS BAT 1.599 21/11/96 15:58 msvcopts.bat MSVCRT DLL 267.536 21/11/96 12:05 msvcrt.dll MWOLES05 DLL 43.520 22/11/96 11:51 mwoles05.dll PERL100 DLL 525.312 21/11/96 12:05 perl100.dll PERL EXE 36.352 21/11/96 12:05 perl.exe SHOWDLLS EXE 49.668 21/11/96 12:05 showdlls.exe WATENG~1 BAT 1.701 21/11/96 15:58 watengmatopts.bat WSPTOOL EXE 60.928 21/11/96 12:05 wsptool.exe LICENSE DAT 167 06/01/98 7:24 license.dat W32SSI DLL 66.560 02/04/96 11:01 w32ssi.dll 31 archivo(s) 6.286.965 bytes 2 directorio(s) 46.161.920 bytes libres
Most of the files have (more or less) the same date: 21-22/11/96, but there are four of them that have not:
MATLAB EXE 3.457.536 06/01/98 7:24 matlab.exe MEDIT EXE 144.896 04/12/96 13:43 medit.exe LICENSE DAT 167 06/01/98 7:24 license.dat W32SSI DLL 66.560 02/04/96 11:01 w32ssi.dll
matlab.exe : main executable, installation date stamped medit.exe : Matlab editor/debugger license.dat : ASCii license file, installation date stamped w32ssi.dll : what the hell could be this?
Take your favourite hex editor, search for our code and EUREKA! To read it better take W32Dasm and get its dead listing (about 245 kb):
Exported fn(): wSSIEIni - Ord:000Fh :40118A 55 push ebp :40118B 8BEC mov ebp, esp :40118D 53 push ebx :40118E 56 push esi :40118F 57 push edi :401190 8B4518 mov eax,[ebp+18] :401193 50 push eax :401194 8B4514 mov eax,[ebp+14] :401197 50 push eax :401198 8B4510 mov eax,[ebp+10] :40119B 50 push eax :40119C 8B450C mov eax,[ebp+C] :40119F 50 push eax :4011A0 8B4508 mov eax,[ebp+8] :4011A3 50 push eax :4011A4 E87C030000 call 401525 <--- call to checking_system :4011A9 83C414 add esp,14 :4011AC E900000000 jmp 4011B1 :4011B1 5F pop edi :4011B2 5E pop esi :4011B3 5B pop ebx :4011B4 C9 leave :4011B5 C21400 ret 14 <-------- return to MATLAB
If the dongle is installed this call returns EAX = 0. If not, it will return EAX = -1 ($FFFFFFFF). The aim is clear, isn't it? ... we'll patch this function to return always EAX=0. There are multiple solutions, e.g.:
:40118A 55 push ebp :40118A 33c0 xor eax,eax :40118B 8BEC mov ebp,esp ---\ :40118C c21400 ret 14 :40118D 53 push ebx ---/ :40118E 56 push esi
After live testing patching code in memory (it works fine), will be easy to patch the code on disk:
W32SSi.DLL, 66.560 bytes Search : 55 8b ec 53 56 57 8b 45 18 Replace : 33 c0 c2 14 00 -- -- -- --
Now run the program and test it, everything should work fine ... We don't care (by the moment) about how messy things are done inside the hardware checking routines, but if you trace the code inside the DLL you'll find code snippets like this:
... :401712 push eax :401713 mov eax,80992014 :401718 push eax :401719 push dword ptr [4070A0] :40171F call dword ptr  :401725 mov eax,[4070A0] :40172A push eax :40172B call dword ptr  :401731 mov dword ptr [4070A0],-1 :40173B jmp 40175A :40173D mov ebp,[4076A4] :401743 mov esi,[4076A8] :401749 mov edi,[4076AC] :40174F mov edx,9966 :401754 mov ax,8 :401758 out dx,ax ...
... :40197B mov edx,9966 :401980 sub eax,eax :401982 in ax,dx :401984 cmp ax,9966 :401988 jne 401A67 :40198E in al,dx :40198F cmp al,55 :401991 jne 401A67 :401997 inc edx :401998 in al,dx :401999 cmp al,88 :40199B jne 401A67 :4019A1 mov edx,9964 :4019A6 sub eax,eax :4019A8 in ax,dx :4019AA and eax,FFFF :4019AF mov edx,eax :4019B1 cmp ax,1000 :4019B5 jb 401A67 :4019BB and al,3 :4019BD jne 401A67 :4019C3 mov [4070A4], edx :4019C9 mov byte ptr [4070F1],1 :4019D0 jmp 401A67 ...
quite interesting material, but not for this essay ... may be in a future :)
This 2nd approach give us two iMPORTANT advantages over the 1st one:
1) Our target only calls the dongle checking routine once at startup, but you'll find applications that make multiple callings from anywhere at anytime during its execution. An example of this could be AutoCAD 13 from AutoDesk. Its protection check is mainly the same, you reach one point in the code with a call returning EAX=0 => good guy, and this is called not only at startup, but some more times while the program is running. If you take the 1st approach as a model for this kind of targets, you will must patch *any* references to the call ...
2) When a programmer distributes part of the code in DLLs he does it in order to reduce the size of the main EXE freeing it from the additional load of routines that are used only one or two times along the program, but most of the times do it to *share* routines among different applications ... taking into consideration the date of the w32ssi.dll file it won't be very strange to find the same DLL in other applications out there, and if this was the case we'd have broken down a ready made protection system ;-).
Like many other contributors to this pages English is not my mothertongue ... ... sorry for any inconvenience, be patient ;).
Greetings to all the reverse engineers from Euskal Herria (Basque Country) ... ... jotake irabazi arte !
(c) 1998 by +Aitor and the +HCU. All rights reserved.