Keygening Security Administrator v8.7

by Th3 Ang3l

  • Subject: Hands on a simple keygen routine
  • Author: Th3 Ang3l
  • Author's E-mail: alphaville0202@yahoo.com
  • Rating: Beginner
  • Target: Security Administrator v8.7
  • Date: 31-08-2002
  • Tools used: W32Dasm for disassembling the target and a compiler for making the keygen
  • Knowledge Required: The basics of assembly
  • Tutorial Number: 1
     
I. Introduction

Hi to everyone. This is the first cracking tut I'm actually gonna publish so I hope you will forgive any mistakes and / or omissions that I might (surely) make.

Also keep in mind that:

  1. English is not my mother language (I'm Greek), so I'm bound to make a mistake or two (hopefully).
  2. I'm still a newbie, although I've been cracking for sometime now.

With all this in mind, read this tut and if you like it and want to see more, if there is something wrong with it or for any other kind of information or even crack requests, e-mail me at alphaville0202@yahoo.com .


II. Security Administrator Information

It's always a good idea to check the site of each of our targets. This way and if we are lucky enough, we might get a clue of the programme's protection and of course find any other information that might be useful to us. Unfortunately in this case we aren't so lucky; the page mentions nothing of the programme's protection and it only gives us an overview of its features. Here is our target's home page:

Protect your privacy and control access to your computer
  Security Administrator 
 
Version: 8.7
Date: 05/20/02
Size: 960Kb
OS: Win95/98/ME
Price: $34
This is now the Advanced Security Administrator v8.7
This version contains 82 New Restrictions. Buy it now!

Protect your computer and restrict access to Internet with Security Administrator. This nice password-protected security utility enables

 you to impose a variety of access restrictions to protect your privacy and stop others from tampering with your PC. You can deny access

 to each individual component of several Control Panel applets, including Display, Network, Passwords, Printers, System and

 Internet Options. You can disable your boot keys, context menus, DOS windows, Registry editing, Internet and Network access.

 Hide your desktop icons, individual drives, Start menu items, or even the entire taskbar. You can also apply password protection to

 Windows and restrict users to running specific applications only, Control Internet Usage, view statistics of computer use by your kids

 or employees. Security restrictions can be applied universally or to specific computer users. You'll find the program interface very easy

 to negotiate. Excellent online help is available. Try our password and security tools. Free downloads.

 

III. "Administrating" our target: Is Security Administrator all that secure?

As you might have guessed by now the answer is a plain NO. Once more we're faced with another crap protection, a typical good guy / bad guy jump, a simple patch and there you have it. Well, this time, let's try to be a little more creative: why don't we try to make a keygen out of our target? No patches, no messing around with the code, just a plain, simple, legal (yeah sure!!!) reg code. So off we go.

Disassembling the target with W32Dasm

We launch the target. Immediately, a window will appear, asking us to register, or enter the key we've received.

Well since we've lost the key ;) let's enter a bogus code and see what happens; a nice message box saying, sorry the registration code is invalid!

We could certainly use a lot of different approaches to get to our goal; for example the first time I cracked it I used Soft ICE and made the patch with a hex editor. You could also try DeDe since the program is in Delphi but for this tutorial we're gonna use W32Dasm.

OK. Enough with words. Let's disassemble our target. Do you remember the message after the bogus code we inserted? Look for it in the String Data References. Once found, double click on it and you'll get to CS:4B5EE1. Here's the code snippet:

 

* Referenced by a (U)unconditional or (C)onditional Jump at Address:

|:004B5E9C(C)

|

:004B5EDA 6A10                    push 00000010

 

* Possible StringData Ref from Code Obj ->"Error"

                                  |

:004B5EDC B9585F4B00              mov ecx, 004B5F58

 

* Possible StringData Ref from Code Obj ->"Sorry, this registration code "

                                        ->"is invalid!"

                                  |

:004B5EE1 BA605F4B00              mov edx, 004B5F60                            <==  we land here

:004B5EE6 A18CDF4C00              mov eax, dword ptr [004CDF8C]

:004B5EEB 8B00                    mov eax, dword ptr [eax]

:004B5EED E85E0BFBFF              call 00466A50

 

So what can we tell for the above code: 1) it's assembly (NO SHIT!!! Well actually if you've said it, forget cracking and go buy the new game starring Britney Spears)  2) once we entered the bogus code, our target did some calculations and JUMPED to this snippet. So it's obvious that we have to get to what's calling this function and as W32Dasm informs us it's being called at CS:004B5E9C. Let's give it a look:

 

* Referenced by a CALL at Address:

|:004A13E2  

|

:004B5E70 55                      push ebp

:004B5E71 8BEC                    mov ebp, esp

:004B5E73 51                      push ecx

:004B5E74 53                      push ebx

:004B5E75 8955FC                  mov dword ptr [ebp-04], edx

:004B5E78 8BD8                    mov ebx, eax

:004B5E7A 8B45FC                  mov eax, dword ptr [ebp-04]

:004B5E7D E8C6EEF4FF              call 00404D48

:004B5E82 33C0                    xor eax, eax

:004B5E84 55                      push ebp

:004B5E85 68085F4B00              push 004B5F08

:004B5E8A 64FF30                  push dword ptr fs:[eax]

:004B5E8D 648920                  mov dword ptr fs:[eax], esp

:004B5E90 8B55FC                  mov edx, dword ptr [ebp-04]

:004B5E93 8BC3                    mov eax, ebx

:004B5E95 E83E8EFFFF              call 004AECD8           <==  what do you think this call does?

:004B5E9A 84C0                    test al, al

:004B5E9C 743C                    je 004B5EDA                   <==  good guy / bad guy jump here

:004B5E9E A180DD4C00              mov eax, dword ptr [004CDD80]

:004B5EA3 8B00                    mov eax, dword ptr [eax]

:004B5EA5 8B4DFC                  mov ecx, dword ptr [ebp-04]

:004B5EA8 BA1C5F4B00              mov edx, 004B5F1C

:004B5EAD E8F687FDFF              call 0048E6A8

:004B5EB2 A180DD4C00              mov eax, dword ptr [004CDD80]

:004B5EB7 8B00                    mov eax, dword ptr [eax]

:004B5EB9 B201                    mov dl, 01

:004B5EBB E8CC87FDFF              call 0048E68C

:004B5EC0 6A40                    push 00000040

 

* Possible StringData Ref from Code Obj ->"Information"

                                  |

:004B5EC2 B9205F4B00              mov ecx, 004B5F20

 

* Possible StringData Ref from Code Obj ->"Registration has successfully "

                                        ->"completed!" <== we want to get here!

                                  |

:004B5EC7 BA2C5F4B00              mov edx, 004B5F2C

:004B5ECC A18CDF4C00              mov eax, dword ptr [004CDF8C]

:004B5ED1 8B00                    mov eax, dword ptr [eax]

:004B5ED3 E8780BFBFF              call 00466A50

:004B5ED8 EB18                    jmp 004B5EF2

 

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:004B5E9C(C)

|

:004B5EDA 6A10                    push 00000010

 

* Possible StringData Ref from Code Obj ->"Error"

                                  |

:004B5EDC B9585F4B00              mov ecx, 004B5F58

 

* Possible StringData Ref from Code Obj ->"Sorry, this registration code "

                                        ->"is invalid!" <== instead we end up here

                                  |

:004B5EE1 BA605F4B00              mov edx, 004B5F60

:004B5EE6 A18CDF4C00              mov eax, dword ptr [004CDF8C]

:004B5EEB 8B00                    mov eax, dword ptr [eax]

:004B5EED E85E0BFBFF              call 00466A50

 

I've copied a lot of code, but just to make it easier for you to follow the programme flow. It starts by storing values in the stack, then it clears the accumulator to make space and then pushes our code in edx; after that a CALL (nothing important) and then if ax is zero, jump to 4B5EDA that leads us to registration code invalid, or else continue to Registration successful.

Now if you want to end things right away you can simply change the JE to JNE (or even better, change the TEST AL,AL to INC AX), but if you just bear with me a little longer, you will learn how to actually obtain a valid registration key (which means no change to our target's code, i.e. the perfect crack), and what's more important you will become familiar with a new technique. Remember that cracking (the appropriate term should be reversing) is all about gaining knowledge and mastering new techniques. It has nothing to do with crack-target-quickly, -release-target, -release-100-patches-for-crack-'cause-I-didn't-even-check-it, ideology that some cracking / warez groups are following (no, Microsoft is not a warez group). So please remember to always take your time and try to crack the same target using different methods. This way, you'll form a good arsenal of knowledge and a correct background that will help you use it.

 

IV. Serial fishing

The Algorithm 

Now since we've decided to not wanna patch anything, it's obvious that what interests us is that CALL. Let's dive in:

 

* Referenced by a CALL at Addresses:

|:004AFAAF   , :004B5E95  

|

:004AECD8 55                      push ebp

:004AECD9 8BEC                    mov ebp, esp

:004AECDB 51                      push ecx

:004AECDC 53                      push ebx

:004AECDD 56                      push esi

:004AECDE 8955FC                  mov dword ptr [ebp-04], edx

:004AECE1 8BF0                    mov esi, eax

:004AECE3 8B45FC                  mov eax, dword ptr [ebp-04]

:004AECE6 E85D60F5FF              call 00404D48

 

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:004AEC84(C)

|

:004AECEB 33C0                    xor eax, eax

:004AECED 55                      push ebp                      <==  we land here

:004AECEE 6851EE4A00              push 004AEE51

:004AECF3 64FF30                  push dword ptr fs:[eax]

:004AECF6 648920                  mov dword ptr fs:[eax], esp

:004AECF9 33DB                    xor ebx, ebx

:004AECFB C6053C024D0000          mov byte ptr [004D023C], 00

:004AED02 B840024D00              mov eax, 004D0240

:004AED07 E89C5BF5FF              call 004048A8

:004AED0C 837DFC00                cmp dword ptr [ebp-04], 00000000  <==  code is blank ?

:004AED10 0F8425010000            je 004AEE3B                  <==  if no, continue, else jump to end

:004AED16 8B45FC                  mov eax, dword ptr [ebp-04]  <==  eax now stores our code

:004AED19 E8425EF5FF              call 00404B60

:004AED1E 83F80C                  cmp eax, 0000000C <==  our code has 12 letters ?

:004AED21 740C                    je 004AED2F            <==  if yes, jump to start of algo else

:004AED23 8B45FC                  mov eax, dword ptr [ebp-04]      <==  store our code in eax

:004AED26 803838                  cmp byte ptr [eax], 38                  <==  is the 1st character an 8 ?

:004AED29 0F850C010000            jne 004AEE3B                       <==  if no jump to end

 

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:004AED21(C)

|

:004AED2F 8B45FC                  mov eax, dword ptr [ebp-04] <==  Algo starts. eax has our code

:004AED32 803838                  cmp byte ptr [eax], 38       <==  is our 1st character 38 (an 8) ?

:004AED35 0F8500010000            jne 004AEE3B             <==  if no, jump to end, else continue

:004AED3B 8B45FC                  mov eax, dword ptr [ebp-04]

:004AED3E 80780233                cmp byte ptr [eax+02], 33<==  is our 3rd character 33 (a 3) ?

:004AED42 0F85F3000000            jne 004AEE3B

:004AED48 8B45FC                  mov eax, dword ptr [ebp-04]

:004AED4B 80780331                cmp byte ptr [eax+03], 31<==  is our 4th character 31 (a 1) ?

:004AED4F 0F85E6000000            jne 004AEE3B

:004AED55 8B45FC                  mov eax, dword ptr [ebp-04]

:004AED58 80780439                cmp byte ptr [eax+04], 39<==  is our 5th character 39 (a 9) ?

:004AED5C 0F85D9000000            jne 004AEE3B

:004AED62 8B45FC                  mov eax, dword ptr [ebp-04]

:004AED65 80780830                cmp byte ptr [eax+08], 30<==  is our 9th character 30 (a 0) ?

:004AED69 0F85CC000000            jne 004AEE3B

:004AED6F 8B45FC                  mov eax, dword ptr [ebp-04]

:004AED72 80780935                cmp byte ptr [eax+09], 35<==  is our 10th character 35 (a 5) ?

:004AED76 0F85BF000000            jne 004AEE3B

:004AED7C 8B45FC                  mov eax, dword ptr [ebp-04]

:004AED7F 80780A53                cmp byte ptr [eax+0A], 53<== is our 11th character 53 (an S) ?

:004AED83 0F85B2000000            jne 004AEE3B

:004AED89 8B45FC                  mov eax, dword ptr [ebp-04]

:004AED8C 80780B45                cmp byte ptr [eax+0B], 45<== is our 12th character 45 (an E) ?

:004AED90 0F85A5000000            jne 004AEE3B

:004AED96 B840024D00              mov eax, 004D0240

:004AED9B 8B55FC                  mov edx, dword ptr [ebp-04]

:004AED9E E8595BF5FF              call 004048FC

:004AEDA3 C6053C024D0001          mov byte ptr [004D023C], 01

:004AEDAA B301                    mov bl, 01

:004AEDAC 33D2                    xor edx, edx

 

V. Keygen time

The code is a bit long but it's quite straightforward. In any case I hope the comments are helpful.

So the way our code should look is this: 8 x 3 1 9 x x x 0 5 S E

Where an x is any kind of value. Wasn't that easy after all? All we have to do now is make a keygen. Mine is in Java and it's included in this tut (I know that most of the keygens are in C / C++ but I'm currently learning Java and wanted to experiment a bit. Anyway I know the code sucks so don't complain).

This keygen should work for all versions of the programme from v8.1 to v8.7

 

VI. Greetings, thanxs and other ass licking stuff

That's all folks. Before going to sleep (shit it's 5 in the morning), I'd like to send a big salute and thanxs to Krobar (you're doing a great job man) and to all those reversers that helped me out on my first steps, with their tutorials (ORC, Fravia, Razzia and lots and lots of others. Guys your work is really valuable to us all).

Remember to e-mail me if you have any subject you would like to see explained in an upcoming tutorial (that's it if I can explain it). That's REALLY all folks. Until my next tut.

Ending Note: Please bear in mind that our main goal in cracking is not to avoid buying the program we've cracked, but to actually understand its protection and find ways to override it. In simple words: GAIN KNOWLEDGE. So if you like a program please consider buying it. Remember that programmer's (sometimes) work really hard and there are lots of programmes out there that really deserve its money. Also remember that this tutorial is for EDUCATIONAL PURPOSES ONLY and that the author has NO RESPONSIBILITY for your actions.
Copyright stuff:
This tutorial was written by Th3 Ang3l © 2001-2002 and it can be freely distributed, published, printed or anything else, as long as no modifications are made.

Den elpizo se tipota, de fovamai tipota, eimai eleftheros

Nikos Kazantzakis