----------------------[ Nag Screen Removal: NotePad - Date: 15/12/98 ]----------

-= Written By =-                                              Number of pages: 5
  ______
 /  ___ \  ______   ______   ______   ______   ______   _    _   ______
 | /   \| /  ___ \ /  __  \ /  __  \ /  ___ \ /  __  \ / \  / \ /  ___ \
 | |    | | /   \| | /  \ | | /  \ | | /   \| | /  \ | | |  | | | /   \|
 | |      | |_   | | \__/ | | \__/ | | |_   | | \__/ | | |  | | | \____
 | |      |   \    |  __  / |  __  / |   \    |  __  / | |  | | \____  \
 | |    | |  _/  | | /  \ \ | /  \ \ |  _/  | | /  \ \ | |  | |      \ |
 | \___/| | \___/| | |  | | | \__/ | | \___/| | |  | | | \__/ | |\___/ |
 \______/ \______/ \_/  \_/ \______/ \______/ \_/  \_/ \______/  \_____/


+----------                                                          ---------+
  How to get rid of the nasty Nag you get in Notepad when opening large files
+----------                                                          ---------+


My first tutorial. I want to crack Notepad. Yeah, I know, many before me did it. But they all did it with help of SoftIce, but I somehow knew that this wasn't necessary. So I started cracking.

Required:
* W32Dasm, I used version 8.9  <- Find it on the I-Net (f.e. Astalavista.box.sk)
* HexView, I used version 5.84 <- Find it on the I-Net (f.e. Astalavista.box.sk)
* FC (File Compare, standard in DOS)
* Some programming experience
* A BackUp of NotePad

First of all you'll have to run Notepad and open a big file (> 32Kb). If it is OK, you'll see a message like this (Translated from Dutch, so the English version could be a little different!!):

+--------------------------------------------------+
| File is too big and cannot be opened by Notepad. |
| Do you want to run WordPad to read this file?    |
+--------------------------------------------------+

If you choose [NO], it doesn't run WordPad, but if you choose [YES], it'll run WordPad! Remember the message. It is always necessary that you write down or remember the shown message. You'll have to keep in mind that a messagebox was shown.

We have everything we need to crack, so exit NotePad. Disassemble NotePad with W32Dasm. Click on "List and Search for String Data Referenced in Disassembly". The button is between [DLG Ref] and the Print Button, or you could select "String Data References" under the "Refs" menu. Find the Message in the list and double-click on it. Close the box. 
Click on "List and Search for Imported Modules and Functions". Between [Ret] and [Exp Fn] on the Toolbar or choose "Imports" in the "Functions" menu. Find in the list "USER32.MessageBoxA", the "32" and the "A" says it is 32-bit. Double-click on the item and close the dialog box. Why first the string search? Well, a messagebox is called often by the same program, so it is very unlikely that you get the right one immediately. We want the MessageBox which is shown after the text is initialised, therefore it has to be done this way!
You see this:

* Reference To: USER32.MessageBoxA, Ord:01ACh
                                  |
:004033B1 FF15A8644000            Call dword ptr [004064A8] <-- The call to
                                                        show the dialog box
:004033B7 83F806                  cmp eax, 00000006 <-- When [YES] is
                                                        pressed, the
                                                        dialog box sets eax
                                                        to 6, but if [NO]
                                                        is pressed, eax
                                                        would be set to 7
:004033BA 0F85A7000000            jne 0040467       <-- Jump Not Equal (eax
                                                        equal to 6. No?
                                                        Then jump else
                                                        don't jump)
:004033C0 6804010000              push 00000104
:004033C5 8D858CFDFFFF            lea eax, dword ptr [ebp+FFFFFD8C]
:004033CB 837D1001                cmp dword ptr [ebp+10], 00000001
:004033CF 1BFF                    sbb edi, edi
:004033D1 50                      push eax
:004033D2 83C737                  add edi, 00000037

* Possible Reference to String Resource ID=00056: "wordpad.exe"
                                  |
:004033D5 6A38                    push 00000038
:004033D7 FF3540554000            push dword ptr [00405540]

As you see, poorly protected. But why should it?

Select the line: Call dword ptr [004064A8]
On the statusbar you see "@Offset 000033B1h"
Then select the line: jne 0040467
On the statusbar you see "@Offset 000033BAh"
These are the offsets in the file NotePad.EXE, which we are going to use when patching it.

Let's delete the call to the dialog box. You can do this with the NOP instruction, but programs which are checking itself, 'know' that it is a crack when it encounters about three NOP's in the program. NotePad doesn't check itself, but I show you how to avoid such checks anyway. We can increase a register and decrease it, so we don't have to use NOP and we don't change the progress. We're going to do the same thing with the conditional jump (jne).

:004033B1 FF15A8644000            Call dword ptr [004064A8]
          \-> Bytes: FFh 15h A8h 64h 40h 00h

      Action        Instruction  Byte Offset
      =----=        =---------=  =--= =----=
      Increase ecx: inc   ecx -> 41h  33B1h
      Increase edx: inc   edx -> 42h  33B2h +1, because the instruction is
                                                1 byte long
      Decrease ecx: dec   ecx -> 49h  33B3h
      Decrease edx: dec   edx -> 4Ah  33B4h
      Increase eax: inc   eax -> 40h  33B5h
      Decrease eax: dec   eax -> 48h  33B6h

:004033BA 0F85A7000000            jne 0040467
          \-> Bytes: OFh 85h A7h 00h 00h 00h

      Decrease eax: dec   eax -> 48h  33BAh
      Increase eax: inc   eax -> 40h  33BBh
      Increase ecx: inc   ecx -> 41h  33BCh
      Decrease ecx: dec   ecx -> 49h  33BDh
      Decrease edx: dec   edx -> 4Ah  33BEh
      Increase edx: inc   edx -> 42h  33BFh
      
(You can also do other registers, as long as you make sure the registers doesn't have other values after the action!)

Load HexView 5.84 with the only parameter $windowspath$\NOTEPAD.EXE
- Press [F4] (Mode) and choose "Decode". 
Now you see the listing with at the left side the offset, then the bytes then the instruction. 
- Press [F5] (Goto) and input our first offset: 33B1h (you can omit the 'h'). 
- Press [F3] (Edit) and input the bytes which belong to that offset: 41 (Hexadecimal!)
The instruction immediately changes to: inc   ecx
Repeat this routine until you did all the offsets. Beware of the offset 33B7h, this is a CoMPare, and we won't delete it. If you want to do this anyway you can use one NOP and an INCrease and an DECrease instruction.
- Press [F9] (Update)
- Press [F10] (Quit)

Load NotePad and open a big file (> 32Kb). Yes, it's cracked!! Now create a patch and distribute it.

Compare the BackUp and the cracked NotePad with:

FC /B $backup$ NotePad.EXE > Crack.TXT

When opening "Crack.TXT" you get:

Offset    Original Cracked 
------    -------- ------- 
000033B1: FF       41
000033B2: 15       42
000033B3: A8       49 
000033B4: 64       4A
000033B5: 40       40
000033B6: 00       48
000033BA: 0F       48
000033BB: 85       40
000033BC: A7       41
000033BD: 00       49
000033BE: 00       4A
000033BF: 00       42

Source:

BASIC
-----

DEFINT A-Z
CONST NumOffset = 12                                   ' Number of offsets
CONST FileName = "NOTEPAD.EXE"                         ' Filename
CONST True = -1
CONST False = 0
TYPE CrackType
  Offset AS INTEGER                                    ' The offset
  Original AS INTEGER                                  ' Original code
  ChangeTo AS INTEGER                                  ' Change it to
END TYPE
DIM Crack(1 TO NumOffset) AS CrackType, Byte AS INTEGER
RANDOMIZE TIMER

SCREEN 0, 0, 0, 0                                      ' Draw logo
COLOR 7, 0
CLS
COLOR 14, 1

PRINT "                                                                          "
PRINT " -= Created By =-                                                         "
PRINT "                                                                          "
PRINT "   ______                                                                 "
PRINT "  /  ___ \  ______   ______   ______   ______   ______   _    _   ______  "
PRINT "  | /   \| /  ___ \ /  __  \ /  __  \ /  ___ \ /  __  \ / \  / \ /  ___ \ "
PRINT "  | |    | | /   \| | /  \ | | /  \ | | /   \| | /  \ | | |  | | | /   \| "
PRINT "  | |      | |_   | | \__/ | | \__/ | | |_   | | \__/ | | |  | | | \____  "
PRINT "  | |      |   \    |  __  / |  __  / |   \    |  __  / | |  | | \____  \ "
PRINT "  | |    | |  _/  | | /  \ \ | /  \ \ |  _/  | | /  \ \ | |  | |      \ | "
PRINT "  | \___/| | \___/| | |  | | | \__/ | | \___/| | |  | | | \__/ | |\___/ | "
PRINT "  \______/ \______/ \_/  \_/ \______/ \______/ \_/  \_/ \______/  \_____/ "
PRINT "                                                                          "
PRINT "                                    cerberus_x@hotmail.com                "
PRINT "                                                                          "
COLOR 7, 0
FOR Count = 1 TO NumOffset                             ' Read DATA into Crack()
  READ Ofs, Ori, Cha
  Crack(Count).Offset = Ofs + 1                        ' Offset
  Crack(Count).Original = Ori                          ' Original code
  Crack(Count).ChangeTo = Cha                          ' Change it to
NEXT Count
ON ERROR GOTO NotValid
OPEN FileName FOR INPUT AS #1: CLOSE
ON ERROR GOTO 0

OPEN FileName FOR BINARY AS #1                         ' Open file
  FOR Count = 1 TO NumOffset                           ' Check if file
    Ofs = Crack(Count).Offset                          ' is a valid Notepad
    Ori = Crack(Count).Original
    Bytes$ = " "
    GET #1, Ofs, Bytes$
    Byte = ASC(Bytes$)
    IF Byte <> Ori THEN GOTO NotValid                  ' If not, goto NotValid
  NEXT

  PRINT
  PRINT "Creating BackUp [NOTEPAD.CBS]..."
  SHELL "COPY NOTEPAD.EXE NOTEPAD.CBS > Null"          ' Create BackUp
  GOSUB Pause

  PRINT
  PRINT "Patching...";
  LOCATE CSRLIN - 1, 1
  FOR Count = 1 TO NumOffset                           ' Apply patch
    Ofs = Crack(Count).Offset
    Cha = Crack(Count).ChangeTo
    Bytes$ = CHR$(Cha)
    PUT #1, Ofs, Bytes$
    GOSUB Pause
  NEXT
  
  PRINT
  PRINT "NotePad successfully patched!"                ' Message if OK
  GOTO Quit

NotValid:
  PRINT
  PRINT "NotePad.EXE isn't valid!"                     ' Message if not OK
  BEEP

Quit:
CLOSE
END

Pause:                                                 ' This routine sets a
  t! = TIMER + RND / 6                                 ' delay, so it seems
  DO WHILE TIMER <= t!: LOOP                           ' as if it is a difficult
RETURN                                                 ' task

'DATA acquired from the compare made with File Compare
'Offset, Original, Change the byte to

DATA &H33B1, &HFF, &H41
DATA &H33B2, &H15, &H42
DATA &H33B3, &HA8, &H49
DATA &H33B4, &H64, &H4A
DATA &H33B5, &H40, &H40
DATA &H33B6, &H00, &H48

DATA &H33BA, &H0F, &H48
DATA &H33BB, &H85, &H40
DATA &H33BC, &HA7, &H41
DATA &H33BD, &H00, &H49
DATA &H33BE, &H00, &H4A
DATA &H33BF, &H00, &H42


If you want to E-Mail me, and you want to, mail to this address:

cerberus_x@hotmail.com

Cerberus

--------------------------------------[ Einde ] --------------------------------------