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

  1.  
  2.      odin's_________    _______        ______    _____________
  3.        ____\       /____\     /________\    /____|     /_____/_______ _________
  4.       /     _____/      _____/    __    ___/     '____/ /   |        \   _____/___
  5.      /     |      \    ||    |    |    |    \    .     \    |    |    |  \__     /
  6.      \_____        \___| \____    |____      \___|      \___|____|    |_____     |
  7.            |_______/ <hook>  `----'    |_____/   |______/        |____|    |_____|
  8.                                                                 tutorial v1.51
  9.  
  10. Cracking/Patching SoftArt's Deskey v1.02.010
  11.  
  12. X. TABLE OF CONTENTS
  13.  
  14.      1. FOREWARDS
  15.      2. INTRODUCTION
  16.      3. TOOLS USED FOR THIS
  17.      4. THE CRACKING STARTS
  18.      5. MAKING A PATCH
  19.      6. THE URL'S
  20.  
  21. 1. Forewards
  22.  
  23.      Welcome. So how come you're interested in reading this tutorial?
  24.      Perhaps you think cracking is cool and seems easy, and that cracking
  25.      is a way to be famous on the internet today. Well, if you think like
  26.      this please stop reading now. Why? Mainly because most crackers don't
  27.      crack because they think it's "cool." and want to be famous. Cracking
  28.      is something they actually do because they think its a great thing to
  29.      spend their precious time on, believe it or not. Most crackers, not to
  30.      say all, also code in one or several computer languages.
  31.  
  32.      On the other hand if you're very interested in how computers work
  33.      internally, and you like to program in languages like Pascal, C++ and
  34.      Assembler, then I believe this tutorial is worth reading for people
  35.      such as you, and you might even learn something from it.
  36.  
  37.      If you're the third category, you've been learning cracking for some
  38.      time now and read every little article about cracking you can get,
  39.      then this tutorial also is very good to read. You can always learn
  40.      something that you didn't know before. Even I can learn things I
  41.      didn't know by listening to others and reading various text files.
  42.  
  43.      To become a cracker will take several years. And to become a good
  44.      cracker will take even longer. The key to success is practice and, in
  45.      my point of view, learning and listening to other crackers.
  46.  
  47.      I'll skip the most things about how SoftICE works because there are
  48.      several good tutorials out about that. One is Exact's SoftICE
  49.      tutorial, very good and recommended reading.
  50.  
  51. 2. Introduction
  52.  
  53.      This text files purpose is to show and hopefully learn you how to
  54.      patch away a time limit of a program. The program we will use is
  55.      SoftArt's Deskey. It isn't necessary to patch this program because you
  56.      can also enter a registration code in the registry to get the program
  57.      to work fully, but then you have to write a keymaker because the code
  58.      depends on the Windows name and company (the one you enter when you
  59.      installed Windows 95). So we're going to do it the lazy way and patch
  60.      it. There are of course other ways to do this crack.
  61.  
  62. 3. Tools you will need for this
  63.  
  64.      (1) SoftICE 2.0/3.0, of course, our beloved debugger.
  65.  
  66.      (2) Ultra Edit or another good hex editor.
  67.  
  68.      (3) A patch generator, or if you write the patch yourself as I do.
  69.  
  70. 4. The cracking starts
  71.  
  72.      Ok, let's begin with removing the semicolon from the user32.dll and
  73.      kernel32.dll lines in SOFTICE.DAT if you haven't done so already.
  74.  
  75.      Now let's do some detective work, by checking the Deskey help file.
  76.      You'll notice that this program will stop working after 60 minutes.
  77.      This limit is what we're going to remove. There are a few possible
  78.      solutions for the programmer to obtain this limit. To check which
  79.      functions the program use, let's test the approach Qapla used in his
  80.      tutorial:
  81.  
  82.      Start the explorer and press the right mouse button on the Deskey exe
  83.      file. Now choose Quick-View. You'll notice all the calls the program
  84.      uses and which dll's store the code for the calls. When you look at
  85.      them, you'll notice some interesting functions.
  86.  
  87.      Import Table
  88.  
  89.           ...
  90.           KERNEL32.dll
  91.           Ordinal  Function Name
  92.           ...     ...
  93.           008f    FreeLibrary
  94.           0188    MultiByteToWideChar
  95.           011d    GetSystemTime        <----- Interesting
  96.           00e4    GetLocalTime         <----- Interesting
  97.           025d    lstrcmpiA
  98.           00ca    GetDateFormatA
  99.           ...     ...
  100.  
  101.           USER32.dll
  102.           Ordinal  Function Name
  103.           ...     ...
  104.           00ec    GetDlgItemTextA
  105.           007d    DefWindowProcA
  106.           01fe    SetTimer             <----- Interesting
  107.           01a2    PostMessageA
  108.           0224    TrackPopupMenu
  109.           01b8    RemoveMenu
  110.           ...     ...
  111.  
  112.      Ok, as you see I'm interested in 3 different calls. We can try to see
  113.      if the program uses KERNEL32!GetSystemTime(); and
  114.      KERNEL32!GetLocalTime();. Enter SoftICE and put a breakpoint on these
  115.      two. Enable them just when you're about to start the program. If you
  116.      do it before, you risc to break on these calls used by another
  117.      program. So just before you start Deskey, enable these.
  118.  
  119.      Now you started it and program pops up in the traybar. Nothing
  120.      happens. Oh well, then we can exclude these ones. Actually a cracker
  121.      might have excluded them from the beginning and tried some other calls
  122.      first. Why? Probably because a programmer usually uses these calls if
  123.      the program has a 30-day limit, not a 60-minutes one.
  124.  
  125.      We have one left to test, USER32!SetTimer();. Exit Deskey and put a
  126.      breakpoint on SetTimer(); just before you start Deskey.
  127.  
  128.      Finally, SoftICE detected the use of this function by Deskey. Press
  129.      F11. It should look something like this now:
  130.  
  131.                       .
  132.                       .
  133.                       .
  134.        0137:0040397F  833D1890400000  CMP   DWORD PTR [00409018], 00
  135.        0137:00403986  7409            JZ    00403991
  136.        0137:00403988  833D1C90400000  CMP   DWORD PTR [0040901C], 00
  137.        0137:0040398F  7421            JZ    004039B2
  138.        0137:00403991  6A00            PUSH  00
  139.        0137:00403993  A128904000      MOV   EAX,[00409028]
  140.        0137:00403998  6880EE3600      PUSH  0036EE80
  141.        0137:0040399D  6834120000      PUSH  00001234
  142.        0137:004039A2  50              PUSH  EAX
  143.        0137:004039A3  FF158CB44000    CALL  [USER32!SetTimerA] <-- you're here
  144.        0137:004039A9  8BBC24AC060000  MOV   EDI,[ESP+000006AC]
  145.        0137:004039B0  EB12            JMP   004039C4
  146.        0137:004039A9  8BBC24AC060000  MOV   EDI,[ESP+000006AC]
  147.        0137:004039B0  EB09            JMP   004039C4
  148.        0137:004039A9  8BBC24AC060000  MOV   EDI,[ESP+000006AC]
  149.        0137:004039B0  EB07            JMP   004039CB
  150.                       .
  151.                       .
  152.                       .
  153.  
  154.      Let's check the SetTimerA function in our we-cant-be-without-it API
  155.      guide:
  156.  
  157.         The SetTimer function creates a timer with the specified time-out value.
  158.  
  159.         UINT SetTimer(
  160.            HWND  hwnd,       // handle of window for timer messages
  161.            UINT  idTimer,    // timer identifier
  162.            UINT  uTimeout,   // time-out value
  163.            TIMERPROC  tmprc  // address of timer procedure
  164.         );
  165.         .
  166.         .
  167.         .
  168.         uTimeout
  169.            Specifies the time-out value, in milliseconds.
  170.         .
  171.         .
  172.         .
  173.  
  174.      Aha, let's check on the code again:
  175.  
  176.        0137:00403991  6A00            PUSH  00                 <-- tmprc
  177.        0137:00403993  A128904000      MOV   EAX,[00409028]     <-- pushed later
  178.        0137:00403998  6880EE3600      PUSH  0036EE80           <-- uTimeout
  179.        0137:0040399D  6834120000      PUSH  00001234           <-- idTimer
  180.        0137:004039A2  50              PUSH  EAX                <-- HWND
  181.        0137:004039A3  FF158CB44000    CALL  [USER32!SetTimerA] <-- you're here
  182.  
  183.      Hmm, very interesting indeed, let's check the value 0036EE80 in the
  184.      SoftICE debugger:
  185.  
  186.      :? 36ee80
  187.      0036EE80  0003600000  "6»╟"
  188.  
  189.      An even and nice value. And if you read further in the API help file
  190.      you'll notice that the uTimeout should be in milliseconds. 1 second is
  191.      1000 milliseconds. Let's do some calculating:
  192.  
  193.      3600000/1000=3600 seconds.
  194.  
  195.      60 seconds*60 minutes=3600 seconds, which is 1 hour
  196.  
  197.      We've found the right one! This call creates a timer which will be
  198.      checked when the program process the WM_TIMER message from Windows.
  199.      The WM_TIMER message is sent when 1 hour has past. Let's check the API
  200.      reference once more:
  201.  
  202.         WM_TIMER
  203.  
  204.         wTimerID = wParam;            // timer identifier
  205.         tmprc = (TIMERPROC *) lParam; // address of timer callback
  206.  
  207.         The WM_TIMER message is posted to the installing thread's message
  208.         queue or sent to the appropriate TimerProc callback function after
  209.         each interval specified in the SetTimer function used to install a
  210.         timer.
  211.         .
  212.         .
  213.         .
  214.  
  215.      So now we know where he creates the timer. If you remove this
  216.      SetTimer(); call the WM_TIMER message will never be sent, resulting in
  217.      that the 60 minute limit will be REMOVED!! Let's take a look at this
  218.      example code below:
  219.  
  220.        SetTimer(hwnd, idTimer, 0x36EE80, tmprc);
  221.                                ^-- hex value
  222.  
  223.           WM_TIMER: {                 <-- this structure is reached when
  224.             PostQuitMessage(0);           the hex value above reach 0. If
  225.              ^-- will exit the program    the timer never is set this
  226.           }                               structure wont be reached.
  227.  
  228.      This is very simple to understand, I hope :-).
  229.  
  230.      So perhaps you think, "hey, let's NOP away the whole structure"
  231.  
  232.           (for those of you not familiar with NOP: it means NO OPERATION
  233.           and are very commonly used when patching. The computer will do
  234.           nothing when it executes this instruction.)
  235.  
  236.      Nono stop! Don't NOP away the whole call. Well first of all a good
  237.      rule when patching is that, never alter the code more then you
  238.      actually need. It looks nice (who'll notice anyway), and it decreases
  239.      the chance of program crash due to doing something stupid. So how
  240.      should we do instead? Well let's check that code once more:
  241.  
  242.                       .
  243.                       .
  244.                       .
  245.        0137:0040397F  833D1890400000  CMP   DWORD PTR [00409018], 00
  246.        0137:00403986  7409            JZ    00403991
  247.        0137:00403988  833D1C90400000  CMP   DWORD PTR [0040901C], 00
  248.        0137:0040398F  7421            JZ    004039B2
  249.        0137:00403991  6A00            PUSH  00
  250.        0137:00403993  A128904000      MOV   EAX,[00409028]
  251.        0137:00403998  6880EE3600      PUSH  0036EE80
  252.        0137:0040399D  6834120000      PUSH  00001234
  253.        0137:004039A2  50              PUSH  EAX
  254.        0137:004039A3  FF158CB44000    CALL  [USER32!SetTimerA] <-- you're here
  255.        0137:004039A9  8BBC24AC060000  MOV   EDI,[ESP+000006AC]
  256.        0137:004039B0  EB12            JMP   004039C4
  257.        0137:004039A9  8BBC24AC060000  MOV   EDI,[ESP+000006AC]
  258.        0137:004039B0  EB09            JMP   004039C4
  259.        0137:004039A9  8BBC24AC060000  MOV   EDI,[ESP+000006AC]
  260.        0137:004039B0  EB07            JMP   004039CB
  261.                       .
  262.                       .
  263.                       .
  264.  
  265.      The CMP (compare) instructions above seems very interesting.
  266.  
  267.      As you might notice, the one at 00403986 will jump to 00403991 and
  268.      start the timer. If you check the JZ at 0040398F it will go to
  269.      004039B2 and therefor jump over the timer, resulting in that there
  270.      will be no time limit. So to solve this simple problem just change the
  271.      JZ 00403991 at 00403986 to JMP 004039B2 instead. Like this:
  272.  
  273.        0137:00403986  7409            JZ    00403991
  274.        ---> to --->
  275.        0137:00403986  EB2A            JMP   004039B2
  276.  
  277.      Now let's apply the patch to the exe file. Load up your favorite hex
  278.      editor. In this case I'll use Ultra Edit. Now load the exe file.
  279.      Choose search and enter the following bytes: 68 80 EE 36 00.
  280.  
  281.      So why do we search after these? Well that's very easy. Check the code
  282.      once again:
  283.  
  284.        0137:00403993  A128904000      MOV   EAX,[00409028]
  285.        0137:00403998  6880EE3600      PUSH  0036EE80       <--- this one
  286.        0137:0040399D  6834120000      PUSH  00001234
  287.  
  288.      As you see these bytes stands for the instruction PUSH 0036EE80.
  289.  
  290.      "Uhu, I don't have those cryptic numbers to the left of my
  291.      instructions!!". Well that's easy to fix. Just write 'code on' and
  292.      you'll see these cryptic numbers, also known as OPerand codes.
  293.  
  294.      "Why didn't you search 83 3D 18 90 40 00 00 for example?". Well that's
  295.      because I know the ones we searched for only exists one time in the
  296.      exe file. The one mentioned above (83 3D...) exists several times, so
  297.      you cannot actually know which of those to use, if you don't check the
  298.      surrounding bytes that is. Always do "search next" so you are sure
  299.      that that byte combination doesn't exist somewhere else in the file.
  300.  
  301.      Now let's change the bytes needed. Some bytes above '68 80 EE 36 00'
  302.      you will find '74 09' which is the JZ 00403991 instruction. This is
  303.      the two bytes we want to change. So how do you know which numbers to
  304.      actually change to? That's also easy. In the debugger when you're
  305.      looking at the code just use the 'a' command. Like This:
  306.  
  307.        0137:0040397F  833D1890400000  CMP   DWORD PTR [00409018], 00
  308.        0137:00403986  7409            JZ    00403991
  309.        0137:00403988  833D1C90400000  CMP   DWORD PTR [0040901C], 00
  310.        ----------------------------------------^ code window ^ -----
  311.        :a 00403986 JMP 004039B2
  312.        ----------------------------------------^ prompt ^-----------
  313.  
  314.      This will change the instruction at 00403986 and a new code will pop
  315.      up, EB2A. So this is the code you want to change for the 7409 one.
  316.      Remember, that if you use the 'a' command it will not change the code
  317.      permanently, only temporary. That's why we have to use a hex editor.
  318.      So go to the '74 09' bytes and change it to 'EB 2A'.
  319.  
  320.      Now save the exe file, voila! That's it. Now start the program up and
  321.      test if it works. If SoftICE doesn't break on SetTimer(); it probably
  322.      worked. If it does, read this all again :-).
  323.  
  324.      One thing has to be said also. If you for example want to change a
  325.      instruction with the opcode 'C1 E1 10' (3 bytes) to a instruction that
  326.      only has a 2 byte opcode, for example '0B D1', you have to NOP away
  327.      the last byte. NOP has the hex value 90.
  328.  
  329.      Like this:
  330.  
  331.         C1 E1 10      becomes --->  0B D1 90
  332.         SHL   ECX, 10 becomes --->  OR   EDX, ECX  <- 0B D1
  333.                                     NOP            <- 90
  334.  
  335.      As you see I change the F3 to 90 and therefore put the instruction NOP
  336.      there. If you didn't do this the chance of a program crash would be
  337.      98%.
  338.  
  339.      That's all. To patch is very simple, but to find the bytes to change
  340.      is harder. Remember that the byte combination can exist somewhere else
  341.      so check the surrounding bytes.
  342.  
  343. 5. Making the patch
  344.  
  345.      Now it's time to make this patch available to the public. To write
  346.      something like "uhu change the bytes at blabla to blabla" doesn't look
  347.      that good, does it? So now it's time to make a exe file that changes
  348.      those bytes asap so the user don't have to use Ultra Edit every time.
  349.      I've included a program in Pascal done for this task. There are also
  350.      several good patch generators.
  351.  
  352.      One for Windows 95, that I strongly recommend, is Qapla's PatchIt '97.
  353.      It's fast and nice interface (happy now Qapla :-)
  354.  
  355.      To convert this program to C++ should be easy. You have to know one
  356.      more thing to make a patch, where the bytes are located in the file.
  357.      This is called "offset.", to check the offset just go to the bytes you
  358.      changed, and look at the status bar in Ultra Edit, it should say the
  359.      offset (pos) in hex.
  360.  
  361.      I did the patch in Turbo Pascal 7, most would probably do it in Asm
  362.      :). Anyway, here is the patch:
  363.  
  364.      ---------------------------------------------------------------------
  365.      ---------------------------------------------------------------------
  366.  
  367.      Program Patcher;
  368.  
  369.      Uses Crt;
  370.  
  371.      Const offset   : Longint             = $2D86; { $ means a hex value }
  372.            bytes    : Byte                = 2;
  373.            len      : Longint             = 51200; { file length }
  374.            orgbytes : Array[1..2] Of Byte = ($74, $09);
  375.            newbytes : Array[1..2] Of Byte = ($EB, $2A);
  376.            {---------------------------------------------------------}
  377.            filename : String[12]          = 'DESKEY.EXE';
  378.            errnof   : String[43]          = '    ERROR: File DESKEY.EXE was not found.';
  379.            errver   : String[36]          = '    ERROR: File size is not correct.';
  380.            errpch   : String[36]          = '    ERROR: File seems to be patched.';
  381.            msgdon   : String[21]          = '    Patch successful!';
  382.            ask      : String[26]          = '    Continue anyway? (Y/N)';
  383.  
  384.      Procedure message(message : String);
  385.      Begin
  386.  
  387.        WriteLn;
  388.        WriteLn(message);
  389.        Halt;
  390.  
  391.      End;
  392.  
  393.      Procedure patchfile;
  394.      Var fil  : File Of Byte;
  395.          teck : Byte;
  396.          n    : Byte;
  397.          ch   : Char;
  398.      Begin
  399.  
  400.        Assign(fil, filename);
  401.  
  402.        {$I-}
  403.        Reset(fil);
  404.        {$I+}
  405.  
  406.        If (Not(IOResult=0)) Then message(errnof);
  407.        If (Not(FileSize(fil)=len)) Then
  408.        Begin
  409.  
  410.          WriteLn;
  411.          WriteLn(errver);
  412.          WriteLn(ask);
  413.          Repeat Until Keypressed;
  414.  
  415.          ch:=ReadKey;
  416.  
  417.          If Upcase(ch)='N' Then Halt;
  418.  
  419.        End;
  420.  
  421.        Seek(fil, offset);
  422.  
  423.        For n:=1 To bytes Do
  424.        Begin
  425.  
  426.          Read(fil, teck);
  427.          If (Not(teck=orgbytes[n])) Then message(errpch);
  428.  
  429.        End;
  430.  
  431.        Seek(fil, offset);
  432.        For n:=1 To bytes Do Write(fil, newbytes[n]);
  433.        Close(fil);
  434.  
  435.        WriteLn;
  436.        WriteLn(msgdon);
  437.  
  438.        Halt;
  439.  
  440.      End;
  441.  
  442.      Begin
  443.  
  444.        WriteLn;
  445.        WriteLn('    SoftArts Deskey v1.02.010 Patch');
  446.        WriteLn('         By ODIN / RBS^TFT^PIE in 1997');
  447.        patchfile;
  448.  
  449.      End.
  450.  
  451.      ---------------------------------------------------------------------
  452.      ---------------------------------------------------------------------
  453.  
  454. Some final words.
  455.  
  456.      Take some programs and play with patching them in various ways. This
  457.      gives you experience, and hopefully you'll become a better cracker.
  458.  
  459.      Thanks to Qapla, kOUGER, Hook and Tgunner for help while making this
  460.      tutorial.
  461.  
  462.      A special greeting goes to ED!SON.
  463.  
  464. 6. THE URL'S
  465.  
  466.      My E-Mail : cracking@usa.net
  467.      SoftArts Deskey v1.02.010 : http://www.spiresoft.com
  468.      Ultra Edit vX : http://www.windows95.com/apps/
  469.