Desktop Server 98
Why should we register it?
student
Not Assigned
3 May 1998
by +dynamite
Courtesy of Reverser's page of reverse engineering
slightly edited
by reverser+
fra_00xx
980503
+dynamite
1100
NA
PC
So, this is (clearly) an essay written by a beginner. +dynamite writes too much code, instead of explaining the "philosophy" of his session... he relies much too much on the "specifity" of his own target.
Yet I'm publishing it in the 'essays for beginners' section. For various reasons: Because I am sure that this reverser will grow and send much better works in the future (I feel it). Because this is a good work notwithstanding the tons of code, and deserves to be followed and studied. Because this protection has TWO valid keys (which is not THAT common, after all). Because every reverser that cracks a target that DOES NOT NEED to be cracked in order to work has my unconditional admiration... less code and more theory next time +dynamite! Welcome in the +HCU!
There is a crack, a crack in everything That's how the light gets in
Rating
(x)Beginner ( )Intermediate ( )Advanced ( )Expert

In this essay, you will not only NOP out a jump. You will get the correct unlock key for the entered serial#.
Desktop Server 98
Why should we crack a program that DOES NOT CHANGE at all if you do register it or not?
Written by +dynamite


Introduction

Desktop Server 98 is a program to send emails without an outgoing mail server. It's very curious because if you successfully register your copy of Dektop Server, there will be no changes you can see. So, why should we crack it? The answer is simple. Just to enlarge your knowledge!

Tools required
SoftICE 3.0+
W32Dasm (I'm using version 8.9)
Desktop Server 98

Target's URL/FTP
www.desktopserver98.com

Essay

If you run DS98 (Desktop Server 98), you will note, that it's a simple s/n protection. Just enter any serial# and any unlock key (I used serial:+dynamite / key:12121212). When you press OK, a nag will popup, and tells you, that your key doesn't match the serial. Let's load DSKTPSVR.EXE into W32Dasm and search for the words in the nag. You will find the following piece of code:

:0047F385 E852DAFEFF              call 0046CDDC; Check the key
:0047F38A 84C0                    test al, al; If al = 0 Then WrongUnlockKey
:0047F38C 7472                    je 0047F400; Jump if key is bad, else go on
:0047F38E A1C4614800              mov eax, dword ptr [004861C4]
:0047F393 8B00                    mov eax, dword ptr [eax]
:0047F395 E8E62A0000              call 00481E80
:0047F39A 8D55F8                  lea edx, dword ptr [ebp-08]
:0047F39D A10C614800              mov eax, dword ptr [0048610C]
:0047F3A2 8B00                    mov eax, dword ptr [eax]
:0047F3A4 8B80E4010000            mov eax, dword ptr [eax+000001E4]
:0047F3AA E8CD30FAFF              call 0042247C
:0047F3AF 8B55F8                  mov edx, dword ptr [ebp-08]
:0047F3B2 8B83F8020000            mov eax, dword ptr [ebx+000002F8]
:0047F3B8 0598020000              add eax, 00000298
:0047F3BD E8BA47F8FF              call 00403B7C
:0047F3C2 8B83F8020000            mov eax, dword ptr [ebx+000002F8]
:0047F3C8 E83FD1FEFF              call 0046C50C

* Possible StringData Ref from Code Obj ->"Registration succeeded"
                                  |
:0047F3CD B864F44700              mov eax, 0047F464
:0047F3D2 E855D7FBFF              call 0043CB2C; SuccessfullyReged_Window pops up
:0047F3D7 C683FC02000000          mov byte ptr [ebx+000002FC], 00
:0047F3DE 8B83F8020000            mov eax, dword ptr [ebx+000002F8]
:0047F3E4 05D8020000              add eax, 000002D8

* Possible StringData Ref from Code Obj ->"Destop Server 98 Unlock"
                                  |
:0047F3E9 BA84F44700              mov edx, 0047F484
:0047F3EE E88947F8FF              call 00403B7C
:0047F3F3 8B83F8020000            mov eax, dword ptr [ebx+000002F8]
:0047F3F9 8B10                    mov edx, dword ptr [eax]
:0047F3FB FF5244                  call [edx+44]
:0047F3FE EB2C                    jmp 0047F42C

* Referenced by a Jump at Address:0047F38C(C)
|

* Possible StringData Ref from Code Obj ->"Key doesn't match serial number"
                                  |
:0047F400 B8A4F44700              mov eax, 0047F4A4
:0047F405 E822D7FBFF              call 0043CB2C; WrongUnlockKey_Window pops up
:0047F40A 8B83F8020000            mov eax, dword ptr [ebx+000002F8]
:0047F410 E867D2FEFF              call 0046C67C
:0047F415 EB15                    jmp 0047F42C

We could easily patch this, by NOPing the "JE 0047F400" at :0047F38C. But that's not good. We want to get a valid unlock key. So look into the KeyCheckFunction at :0046CDDC.

* Referenced by a CALL at Address:0047F385   
|
:0046CDDC 53                      push ebx
:0046CDDD 56                      push esi
:0046CDDE 57                      push edi
:0046CDDF 83C4B4                  add esp, FFFFFFB4
:0046CDE2 8BF1                    mov esi, ecx
:0046CDE4 8D3C24                  lea edi, dword ptr [esp]
:0046CDE7 33C9                    xor ecx, ecx
:0046CDE9 8A0E                    mov cl, byte ptr [esi]
:0046CDEB 80F909                  cmp cl, 09
:0046CDEE 7202                    jb 0046CDF2
:0046CDF0 B109                    mov cl, 09

* Referenced by a Jump at Address:0046CDEE(C)
|
:0046CDF2 880F                    mov byte ptr [edi], cl
:0046CDF4 46                      inc esi
:0046CDF5 47                      inc edi
:0046CDF6 F3                      repz
:0046CDF7 A4                      movsb
:0046CDF8 8BF2                    mov esi, edx
:0046CDFA 8D7C240A                lea edi, dword ptr [esp+0A]
:0046CDFE 33C9                    xor ecx, ecx
:0046CE00 8A0E                    mov cl, byte ptr [esi]
:0046CE02 80F932                  cmp cl, 32
:0046CE05 7202                    jb 0046CE09
:0046CE07 B132                    mov cl, 32

* Referenced by a Jump at Address:0046CE05(C)
|
:0046CE09 880F                    mov byte ptr [edi], cl
:0046CE0B 46                      inc esi
:0046CE0C 47                      inc edi
:0046CE0D F3                      repz
:0046CE0E A4                      movsb
:0046CE0F 8BF0                    mov esi, eax
:0046CE11 33DB                    xor ebx, ebx
:0046CE13 889E75030000            mov byte ptr [esi+00000375], bl
:0046CE19 8D442440                lea eax, dword ptr [esp+40]
:0046CE1D 50                      push eax
:0046CE1E 8BCB                    mov ecx, ebx
:0046CE20 8D54240E                lea edx, dword ptr [esp+0E]
:0046CE24 8BC6                    mov eax, esi
:0046CE26 E805FEFFFF              call 0046CC30
:0046CE2B 8D442440                lea eax, dword ptr [esp+40]
:0046CE2F 8BD4                    mov edx, esp
:0046CE31 33C9                    xor ecx, ecx
:0046CE33 8A08                    mov cl, byte ptr [eax]
:0046CE35 41                      inc ecx
:0046CE36 E8395DF9FF              call 00402B74; Check the unlock key
:0046CE3B 0F94C0                  sete al; Set AL = 1, if equal
:0046CE3E 84C0                    test al, al; Key OK?
:0046CE40 7538                    jne 0046CE7A
:0046CE42 B301                    mov bl, 01
:0046CE44 889E75030000            mov byte ptr [esi+00000375], bl
:0046CE4A 8D442440                lea eax, dword ptr [esp+40]
:0046CE4E 50                      push eax
:0046CE4F 8BCB                    mov ecx, ebx
:0046CE51 8D54240E                lea edx, dword ptr [esp+0E]
:0046CE55 8BC6                    mov eax, esi
:0046CE57 E8D4FDFFFF              call 0046CC30
:0046CE5C 8D442440                lea eax, dword ptr [esp+40]
:0046CE60 8BD4                    mov edx, esp
:0046CE62 33C9                    xor ecx, ecx
:0046CE64 8A08                    mov cl, byte ptr [eax]
:0046CE66 41                      inc ecx
:0046CE67 E8085DF9FF              call 00402B74; Check the unlock key
:0046CE6C 0F94C0                  sete al; Set AL = 1, if equal
:0046CE6F 3C01                    cmp al, 01; Key OK?
:0046CE71 7507                    jne 0046CE7A
:0046CE73 C6867503000001          mov byte ptr [esi+00000375], 01

* Referenced by a Jump at Addresses:0046CE40(C), :0046CE71(C)
|
:0046CE7A 83C44C                  add esp, 0000004C
:0046CE7D 5F                      pop edi
:0046CE7E 5E                      pop esi
:0046CE7F 5B                      pop ebx
:0046CE80 C3                      ret

You know, that it depends on the value in AX, if the key is valid or not. So we can search for the last place in the function, where AL gets set. We note the two places, where AL is set to 1 if zeroflag is set (sete al). So we found the function, that compares our entered unlock key with the correct one. Now look into the function, to find the place, where our key gets compared.


* Referenced by a CALL at Addresses:
|:0040348A   , :0045250C   , :00452523   , :004534E7   , :00453533   
|:00453546   , :00455983   , :00456343   , :0045636E   , :004563B2   
|:004563D9   , :004563FF   , :0046CE36   , :0046CE67   
|
:00402B74 53                      push ebx
:00402B75 56                      push esi
:00402B76 51                      push ecx
:00402B77 89CE                    mov esi, ecx
:00402B79 C1EE02                  shr esi, 02
:00402B7C 7426                    je 00402BA4

* Referenced by a Jump at Address:00402B9A(C)
|
:00402B7E 8B08           mov ecx, dword ptr [eax]; Move the first 4 bytes of the VALID
                            unlock key to ECX. The first byte is the length of the key
:00402B80 8B1A           mov ebx, dword ptr [edx]; Move the first 4 bytes of the entered
                            unlock key to EBX
:00402B82 39D9           cmp ecx, ebx; Compare the first 4 bytes
:00402B84 7545           jne 00402BCB; Jump if they doesn't match
:00402B86 4E             dec esi
:00402B87 7415           je 00402B9E
:00402B89 8B4804         mov ecx, dword ptr [eax+04]; Move the next 4 bytes of the
  			    valid key to ECX
:00402B8C 8B5A04         mov ebx, dword ptr [edx+04]; Move the next 4 bytes of the
  			    entered key to EBX
:00402B8F 39D9           cmp ecx, ebx; Compare the 4 bytes
:00402B91 7538           jne 00402BCB; Jump if they doesn't match
:00402B93 83C008         add eax, 00000008
:00402B96 83C208         add edx, 00000008
:00402B99 4E             dec esi
:00402B9A 75E2           jne 00402B7E
:00402B9C EB06           jmp 00402BA4

* Referenced by a Jump at Address:00402B87(C)
|
:00402B9E 83C004                  add eax, 00000004
:00402BA1 83C204                  add edx, 00000004

* Referenced by a Jump at Addresses:00402B7C(C), :00402B9C(U)
|
:00402BA4 5E             pop esi
:00402BA5 83E603         and esi, 00000003
:00402BA8 7436           je 00402BE0
:00402BAA 8A08           mov cl, byte ptr [eax]; Move next byte of valid key to CL
:00402BAC 3A0A           cmp cl, byte ptr [edx]; Compare the byte of the valid key
  			    with the one from the entered key
:00402BAE 7530           jne 00402BE0; Jump if they doesn't match
:00402BB0 4E             dec esi
:00402BB1 7413           je 00402BC6; Jump if end of key
:00402BB3 8A4801         mov cl, byte ptr [eax+01]; Move next byte of valid key to CL
:00402BB6 3A4A01         cmp cl, byte ptr [edx+01]; Compare the byte of the valid key
  			    with the one from the entered key
:00402BB9 7525           jne 00402BE0; Jump if they doesn't match
:00402BBB 4E             dec esi
:00402BBC 7408           je 00402BC6; Jump if end of key
:00402BBE 8A4802         mov cl, byte ptr [eax+02]; Move the last byte of the valid
  			   key to CL
:00402BC1 3A4A02         cmp cl, byte ptr [edx+02]; Compare the last byte of the valid
  			   key with the one from the entered key
:00402BC4 751A           jne 00402BE0; Jump if the doesn't match

* Referenced by a Jump at Addresses:00402BB1(C), :00402BBC(C)
|
:00402BC6 31C0           xor eax, eax; Erase EAX
:00402BC8 5E             pop esi
:00402BC9 5B             pop ebx
:00402BCA C3             ret

Okey. If you want to know the valid key for your entered serial#, just enter "D EAX" at :00402B7E, and you will see it. Easy, isn't it? ;)
But remember, that there was a second jump to this function. The first jump was at :0046CE36 and the second was at :0046CE67. Our key is checked twice. But everytime with another valid key. That means, that there are two valid keys for one serial#. Here are my keys for all the poor lamers in the world, that will never be able to crack:

Serial#: +dynamite
Key_1:   $A655BFBD
Key_2:   $CC7C8C7B


Final Notes
That was it. I hope you enjoyed it.
This was my first essay to the +HCU.

Greets are going to +ORC and all other +HCUkers.



(c) +dynamite (dynamite_@gmx.net)


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.

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

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

--- The end of the HTML code ---