Cracking MMTools

02/03/2001
by +DaFixer
Courtesy of Fravia's page of reverse engineering
slightly edited
by +Tsehp
There is a crack, a crack in everything That's how the light gets in
Rating
( )Beginner ( )Intermediate (x)Advanced ( )Expert

The SwiftSoft multimedia tools are not only very nice components for delphi, but also very interesting reversing target. I can honestly say that this is the hardest to crack delphi component protection i've ever seen. But it is not uncrackable :) I will try to point mainly on protection itself and i assume you know how to debug and trace.
Cracking MMTools
A very good delphi components protection
Written by +DaFixer


Introduction
   MMtools are components for Delphi and C++Builder. They are very nice and good multimedia 
components with a strong protection for delphi components :) The limitations are that you can
run your applications only if your Delphi/C++Builder is active. The protection uses 
mmutil32.dll which is written in Delphi and *IS NOT SHRINKED* !!! Ignore the section names.
One can put what he wants there :) It has a custom/homemade decryption implemented that has
this scheme:

1) The application checks if IDE is running. If you are good boy it 
calls mmutil32._GetDeviceID_ function
2) _GetDeviceID_ decrypts _GetDeviceStatus_ and some more procedures
3) _GetDeviceStatus_ checks if IDE is running with FindWindow() and comparing the
loaded modules names with the normal delphi dlls that are loaded when delphi is loaded.
4) if all is ok _GetDeviceStatus_ decrypts the rest of mmutil32.dll
5) In addition there are *hidden* and *random* checks in the executable itself that exits
immediately if it found that you are bad guy :)

I dont like all this and will gonna fix it ! :)
Tools required
 W32Dasm, 
 Hex editor (i use WinHEX), 
 DeDe 2.44 or higher (I love this tool :)) )
 SoftIce -- (Optional)
Target's URL/FTP
 www.swiftsoft.de
Program History
   The protection has been changed from v1.5 to v2.0!
Essay
I wont explain all the crap in this protection because it is huge enough. Instead i will point on 
the most interesting part that is the decryption of mmutil32.dll and the checks for is IDE running 
there. As sample application you may use project2.exe. You can download it here.

For now disassemble it with D32DASM and DeDe. 

The executable itself do not have in imported modules this mmutil32.dll so it is loaded 
from the code. I found the place where all this is done and will show you how! Start to 
debug the target in win32dasm. The first lines are:

00543A80   55                     push    ebp
00543A81   8BEC                   mov     ebp, esp
00543A83   83C4F4                 add     esp, -$0C
00543A86   B8D0335400             mov     eax, $005433D0

00543A8B   E8A435ECFF             call    00407034  <-- this is the _InitExe routine
                                                    <-- that also initialize units.

* Possible reference to TApplication instance
|
00543A90   A198785400             mov     eax, dword ptr [$547898] 
00543A95   8B00                   mov     eax, [eax]

* Reference to: Forms.TApplication.Initialize()
|
00543A97   E88090F0FF             call    0044CB1C
00543A9C   8B0D387A5400           mov     ecx, [$547A38]

.....

Initiazation of units means running its initialization code. Step in 00407034 and 
continue to trace until you reach the IniUnits() routine:


004039E8   3BF3                   cmp     esi, ebx
004039EA   7E14                   jle     00403A00

004039EC   8B04DF                 mov     eax, [edi+ebx*8] <-- prepare the offset of initialization
                                                           <-- routine of a unit

004039EF   43                     inc     ebx              <-- increase processed units counter 
004039F0   891DB0845400           mov     [$5484B0], ebx

004039F6   85C0                   test    eax, eax         <-- is there any initialization routine
                                                           <-- for this unit ?

004039F8   7402                   jz      004039FC         <-- if no, then process next unit

004039FA   FFD0                   call    eax              <-- else call it !

004039FC   3BF3                   cmp     esi, ebx         <-- did we processed all units ?
004039FE   7FEC                   jnle    004039EC         <-- loop until all got processed!


When EBX is $30 (hex) the initialization routine for unit MMUtils.dcu is called:


0044326C   55                     push    ebp
0044326D   8BEC                   mov     ebp, esp
0044326F   33C0                   xor     eax, eax
00443271   55                     push    ebp
00443272   68EB334400             push    $004433EB

***** TRY
|
00443277   64FF30                 push    dword ptr fs:[eax]
0044327A   648920                 mov     fs:[eax], esp
0044327D   832D0899440001         sub     dword ptr [$449908], +$01
00443284   0F8353010000           jnb     004433DD

* Reference to: MMUtils.FindIDERunning()
|
0044328A   E881FBFFFF             call    00442E10
0044328F   84C0                   test    al, al
00443291   7529                   jnz     004432BC      <-- bad boys jumps here
00443293   6A00                   push    $00
00443295   B82C994400             mov     eax, $0044992C

* Possible String Reference to: 'IDE not found. Please register !'
|
0044329A   BAFC334400             mov     edx, $004433FC

* Reference to: Sysutils.StrPCopy(System.AnsiString)
|
0044329F   E8E04AFCFF             call    00407D84
004432A4   8BD0                   mov     edx, eax

* Possible String Reference to: 'Multimedia Tools'
|
004432A6   B920344400             mov     ecx, $00443420

* Possible reference to TApplication instance
|
004432AB   A1E08D4400             mov     eax, dword ptr [$448DE0]
004432B0   8B00                   mov     eax, [eax]

* Reference to: Forms.TApplication.MessageBox()
|
004432B2   E899AFFFFF             call    0043E250

* Reference to: System..Halt0()
|
004432B7   E86405FCFF             call    00403820

* Reference to: MMUtils.InitMMUtils()
|
004432BC   E817FCFFFF             call    00442ED8
004432C1   680C994400             push    $0044990C

* Reference to: kernel32.InitializeCriticalSection()
|
004432C6   E8512CFCFF             call    00405F1C

* Reference to: TransactionOK
|
004432CB   C605488B440001         mov     byte ptr [$448B48], $01

* Reference to: GetDeviceID
|
004432D2   833D2499440000         cmp     dword ptr [$449924], +$00
004432D9   740B                   jz      004432E6

* Reference to: MMUtil32._GetDeviceID_()
|
004432DB   FF1524994400           call    dword ptr [$449924]  <-- The first interesting proc

* Reference to: InitCode
|
004432E1   A32C8B4400             mov     dword ptr [$448B2C], eax

* Reference to: InitCode
|
004432E6   833D2C8B440000         cmp     dword ptr [$448B2C], +$00
004432ED   7516                   jnz     00443305

* Possible String Reference to: 'Initialization Error'
|
004432EF   B93C344400             mov     ecx, $0044343C
004432F4   B201                   mov     dl, $01

* Possible reference to class Exception
|
004432F6   A1806B4000             mov     eax, dword ptr [$406B80]

* Reference to: Sysutils.Exception.Create(System.AnsiString)
|
004432FB   E86459FCFF             call    00408C64

* Reference to: System..RaiseExcept()
|
00443300   E84301FCFF             call    00403448

* Reference to: InitCode
|
00443305   A12C8B4400             mov     eax, dword ptr [$448B2C]

* Reference to: GetDeviceStatus
|
0044330A   FF1528994400           call    dword ptr [$449928]   <-- And the second interesting proc

* Reference to: System.Randomize()
|
00443310   E813F6FBFF             call    00402928
00443315   B850C30000             mov     eax, $0000C350

......
......


Ok step in the call to MMUtil32._GetDeviceID_() and lets trace a bit more:

Exported fn(): _GetDeviceID_ - Ord:0002h
:00409C48 53                      push ebx
:00409C49 803DC0D2400000          cmp byte ptr [0040D2C0], 00
:00409C50 7441                    je 00409C93
:00409C52 33C0                    xor eax, eax
:00409C54 A3D8E54000              mov dword ptr [0040E5D8], eax
:00409C59 33C0                    xor eax, eax
:00409C5B A3DCE54000              mov dword ptr [0040E5DC], eax
:00409C60 BB187C4000              mov ebx, 00407C18
:00409C65 BAC87E4000              mov edx, 00407EC8
:00409C6A B86C874000              mov eax, 0040876C
:00409C6F E8E8E1FFFF              call 00407E5C <-- Decrypts the proc at 00407F28  
:00409C74 8BC3                    mov eax, ebx
:00409C76 E8ADE2FFFF              call 00407F28 <-- Decrypts _GetDeviceStatus_ routine
                                                <-- lets have a closer look:
   :00CD7F28 push ebx
   :00CD7F29 push esi
   :00CD7F2A push edi

   :00CD7F2B lea edx, dword ptr [eax+4C]  
   :00CD7F2E mov esi, dword ptr [edx]

   :00CD7F30 lea edx, dword ptr [eax+64]
   :00CD7F33 sub esi, dword ptr [edx]    <-- some very secret params :))

   :00CD7F35 lea edx, dword ptr [eax+50]
   :00CD7F38 mov edi, dword ptr [edx]    <-- like the offset of decryption procedure

   :00CD7F3A lea edx, dword ptr [eax+5C]
   :00CD7F3D mov ecx, dword ptr [edx]

   :00CD7F3F lea edx, dword ptr [eax+54]
   :00CD7F42 sub ecx, dword ptr [edx]    <-- and the count of bytes that must be decrypted ($62E)

   :00CD7F44 mov edx, 07327281           <-- some parameters for the decryption
   :00CD7F49 push 06262771
   :00CD7F4E push esi <- this is $0000006C
   :00CD7F4F lea ebx, dword ptr [ecx+edx] <-- fast calculation and push (073278AD)
   :00CD7F52 push ebx

   :00CD7F53 add eax, 00000054
   :00CD7F56 mov eax, dword ptr [eax]
   :00CD7F58 xchg eax,edx                <-- and more secret stuff :))

(-- registers before the call
(EIP=00CD7F59
(EAX=07327281
(ebx=073278ad
(ecx=0000062c
(EDX=00CD9618
(esi=0000006c
(edi=00cd7ef0
(ebp=0069fdfc
(esp=0069fdcc
   :00CD7F59 call edi   <-- calls decryption routine at 00CD7EF0


     The decryption routine:
     -----------------------
     :00CD7EF0 push ebp
     :00CD7EF1 mov ebp, esp
     :00CD7EF3 push edi
     :00CD7EF4 push ebx

     :00CD7EF5 mov ebx, eax  <-- some initial value for BL
     :00CD7EF7 mov edi, edx  <-- pointer to the stream that should be decrypted

     :00CD7EF9 imul [ebp+10]               <-- [ebp+10] = 06262771 
     :00CD7EFC add eax, dword ptr [ebp+0C] <-- [ebp+0c] = 6C 
     :00CD7EFF cdq
     :00CD7F00 idiv [ebp+08]               <-- [ebp+10] = 06262771
     :00CD7F03 mov eax, edx                <-- gets the modulo
     :00CD7F05 and eax, 800000FF           <-- as byte
     :00CD7F0A jns 00CD7F13
     :00CD7F0C dec eax
     :00CD7F0D or eax, FFFFFF00
     :00CD7F12 inc eax
     :00CD7F13 mov ah, byte ptr [edi]      <-- store the current still not decrypted byte
     :00CD7F15 add byte ptr [edi], bl      <-- add BL
     :00CD7F17 sub byte ptr [edi], al      <-- and substract the prev calc. modulo as byte
     :00CD7F19 mov bl, ah                  <-- store the encrypted byte in BL
     :00CD7F1B mov eax, edx                <-- store eax
     :00CD7F1D inc edi                     <-- next byte to be decrypted
     :00CD7F1E loop 00CD7EF9

     :00CD7F20 pop ebx
     :00CD7F21 pop edi
     :00CD7F22 pop ebp
     :00CD7F23 ret 000C


   :00CD7F5B pop edi
   :00CD7F5C pop esi
   :00CD7F5D pop ebx
   :00CD7F5E ret
 
:00409C7B C605C8D2400001          mov byte ptr [0040D2C8], 01
:00409C82 891DB8D24000            mov dword ptr [0040D2B8], ebx
:00409C88 E81FECFFFF              call 004088AC
:00409C8D 8BC3                    mov eax, ebx
:00409C8F 03C0                    add eax, eax
:00409C91 5B                      pop ebx
:00409C92 C3                      ret


Well now we know where the first decryption is done. It is applied for _GetDeviceStatus_ and 
some more routines. Lets look at the algo:

 D[i] = E[i]+D[i-1]-f(i)

 f(i) is not function of D[i] and/or E[i]
 and : f(i)  = byte [(VARi-1 * CONST1 + CONST2) mod CONST3]
       VARi  = dword[(VARi-1 * CONST1 + CONST2) mod CONST3]
       CONST1= 06262771
       CONST2= 073278AD
       CONST3= 6C
       D[-1] = 81
       VAR-1 = 07327281

 Here D[i] is the i-th decrypted byte and E[i] is the i-th encrypted.
 Now when we know this algo we can commit patches in _GetDeviceStatus_ :)
 Lets look at it what needs to be patched :))


_GetDeviceStatus_()
   :00CD997C push ebx
   :00CD997D push esi
   :00CD997E push edi
   :00CD997F push ebp
   :00CD9980 add esp, FFFFFC2C
   :00CD9986 mov ebx, eax
   :00CD9988 mov ebp, 00000007
   :00CD998D shr ebx, 1
   :00CD998F xor eax, eax
   :00CD9991 mov dword ptr [esp], eax
   :00CD9994 lea eax, dword ptr [ebx+2C]
   :00CD9997 mov eax, dword ptr [eax]
   :00CD9999 mov eax, dword ptr [eax]
   :00CD999B lea edx, dword ptr [ebx+38]
   :00CD999E mov edx, dword ptr [edx]
   :00CD99A0 mov dword ptr [esp+28], edx
   :00CD99A4 lea esi, dword ptr [ebx+68]
   :00CD99A7 push 00000000
   :00CD99A9 mov edx, dword ptr [esi+38]
   :00CD99AC push edx
   :00CD99AD call eax       <-- This is a call to FindWindowA('TAppBuilder',null)
   :00CD99AF test eax, eax  <-- if not found
   :00CD99B1 je 00CD9BD9    <-- then you are bad guy

   /////////////////////////////////////////////////////////////////////////////////
   // to always have the good jump we can patch this je 00CD9BD9 to
   // jmp 00CD99B7, where the good guys goes :)
   /////////////////////////////////////////////////////////////////////////////////

   :00CD99B7 lea edx, dword ptr [ebx+30]
   :00CD99BA mov edx, dword ptr [edx]
   :00CD99BC mov edx, dword ptr [edx]
   :00CD99BE push 00000050
   :00CD99C0 lea ecx, dword ptr [esp+00000384]
   :00CD99C7 push ecx
   :00CD99C8 push eax
   :00CD99C9 call edx       <-- This is a call to GetWindowTextA()
   :00CD99CB mov eax, dword ptr [esi+3C]  <-- This points to 'Delphi'
   :00CD99CE mov dl, byte ptr [eax]       <-- This is the window text
   :00CD99D0 cmp dl, byte ptr [esp+00000380]  <-- compares the 1-st letters
   :00CD99D7 jne 00CD9A1D
   :00CD99D9 mov dl, byte ptr [eax+01]
   :00CD99DC cmp dl, byte ptr [esp+00000381]  <-- compares the 2-nd letters
   :00CD99E3 jne 00CD9A1D
   :00CD99E5 mov dl, byte ptr [eax+02]
   :00CD99E8 cmp dl, byte ptr [esp+00000382]  <-- oh fuck the coder of this crap has been lamer :)
   :00CD99EF jne 00CD9A1D
   :00CD99F1 mov dl, byte ptr [eax+03]
   :00CD99F4 cmp dl, byte ptr [esp+00000383]
   :00CD99FB jne 00CD9A1D
   :00CD99FD mov dl, byte ptr [eax+04]
   :00CD9A00 cmp dl, byte ptr [esp+00000384]
   :00CD9A07 jne 00CD9A1D
   :00CD9A09 mov al, byte ptr [eax+05]
   :00CD9A0C cmp al, byte ptr [esp+00000385]  <-- compares till the 5-th letter
   :00CD9A13 jne 00CD9A1D
   :00CD9A15 mov dword ptr [esp], esi  <-- point to string 'DELPHI32.EXE'

   :00CD9A18 jmp MMUTIL32.00CD9A9D   <-- hope that this jumps to some more usefull code :)

   :00CD9A1D mov eax, dword ptr [esi+40]     <-- and here comes the check for 'C++Builder'
   :00CD9A20 mov dl, byte ptr [eax]
   :00CD9A22 cmp dl, byte ptr [esp+00000380]
   :00CD9A29 jne 00CD9A9D
   :00CD9A2B mov dl, byte ptr [eax+01]
   :00CD9A2E cmp dl, byte ptr [esp+00000381]
   :00CD9A35 jne 00CD9A9D
   :00CD9A37 mov dl, byte ptr [eax+02]
   :00CD9A3A cmp dl, byte ptr [esp+00000382]
   :00CD9A41 jne 00CD9A9D
   :00CD9A43 mov dl, byte ptr [eax+03]
   :00CD9A46 cmp dl, byte ptr [esp+00000383]
   :00CD9A4D jne 00CD9A9D
   :00CD9A4F mov dl, byte ptr [eax+04]
   :00CD9A52 cmp dl, byte ptr [esp+00000384]
   :00CD9A59 jne 00CD9A9D
   :00CD9A5B mov dl, byte ptr [eax+05]
   :00CD9A5E cmp dl, byte ptr [esp+00000385]
   :00CD9A65 jne 00CD9A9D
   :00CD9A67 mov dl, byte ptr [eax+06]
   :00CD9A6A cmp dl, byte ptr [esp+00000386]
   :00CD9A71 jne 00CD9A9D
   :00CD9A73 mov dl, byte ptr [eax+07]
   :00CD9A76 cmp dl, byte ptr [esp+00000387]
   :00CD9A7D jne 00CD9A9D
   :00CD9A7F mov dl, byte ptr [eax+08]
   :00CD9A82 cmp dl, byte ptr [esp+00000388]
   :00CD9A89 jne 00CD9A9D
   :00CD9A8B mov al, byte ptr [eax+09]
   :00CD9A8E cmp al, byte ptr [esp+00000389]
   :00CD9A95 jne 00CD9A9D
   :00CD9A97 lea eax, dword ptr [esi+1C]
   :00CD9A9A mov dword ptr [esp], eax

   :00CD9A9D cmp dword ptr [esp], 00000000
   :00CD9AA1 je 00CD9BD9  <-- bad boys jumps there

   :00CD9AA7 lea eax, dword ptr [ebx+14]
   :00CD9AAA mov eax, dword ptr [eax]
   :00CD9AAC mov eax, dword ptr [eax]
   :00CD9AAE mov dword ptr [esp+18], eax  <-- EAX=82C154B8

   :00CD9AB2 lea eax, dword ptr [ebx+18]
   :00CD9AB5 mov eax, dword ptr [eax]
   :00CD9AB7 mov eax, dword ptr [eax]
   :00CD9AB9 mov dword ptr [esp+20], eax  <-- EAX=82C154C8

   :00CD9ABD lea eax, dword ptr [ebx+1C]
   :00CD9AC0 mov eax, dword ptr [eax]
   :00CD9AC2 mov eax, dword ptr [eax]
   :00CD9AC4 mov dword ptr [esp+24], eax  <-- EAX=82c154d8

   :00CD9AC8 lea eax, dword ptr [ebx+3C]
   :00CD9ACB mov eax, dword ptr [eax]
   :00CD9ACD mov dword ptr [esp+08], eax  <-- EAX=00CD48E8 
                                          <--     00CD48E8 jmp KERNEL32.CloseHandle

   :00CD9AD1 lea eax, dword ptr [ebx+000000B4]
   :00CD9AD7 mov edi, dword ptr [eax]     <-- EDI=00CD9930    

   :00CD9AD9 lea eax, dword ptr [ebx+000000C0]
   :00CD9ADF mov eax, dword ptr [eax]     <-- EAX=00CD9D08

   :00CD9AE1 mov dword ptr [esp+2C], eax
   :00CD9AE5 mov eax, ebx                 <-- EAX=00CD7C18
   :00CD9AE7 call edi


      :00CD9930 push ebx
      :00CD9931 push esi
      :00CD9932 mov ebx, eax  <-- EBX=EAX=00CD7C18

      :00CD9934 lea eax, dword ptr [ebx+000000CC]
      :00CD993A mov eax, dword ptr [eax]

      :00CD993C mov esi, eax  <-- ESI=EAX=00CD8F88   <-- looks like offset
                                                     <-- of decrypting procedure
 
      :00CD993E mov eax, ebx  <-- EAX=EBX=00CD7C18   <-- looks like pointer
                                                     <-- to memory array

      :00CD9940 call esi      <-- interesting routine that creates semaphor with the name
                              <-- of DHH serail as int (if it does not exists)

      :00CD9942 lea edx, dword ptr [ebx+000000BC]
      :00CD9948 mov edx, dword ptr [edx]
      :00CD994A mov byte ptr [edx], al
      :00CD994C add ebx, 000000B8
      :00CD9952 mov edx, dword ptr [ebx]
      :00CD9954 inc dword ptr [edx]
      :00CD9956 pop esi
      :00CD9957 pop ebx
      :00CD9958 ret

   :00CD9AE9 test al, al   <-- AL=01 in both cases
   :00CD9AEB jne 00CD9AF9  <-- jumps in all cases

   :00CD9AED call [esp+2C]
   :00CD9AF1 test al, al
   :00CD9AF3 je 00CD9BD9

   :00CD9AF9 lea eax, dword ptr [ebx+44]
   :00CD9AFC mov eax, dword ptr [eax]  
   :00CD9AFE mov dword ptr [esp+1C], eax  <-- EAX=00CD995C (interesting routine)

   :00CD9B02 lea eax, dword ptr [ebx+000000B0]
   :00CD9B08 mov eax, dword ptr [eax]
   :00CD9B0A cmp dword ptr [eax], 00000002 <-- this doesnt happen in both cases
   :00CD9B0D je 00CD9BD7

///////////////////////////////////////////////////////////////////////////////
// What cames here is comparison of module names of the found 
// process with class 'TAppBuilder' with hardcoded strings.
// But this happens only if we run Win9X. Else the jump above to 
// 00CD9BD7 is executed and the next crap shit is skiped going
// directly to the routine that decrypts the rest of this funny
// mmutil32.dll. This is the reason why at first the crack run only under
// WinNT2K !!!
//
// Good patch is to patch the above jump to always jump to our good
// 00CD9BD7 offset :)
//
// See at the end how to patch it !!!
//
// note: When i traced this i still didnt know what type of routine follows below
///////////////////////////////////////////////////////////////////////////////

   :00CD9B13 lea eax, dword ptr [ebx+20]
   :00CD9B16 mov eax, dword ptr [eax]
   :00CD9B18 mov eax, dword ptr [eax]
   :00CD9B1A mov dword ptr [esp+04], eax
   :00CD9B1E push 00000000
   :00CD9B20 push 00000002
   :00CD9B22 call [esp+20]  <-- hmm. I cant trace these calls with W32DASM :((

------- LOTS OF CRAP CODE HERE
   :00CD9B26 mov dword ptr [esp+10], eax
   :00CD9B2A lea eax, dword ptr [ebx+24]
   :00CD9B2D mov eax, dword ptr [eax]
   :00CD9B2F mov eax, dword ptr [eax]
   :00CD9B31 mov dword ptr [esp+0C], eax
   :00CD9B35 mov dword ptr [esp+00000258], 00000128
   :00CD9B40 lea eax, dword ptr [esp+00000258]
   :00CD9B47 push eax
   :00CD9B48 mov eax, dword ptr [esp+14]
   :00CD9B4C push eax
   :00CD9B4D call [esp+28]
   :00CD9B51 test eax, eax
   :00CD9B53 je 00CD9BCC


   :00CD9B55 mov eax, dword ptr [esp+00000260]
   :00CD9B5C push eax
   :00CD9B5D push 00000008
   :00CD9B5F call [esp+20]
   :00CD9B63 mov dword ptr [esp+14], eax
   :00CD9B67 mov [esp+30], 00000225
   :00CD9B6F lea eax, dword ptr [esp+30]
   :00CD9B73 push eax
   :00CD9B74 mov eax, dword ptr [esp+18]
   :00CD9B78 push eax
   :00CD9B79 call [esp+0C]
   :00CD9B7D test eax, eax
   :00CD9B7F je 00CD9BAE

--- UNTIL THIS PLACE
   :00CD9B81 xor edi, edi
   :00CD9B83 mov eax, dword ptr [esp]        <--  points to 'DELPHI32.EXE'
   :00CD9B86 mov eax, dword ptr [eax+4*edi]  <--  loads string from an array in EAX
                                             <--  the array is:
                                                  'DELPHI32.EXE', 'DCC.DLL', 'DELPHIMM.DLL'
                                                  'DFWEIT.DLL', 'BORLNDMM.DLL', 'DCC40.DLL'
                                                  'DCC50.DLL', 'BCBEDIT.DLL', ...  
   :00CD9B89 lea edx, dword ptr [esp+50]     <-- 'USER32.DLL'
   :00CD9B8D call [esp+28]                   <-- [ESP+28] is 00CD9C98

     // This procedure compares the two strings
   :00CD9B91 test eax, eax
   :00CD9B93 jne 00CD9B96

   :00CD9B95 dec ebp <-- if they are equal EBP is decreased
   :00CD9B96 inc edi 

   :00CD9B97 cmp edi, 00000007
   :00CD9B9A jne 00CD9B83 <-- compares with first 7 entries in this array


   :00CD9B9C lea eax, dword ptr [esp+30]
   :00CD9BA0 push eax
   :00CD9BA1 mov eax, dword ptr [esp+18]
   :00CD9BA5 push eax
   :00CD9BA6 call [esp+14]
   :00CD9BAA test eax, eax
   :00CD9BAC jne 00CD9B81 <-- jump to process next module of found app 
                          <-- with class TAppBuilder and caption starting 
                          <-- with 'Delphi' or 'C++Builder'



   :00CD9BAE mov eax, dword ptr [esp+14]
   :00CD9BB2 push eax
   :00CD9BB3 call [esp+0C]
   :00CD9BB7 lea eax, dword ptr [esp+00000258]
   :00CD9BBE push eax
   :00CD9BBF mov eax, dword ptr [esp+14]
   :00CD9BC3 push eax
   :00CD9BC4 call [esp+2C]
   :00CD9BC8 test eax, eax
   :00CD9BCA jne 00CD9B55


   :00CD9BCC mov eax, dword ptr [esp+10]
   :00CD9BD0 push eax
   :00CD9BD1 call [esp+0C]
   :00CD9BD5 jmp MMUTIL32.00CD9BD9
   :00CD9BD7 xor ebp, ebp

   :00CD9BD9 cmp ebp, 00000003
   :00CD9BDC jg 00CD9C2E <-- This shouldn't jump
                         <-- if we like to have this shit running 
                         <-- on our Win9x machine :))

   :00CD9BDE lea eax, dword ptr [ebx+40]
   :00CD9BE1 mov eax, dword ptr [eax]
   :00CD9BE3 cmp dword ptr [eax], 00000000
   :00CD9BE6 jne 00CD9C2E

   // Remember that we had some nice decryption routine in [esp+1C] ??
   // Well here the good guys have their mmutil32.dll fully decrypted :)
   :00CD9BE8 lea edx, dword ptr [ebx+58]
   :00CD9BEB mov ecx, dword ptr [edx]
   :00CD9BED lea eax, dword ptr [ebx+54]
   :00CD9BF0 sub ecx, dword ptr [eax]
   :00CD9BF2 mov edx, dword ptr [eax]
   :00CD9BF4 mov al, 7E
   :00CD9BF6 call [esp+1C]

   :00CD9BFA lea edx, dword ptr [ebx+60]
   :00CD9BFD mov ecx, dword ptr [edx]
   :00CD9BFF lea eax, dword ptr [ebx+000000F8]
   :00CD9C05 sub ecx, dword ptr [eax]
   :00CD9C07 mov edx, dword ptr [eax]
   :00CD9C09 mov al, D3
   :00CD9C0B call [esp+1C]

   :00CD9C0F lea eax, dword ptr [ebx+34]
   :00CD9C12 mov eax, dword ptr [eax]
   :00CD9C14 mov eax, dword ptr [eax]
   :00CD9C16 mov edx, dword ptr [esi+44]
   :00CD9C19 push edx
   :00CD9C1A push 00000001
   :00CD9C1C push 00000000
   :00CD9C1E push 00000000
   :00CD9C20 call eax
   :00CD9C22 lea edx, dword ptr [ebx+000000C8]
   :00CD9C28 mov edx, dword ptr [edx]
   :00CD9C2A mov dword ptr [edx], eax
   :00CD9C2C xor ebp, ebp

   // And the bad guys come direclty here, without decription
   // of mmutil32.dll !!!
   :00CD9C2E add ebx, 00000040
   :00CD9C31 mov eax, dword ptr [ebx]
   :00CD9C33 inc dword ptr [eax]
   :00CD9C35 mov eax, ebp
   :00CD9C37 add esp, 000003D4
   :00CD9C3D pop ebp
   :00CD9C3E pop edi
   :00CD9C3F pop esi
   :00CD9C40 pop ebx
   :00CD9C41 ret


  Ok now lets calculate our patches we want to commit. The encrypted bytes i calculated 
coding a little util that helped me.
 look at the algo again if you dont remember it

   RVA             : 00CD99B1 
   Physical Offset : 00008DB1
   Instruction     : je 00CD9BD9
   encrypted           : 5F, 8E, 90, 51, C8, 4C 
   decrypted           : F0, 84, 22, 02, 00, 00 (jz  +00000222)
   patched             : 90, E9, F0, 00, 00, 00 (nop, jmp 00CD9AA7) 
   patched & encrypted : E0, 72, 7A, 65, B4, 60 

   RVA             : 00CD9B0D 
   Physical Offset : 00008F0D
   Instruction     : je 00CD9BD7
   encrypted           : 1B, 4E, FE, 68, 0A, D7
   decrypted           : F0, 84, C4, 00, 00, 00 (jz +000000C4)
   patched             : 90, E9, C4, 00, 00, 00 (nop, jmp +000000C4)  
   patched & encrypted : 9C, 32, 1A, 4C, 26, BB


Final Notes

  Well this was all. To completely crack mmutil32.dll you need to apply some more patches
like _IDERunning_ to always return true. But this function is not encrypted so you can
patch it yourself. What i mostly wanted to show is how to apply patch in crypted dll
without decrypting it :) 
  To completely crack MMTools components we need more work. You can download my unlocker
here.

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. Should you want to STEAL this software instead, you don't need to crack its protection scheme at all: you'll find it on most Warez sites, complete and already regged, farewell, don't come back.

You are deep inside Fravia's page of reverse engineering, choose your way out:


redhomepage redlinks redsearch_forms red+ORC redhow to protect redacademy database
redreality cracking redhow to search redjavascript wars
redtools redanonymity academy redcocktails redantismut CGI-scripts redmail_Fravia
redIs reverse engineering legal?