home *** CD-ROM | disk | FTP | other *** search
/ Hacks & Cracks / Hacks_and_Cracks.iso / hackersclub / km / library / cracking / razzia-keygen.txt < prev    next >
Text File  |  1998-03-25  |  17KB  |  359 lines

  1. raZZia's Tutorial on Key Generators (01-97)
  2.  
  3. Tools!
  4.      For tools you need a minimum of debugger like SoftIce for Windows
  5.      (hence WinIce), and a C compiler with Dos libraries.
  6.  
  7. Content!
  8.      In this tutorial I will show how to make a key-gen for Ize and
  9.      Swiftsearch. The protection that these programs use is the well known
  10.      Enter-Name-and-Registration-Number method. After selecting 'register',
  11.      a window pops up where you can enter your name and your registration
  12.      number. The strategy here is to find out where in memory the data you
  13.      enter is stored and then to find out what is done with it. Before you
  14.      go on make sure you configure the SoftIce dat file according to the
  15.      PWD tutorial #1.
  16.  
  17. Case 1: Scanline Swiftsearch 2.0!
  18.      Swiftsearch is a useful little program that you can use to search on
  19.      the web. I will explain step by step how to crack it.
  20.  
  21.      step 1: Start the program :)
  22.  
  23.      step 2: Choose register from the menus. You will now get a window
  24.      where you can enter your name and your registration number.
  25.  
  26.      step 3: Enter SoftIce (ctrl-d)
  27.  
  28.      step 4: We will now set a breakpoint on functions like
  29.      GetWindowText(a) and GetDlgItemText(a) to find out where in memory the
  30.      data that we just entered is stored. The function that is used by this
  31.      program is GetDlgItemTexta (trial and error, just try yourself :) so,
  32.      in SoftIce type BPX GetDlgItemTexta and exit SoftIce with the g
  33.      command.
  34.  
  35.      step 5: Now type a name and a registration number (I used razzia and
  36.      12345) and press OK, this will put you back in SoftIce. Since you are
  37.      now inside the GetDlgItemTexta function press F11 to get out of it.
  38.      You should see the following code:
  39.  
  40.      lea eax, [ebp-2C]          ;<--- we are looking for this location
  41.      push eax
  42.      push 00000404
  43.      push [ebp+08]
  44.      call [USER32!GetDlgItemTextA]
  45.      mov edi, eax               ;<--- eax has the length of the string
  46.                                  and is stored in edi for later usage.
  47.  
  48.      We see that EAX is loaded with a memory address and then pushed to the
  49.      stack as a parameter for the function GetDlgItemTextA. Since the
  50.      function GetDlgItemTextA is already been run we can look at EBP-2c
  51.      (with ED EDP-2c) and see that the name we entered is there. Now we
  52.      know where the name is stored in memory, normally it would be wise to
  53.      write that address down, but we will see that in this case it wont be
  54.      necessary.
  55.  
  56.      So, what next? Now we have to allow the program to read the
  57.      registration number we entered. Just type g and return and when back
  58.      in SoftIce press F11. You should see the following code:
  59.  
  60.      push 0000000B
  61.      lea ecx, [ebp-18]         ;<--So, ebp-18 is where the reg. number
  62.      push ecx                  :    is stored.
  63.      push 0000042A
  64.      push [ebp+08]
  65.      call [USER32!GetDlgItemTextA]
  66.      mov ebx, eax              ;<--save the lenght of string in EBX
  67.      test edi, edi             ;<--remember EDI had the lenght of the
  68.      jne 00402FBF              :    name we entered?
  69.  
  70.      We see that the registration number is stored at location EBP-18 ,
  71.      check it with ED EBP-18. Again, normally it would be wise to note that
  72.      address down. Also we see that it is checked if the length of the name
  73.      we gave was not zero. If it is not zero the program will continue.
  74.  
  75.      Step 6: Ok, now we know where the data we entered is stored in memory.
  76.      What next?
  77.      Now we have to find out what is DONE with it. Usually it would we wise
  78.      to put breakpoints on those memory locations and find out where in the
  79.      program they are read. But in this case the answer is just a few F10's
  80.      away. Press F10 until you see the following code :
  81.  
  82.      cmp ebx, 0000000A       ;<--remember EBX had the length of the
  83.      je 00402FDE             :   registration code we entered?
  84.  
  85.      These two lines are important. They check if the length of the
  86.      registration code we entered is equal to 10. If not the registration
  87.      number will be considered wrong already. The program wont even bother
  88.      to check it. Modify EBX or the FLAG register in the register window to
  89.      allow the jump. Continue Pressing F10 until you get to the following
  90.      code (note that the adresses you will see could be different) :
  91.  
  92.      :00402FDE xor esi, esi        ;<-- Clear ESI
  93.      :00402FE0 xor eax, eax        ;<-- Clear EAX
  94.      :00402FE2 test edi, edi
  95.      :00402FE4 jle 00402FF2
  96.      :00402FE6 movsx byte ptr ecx, [ebp + eax - 2C] ;<-- ECX is loaded with a letter of the  name we entered.
  97.      :00402FEB add esi, ecx        ;<-- Add the letter to ESI
  98.      :00402FED inc eax             ;<-- Increment EAX to get next letter
  99.      :00402FEE cmp eax, edi        ;<-- Did we reach the end of the string?
  100.      :00402FF0 jl 00402FE6         ;<-- If not, go get the next letter.
  101.  
  102.      Well, we see that the program adds together all the letters of the
  103.      name we entered. Knowing that ESI contains the sum of the letters,
  104.      lets continue and find out what the program does with that value :
  105.  
  106.      :00402FF2 push 0000000A
  107.      :00402FF4 lea eax, [ebp-18]   ;<-- Load EAX with the address of the reg. number we entered
  108.      :00402FF7 push 00000000
  109.      :00402FF9 push eax            ;<-- Push EAX (as a parameter for the following function)
  110.      :00402FFA call 00403870       ;<-- Well, what do you think this function does? :)
  111.      :00402FFF add esp, 0000000C
  112.      :00403002 cmp eax, esi        ;<-- Hey!
  113.      :00403004 je 00403020
  114.  
  115.      We see that a function is called and when RETurned ESI is compared
  116.      with EAX. Hmm, lets look at what's in EAX. A '? EAX' reveals :
  117.      00003039 0000012345 "09"
  118.  
  119.      Bingo. That's what we entered as the registration number. It should
  120.      have been what's inside ESI. And we know what's inside ESI, the sum of
  121.      the letters of the name we entered!
  122.  
  123.      Step 7: Now we know how the program computes the registration code we
  124.      can make a key-gen.
  125.      But we should not forget that the program checks also that the
  126.      registration number has 10 digits.
  127.      A simple C code that will compute the registration number for this
  128.      program could look like this:
  129.  
  130.      #include   <stdio.h>
  131.      #include   <string.h>
  132.      main() {
  133.         char Name[100];
  134.         int NameLength,Offset;
  135.         long int Reg = 0, Dummy2 = 10;
  136.         int Dummy = 0;
  137.         int LengtDummy = 1;
  138.         int Lengt , Teller;
  139.         printf("Scanline SwiftSearch 2.0 crack by raZZia.\n");
  140.         printf("Enter your name: ");
  141.         gets(Name);
  142.         NameLength=strlen(Name);
  143.  
  144.      /* the for lus calculates the sum of the letters in Name */
  145.      /* and places that value in Reg                          */
  146.         for (Offset=0;Offset<NameLength;Offset=Offset+1) {
  147.            Reg=Reg+Name[Offset];
  148.         }
  149.  
  150.      /* the while lus calculates the lenght of the figure in */
  151.      /* Reg and places it in Lengt                           */
  152.         while (Dummy != 1) {
  153.            if ( Reg < Dummy2 ) {
  154.               Lengt = LengtDummy ; Dummy =1;
  155.            }
  156.               else {
  157.                  LengtDummy=LengtDummy + 1; Dummy2=Dummy2*10;
  158.               }
  159.         };
  160.  
  161.         printf("\nYour registration number is : " );
  162.  
  163.      /* First print 10-Lengt times a 0                        */
  164.         Lengt=10-Lengt;
  165.         for (Teller=1;Teller<=Lengt;Teller=Teller+1) printf("0");
  166.      /* Then print the registration number                    */
  167.         printf("%lu\n",Reg);
  168.      }
  169.  
  170. Case 2: Ize 2.04 from Gadgetware
  171.      Ize from Gadgetware is a cute little program that will put a pair of
  172.      eyes on your screen which will follow your mousepointer. It has a
  173.      register function where you can enter your name and a registration
  174.      number. The strategy in this case is still the same : Find out where
  175.      in memory the entered information is stored and then find out what is
  176.      done with that information.
  177.  
  178.      Step 1: Start Ize. Chose register and enter a name and a number. I
  179.      used 'razzia' and '12345'.
  180.  
  181.      Sterp 2: Enter (CTRL-D) Softice and set a breakpoint on
  182.      GetDlgItemTextA.
  183.  
  184.      Step 3: Leave SoftIce and press OK. This will put you back in Softice.
  185.      You will be inside the GetDlgItemTextA function. To get out of it
  186.      press F11. You should see the following code :
  187.  
  188.      mov esi, [esp + 0C]
  189.      push 00000064
  190.      push 0040C3A0      ;<--On this memory location the NAME we entered will be stored.
  191.      mov edi, [USER32!GetDlgItemTextA]  ;<--Load edi with adress of GetDlgItemTextA
  192.      push 00004EE9
  193.      push esi
  194.      call edi           ;<-- Call GetDlgItemTextA
  195.      push 00000064            ;<-- (you should be here now)
  196.      push 0040C210      ;<--On this memory location the NUMBER we entered will be stored
  197.      push 00004EEA
  198.      push esi
  199.      call edi           ;<-- Call GetDlgItemTextA
  200.  
  201.      We see that the function GetDlgItemTextA is called twice in this code
  202.      fragment. The first call has already happened. With ED 40C3A0 we can
  203.      check that the name we entered is stored on that location.
  204.  
  205.      To allow the program to read in the number we entered we type G and
  206.      enter. Now we are inside the GetDlgItemTextA function again and we
  207.      press f11 to get out of it. We check memory location 40C210 and we see
  208.      the number we entered is stored there.
  209.  
  210.      Now we know the locations were the name and the number are stored,we
  211.      note those down!
  212.  
  213.      Step 4: Ok, what next? We now know where in memory the name and the
  214.      number are stored. We need to find out what the program does with
  215.      those values. In order to do that we could set breakpoints on those
  216.      memory locations to see where they are read. But in this case it wont
  217.      be necessary. The answer is right after the above code :
  218.  
  219.      push 0040C210  ;<--save the location of the number we entered (as a parameter for the next call)
  220.      call 00404490  ;<-- call this unknown function
  221.      add esp, 00000004
  222.      mov edi, eax  ;<-- save EAX  (hmmmm)
  223.  
  224.      We see a function being called with the number-location as a
  225.      parameter. We could trace into the function and see what it does, but
  226.      that is not needed. With your experience of the Swiftsearch example
  227.      you should be able to guess what this function does. It calculates the
  228.      numerical value of the registration number and puts it in EAX. To be
  229.      sure we step further using F10 untill we are past the call and check
  230.      the contents of EAX (with ? EAX). In my case it showed : 00003039
  231.      0000012345 "09".
  232.  
  233.      Knowing that EDI contains our registration number we proceed:
  234.  
  235.      push 0040C3A0 ;<-- save the location of the name we entered (as a parameter for the next call)
  236.      push 00409080 ;<-- save an unknown memory-location (as a parameter for the next call)
  237.      call 004043B0 ;<--call to an unknown function
  238.      add esp, 00000008
  239.      cmp edi, eax  ;<--compare EDI (reg # we entered) with EAX (unknown, since the previous call                                                                                         change
  240.      jne 004018A1  ;<--jump if not equal
  241.  
  242.      We see that a function is called with two parameters. One of the
  243.      parameters is the location of the name we entered. The other we dont
  244.      know, but we can find out with ED 409080. We see the text 'Ize'. This
  245.      function calculates the right registration number using those two
  246.      parameters. If you just want to crack this program, you can place a
  247.      breakpoint right after the call and check the contents of EAX. It will
  248.      contain the right registration number. But since we want to know HOW
  249.      the reg. # is calculated we will trace inside the function (using T).
  250.      We will then try to find out HOW the contents of EAX got in there.
  251.  
  252.      Step 5: Once inside the interesting function you will see that we are
  253.      dealing with a rather long function. It wont be necessary for me to
  254.      include the complete listing of this function, because we wont need
  255.      all of it to make our key-gen.
  256.  
  257.      But in order find out which part of the code is essential for the
  258.      computation of the right registration number, you have to trace STEP
  259.      by STEP and figure out what EXACTLY is going on!
  260.  
  261.      Afther doing this i found out that the first part of the function
  262.      computes some kind of "key". Then this "key" is stored in memory and
  263.      in that way passed on to the second part of the function.
  264.  
  265.      The second part of the function then computes the right registration
  266.      number, based on this "key" AND the name we entered.
  267.  
  268.      The code that is essential and that we need for our key-gen is the
  269.      following:
  270.  
  271.      (Note that before the following code starts, the registers that are
  272.      used will have the following values: EBX will point to the first
  273.      letter of the name we entered, EDX will be zero, EBP will be zero, the
  274.      "key" that we talked about earlier is stored in memory location
  275.      0040B828 and will have 0xA4CC as its initial value.)
  276.  
  277.      :00404425 movsx byte ptr edi, [ebx + edx]   ;<-- Put first letter of the name in EDI
  278.      :00404429 lea esi, [edx+01] ;<-- ESI gets the "letter-number"
  279.      :0040442C call 00404470  ;<-- Call  function
  280.      :00404431 imul edi, eax  ;<-- EDI=EDI*EAX (eax is the return value of the the previous call)
  281.      :00404434 call 00404470  ;<-- Call function
  282.      :00404439 mov edx, esi
  283.      :0040443B mov ecx, FFFFFFFF
  284.      :00404440 imul edi, eax  ;<-- EDI=EDI*EAX (eax is the return value of the previous call)
  285.      :00404443 imul edi, esi  ;<-- EDI=EDI*ESI ( esi is the number of the letter position)
  286.      :00404446 add ebp, edi  ;<-- EBP=EBP+EDI  (beware that EBP will finally contain the right reg#)
  287.      :00404448 mov edi, ebx  ;<--these lines compute the lenght of the name we entered
  288.      :0040444A sub eax, eax  ;<--these lines compute the lenght of the name we entered
  289.      :0040444C repnz      ;<--these lines compute the lenght of the name we entered
  290.      :0040444D scasb      ;<--these lines compute the lenght of the name we entered
  291.      :0040444E not ecx       ;<--these lines compute the lenght of the name we entered
  292.      :00404450 dec ecx            ;<-- ECX now contains the lenght of the name
  293.      :00404451 cmp ecx, esi
  294.      :00404453 ja 00404425   ;<-- If its not the end of the name , go do the same with the next letter
  295.      :00404455 mov eax, ebp  ;<--  SAVE EBP TO EAX !!!!
  296.      :00404457 pop ebp
  297.      :00404458 pop edi
  298.      :00404459 pop esi
  299.      :0040445A pop ebx
  300.      :0040445B ret
  301.             _____
  302.  
  303.      :00404470 mov eax, [0040B828]     ;<-- Put "key" in EAX
  304.      :00404475 mul eax, eax, 015A4E35  ;<-- EAX=EAX * 15A4E35
  305.      :0040447B inc eax                      ;<-- EAX=EAX + 1
  306.      :0040447C mov [0040B828], eax     ;<-- Replace the "key" with the new value of EAX
  307.      :00404481 and eax, 7FFF0000       ;<-- EAX=EAX && 7FFF0000
  308.      :00404486 shr eax, 10             ;<-- EAX=EAX >>10
  309.      :00404489 ret
  310.  
  311.      The above code consists of a loop that goes trough all the letters of
  312.      the name we entered. With each letter some value is calculated, all
  313.      these values are added up together (in EBP). Then this value is stored
  314.      in EAX and the function RETurns. And that was what we were looking
  315.      for, we wanted to know how EAX got its value!
  316.  
  317.      Step 6: Now to make a key-gen we have to translate the above method of
  318.      calculating the right reg# into a c program. It could be done in the
  319.      following way : (Note : I am a bad c programmer :)
  320.  
  321.      #include <stdio.h>
  322.      #include <string.h>
  323.      main() {
  324.         char Name[100];
  325.         int NameLength,Offset;
  326.         unsigned long Letter,DummyA;
  327.         unsigned long Key = 0xa4cc;
  328.         unsigned long Number = 0;
  329.         printf("Ize 2.04 crack by razzia\n");
  330.         printf("Enter your name: ");
  331.         gets(Name);
  332.         NameLength=strlen(Name);
  333.         for (Offset=0;Offset<NameLength;Offset=Offset+1) {
  334.            Letter=Name[Offset];
  335.            DummyA=Key;
  336.            DummyA=DummyA*0x15a4e35;
  337.            DummyA=DummyA+1;
  338.            Key=DummyA;
  339.            DummyA=DummyA & 0x7fff0000;
  340.            DummyA=DummyA >> 0x10;
  341.            Letter=Letter*DummyA;
  342.            DummyA=Key;
  343.            DummyA=DummyA*0x15a4e35;
  344.            DummyA=DummyA+1;
  345.            Key=DummyA;
  346.            DummyA=DummyA & 0x7fff0000;
  347.            DummyA=DummyA >> 0x10;
  348.            Letter=Letter*DummyA;
  349.            Letter=Letter*(Offset+1);
  350.            Number=Number+Letter;
  351.         }
  352.         printf("\nYour registration number is : %lu\n",Number);
  353.      }
  354.  
  355. Final Notes
  356.      For feedback and suggestions pls contact me :)
  357.  
  358.                                                                     raZZia
  359.