                   

               razzia's tutorial for crypled programs


                        Introduction

  I think every cracker knows the feeling when you download a program
and it turns out to be crypleware. We feel disapointed because we didnt
even get a fair chance in the fight. But in this tutorial i want to
show you that the fight doesnt necessarily have to end there. There is
a good chance we can add the missing code to the program. It will not
be easy, and a good deal of knowledge about windows is needed, but the
satisfaction of a crack in these cases will be greater.

                       Tools and References

  Before you start an operation like this you will need to know 
how windows programs work, and how windows exe files are construc-
ted. You will need to study the following documents :
 
   - http://www.microsoft.com/win32dev/base/pefile.htm
     A document about the structure of the PE header (Win32 files are
     called PE files).

   - Vlad magazine #6
     This virus magazine explains in this issue how they made the 
     first win95 virus called Bizatch, souce code is included. This 
     issue also has another document about the PE header. In the past 
     this document was included in the microsoft win32 SDK package.
     But somehow microsoft stopped doing that.

   - Fravia's tutorials about Taskman and Filemon
     This will give you a good look at how windows programs look when
     they have been compiled to assembly. 

   - Wap32 example that comes with Tasm 5.
     This example will show you how to make win32 programs in assembly.
     This program is also used as the host for Bizatch, so you will
     find its source also in Vlad #6.     

   - A windows programming book

  The tools i have used in this case are Softice 3.0, Tasm 5, Hiew 5.65,
IDA PRO 3.6 and pedump.


                      A few words about Win32 programs

   Every win95 executable file consists of 2 parts : the PE header and 
the sections. The PE header contains all kind of information for the os
about how to threat this file. The sections are grouped by their 
functionality. For example there is one section for the programs code, 
one for its data, one with its resources, one with the table of 
imported functions and a few more.  

  Now, what happens when win95 loads a program is this: 
  First an environment is created for the program where it gets its own 
virtual address-space. Then win95 has to decide where in this virtual
address-space it should place the program. That information is avail-
able in the PE header. The PE header contains the desired imagebase
of the program, this is the adress the program wants to be loaded at.
  Then windows takes all the sections and places them in memory 
beginning at the imagebase (default imagebase is 400000h). Where
exactly it places the sections is also stated in the PE header. Every
section has its own so called RVA (Relative Virtual Address). This is
just an offset relative to the imagebase.
  Once the sections are in memory, windows has to know how to threat 
those sections. It has to know which section contains a stucture with
the resources, which one has the scructure of the import table etc. 
That is also stated in the PE header with RVA's to the beginning of the 
various so called data directories. 
  Then finally windows has to jump to the programs code. This entrypoint
is in the PE header as the entrypoint RVA. 

  The above words about the PE header is not meant as a replacement for
the PE document i mentioned at the beginning of this tutorial. I would
recommend to every (win32) cracker to study the PE header thoroughly.
It will give you a much better understanding of win95 programs.

          
                        Our target : Notepad

  I dont program much, but when i do they are small programs most of 
the time, ie keygens, patches. To edit my code i like to use Note-
pad. But one disadventage of Notepad is that it doesnt show linenumbers.
So when the compiler gives an error with linenumber, i have to load 
another editor to find the line with the error. Therefore it would be 
nice if i could add some code that shows me the current line of the 
cursor.

  The reason i chose Notepad as an example in this tutorial is that it
is small and simple. So its perfect for learning purposes.

  I dont know if Notepad.exe is the same on every version of win95, 
the one i have is 35.328 bytes.
                  

                              Strategy

  Well, its time now to think about the 'crack'. We want to add some 
code to a program and want that code to interact with the existing 
code. We can do it in 2 steps. First we have to find out what code
we are gonna add. Then we will have to append this code to the file
and patch the file at some places so it will jump to the new code
at the right times.

                  Part 1 : find out what code we need      

  In order to find out what code we have to add we will need to do
some investigation on the target program. 

  The 'heart' of every windows program is its WndProc procedure. This
procedure is called by windows everytime the user has interacted 
with the programs window. Windows passes to this procedure a few 
variables, like a windows message, so that WndProc knows what happened
and can perform what needs to be done to keep the window updated. 

  In the case of notepad the main program generates a childwindow
of the 'edit' class (to get more information about this class check 
your windows programming book).The edit childwindow gets the size of
the mainwindow all the time. In order to print our own text to the 
mainwindow we will have to reduce the size of the 'edit' childwindow
so it wont cover the complete mainwindow area. 

  Everytime the user changes the size of the mainwindow, windows 
calls the WndProc functions with the WM_SIZE message. The WndProc 
procedure then can react to this event, ie adjust the size of the 
'edit' childwindow to the new size of the mainwindow. 

  Lets locate this WndProc procedure and see how it handles the 
WM_SIZE message. You can do that either with Softice or IDA . Lets 
chose the more relax way and do it with IDA.

  Run IDA and load Notepad.exe. There are a lot of ways to get to
WndProc procedure, but the easiest way is via the RegisterClass 
function. You see, at the beginning of every windows-program the main
window is 'registered' to windows. The parameter to RegisterClass
is a variable of WNDCLASS, which contains a pointer to the WndProc 
function (check your winAPI reference).

  So, press control-l in IDA and press return on the RegisterClassExA
function (notepad uses this variation of RegisterClass). IDA will show
you:

00402B16 	lea   eax, [ebp-30h]
00402B19 	mov   dword ptr [ebp-08h], offset aNotepad
00402B20	mov   dword ptr [ebp-28h], offset loc_401AAD ;<- WndProc !
00402B27 	mov   dword ptr [ebp-10h], 6
00402B2E	mov   dword ptr [ebp-2Ch], 1000h
00402B35 	push  eax
00402B36	mov   [ebp-24h], edi
00402B39 	mov   [ebp-20h], edi
00402B3C 	call  ds:RegisterClassExA

  Easily we see that loc_401AAD is the location of the WndProc proce-
dure. At loc_401AAD IDA shows :

00401AAD loc_401ADD:			    ;WndProc	 
00401AAD	 push	 ebp
00401AAE	 mov	 ebp, esp
00401AB0	 push	 esi
00401AB1	 push	 edi
00401AB2	 mov	 esi, [ebp+0Ch]
00401AB5	 cmp	 esi, 5             ;beware that WM_SIZE = 5
00401AB8	 ja	 short loc_401ACE
00401ABA	 jz	 loc_401BC6         ;jump here for WM_SIZE
00401AC0	 cmp	 esi, 2
00401AC3	 jz	 loc_401BB9
00401AC9	 jmp	 loc_401B51


  We see that here the program checks to see which message it is dealing
with and branches accordingly. To find out which value corresponds
to WM_SIZE you can look it up in the header files that come with 
a win32 c++ compiler (there is a free one at www.cygnus.com), or you
can do '? wm_size' in softice. 

  We also see that for a WM_SIZE msg the program branches to
loc_401BC6. If you examine the code at that location you will see a 
call to this procedure:

0040113F sub_40113F	 proc near		
0040113F	 push	 1
00401141	 mov	 eax, ds:dword_406004
00401146	 push	 0
00401148	 push	 eax
00401149	 call	 ds:InvalidateRect
0040114F	 push	 1
00401151	 mov	 eax, ds:dword_406004
00401156	 push	 dword ptr [esp+0Ch]  ;Height
0040115A	 push	 dword ptr [esp+0Ch]  ;Width
0040115E	 push	 0
00401160	 push	 0
00401162	 push	 eax                  ;handle of 'edit' win
00401163	 call	 ds:MoveWindow        ;Update size of 'edit' win
00401169	 retn	 8
00401169 sub_40113F	 endp

  Note that the handle of the 'edit' child window is apparently stored
in (virtual) address 406004.
  We also see that for every WM_SIZE message the 'edit' childwindow gets 
updated with a call to MoveWindow with the new size of the mainwindow.
But we dont want the edit childwindow to be the full size of the 
mainwindow. 
  In order to get a smaller heigth  we have to place a jump to our
own code at the line with (virtual) adress 00401156. Such a jump takes
5 bytes, so our return adress will have to be 0040115E. For the code
that gets overwritten we will make up in our code. 

  Own our code will look like :
      
Own_Code_1:            
      sub    esp,8	
      push   ebx                      ;Save ebx temporarily

      mov    ebx,[esp+0Ch+4]          ;Get heigth
      sub    ebx,20                   ;Substract 20                  
      mov    [esp+4+4],ebx            ;Push heigth
             
      mov    dwHeight,ebx             ;Save Height

      mov    ebx,[esp+0Ch]            ;Get width
      mov    [esp+4],ebx              ;Push width 
	      	
      pop    ebx                      ;Restore ebx	                                    
      jmp    0040115E                 ;Return to where we left       
      dwHeigth      dd    0 
              
  One note here is apropiate. We save the Height becos we will need 
this value in the printing part of our code, as you will see if you
continue reading.

  Ok, one down, one more to go (as you will see). We want to print 
some text on the mainwindow. Everytime a window needs to get 
'repainted', for example when an other window overlapped it or when 
the user changed the windows size, windows will call the WndProc
procedure with WM_PAINT. This means we have to 'trap' the WM_PAINT
msg in the WndProc function and make a jump to our own routine that 
prints text. 
  We will also need to do printing every time the vertical position 
of the cursor has changed. The easiest way to do that is by ignoring 
all the possible messages that inform about a change in the cursor
position, and instead compare the new cursor position with the old
one.
  If you examine the WndProc code you will see it doesnt do anything 
with the WM_PAINT message. So,at the beginning of the WndProc procedure
we have to insert a jump to our own code.
   
  The beginning of WndProc procedure looked like this:

00401AAD loc_401ADD:			    ;WndProc	 
00401AAD	 push	 ebp
00401AAE	 mov	 ebp, esp
00401AB0	 push	 esi		    ;<- good place for jump
00401AB1	 push	 edi
00401AB2	 mov	 esi, [ebp+0Ch]     
00401AB5	 cmp	 esi, 5             ;<- return here
00401AB8	 ja	 short loc_401ACE
00401ABA	 jz	 loc_401BC6         
00401AC0	 cmp	 esi, 2
00401AC3	 jz	 loc_401BB9
00401AC9	 jmp	 loc_401B51

 
  A nice place to put the jump to our code for processing WM_PAINT
will be at the line with (virtual) adress 00401AB0. And again, the 
jump takes 5 bytes so will return at adress 00401AB5. 
 
  Our own code for the WM_PAINT msg will look like this :   

Our_Code_2:
      push    esi
      push    edi
      mov     esi, [ebp+0Ch]      ; Esi contains current message now
     
      push    0
      push    -1
      push    EM_LINEFROMCHAR 
      push    [406004]            ; (Handle of 'edit' child win)
      call    SendMessageA        ; After this call EAX will have 
                                  ; the y position of cursor

      cmp     eax,dwLine          ; Has cursor pos changed ?
      jnz     update_line_num     ; If yes, print the new line num      

      cmp     esi,0Fh             ; Is the current msg a WM_PAINT ?
      jnz     no_update_needed    ; If no , return to WndProc

update_line_num:
      mov     dwLine,eax          ; Save new y position of cursor
            
      inc     eax
      push    eax
      push    offset  szFormat
      push    offset  sLineNumber  
      call    wsprintfA           ; Convert number to ascii
 
      push    [406000h]           ; (Handle of main window)
      call    GetDC               ; Get the device context

      mov     theDC,eax           ; Save dc      

      push    0
      push    0
      push    0
      push    14
      push    sLineNumber
      push    0
      push    [dwHeigth]
      push    [theDC]
      call    TabbedTextOut      ; Print the text

      push    [theDC]
      push    [406000h]          ; (Handle of main window)
      call    ReleaseDC          ; Release the DC

no_update_needed:
      mov     esi, [ebp+0Ch]      
      jmp     0401AB5h           ; Return to WndProc      

      dwLine	    dd 0
      szFormat      db '%#05d',0
      sLineNumText  db '  line : '	
      sLineNumber   db  6 dup (?)
      theDC         dd  0      

  A few notes about the above code. First of all i used only api functions
that were imported by Notepad.exe (check its import table). What if
the API's functions we need were not in the import table? How to solve
that problem i will explain in the end of this tutorial.
  Secondly, some functions need the handle of the main window as a 
parameter. You can find its (virtual) address with IDA if you look
where notepad stores it after the first call to CreateWindowExA.
  Finally, this code is not final. Consider it as a scetch. Some minor
but very important changes will be necessary.


                   Part 2 : Appending our code


  Now we are ready to start thinking about adding our code to 
notepad.exe. Our main concern will be to make code that is not 
dependant on the memory location it get placed. This is because our
code gets compiled independently of the notepad code. Therefore our
instuctions with addresses will not get relocated by the win32 loader.

  Lets start from the beginning and deal with the problems as they
occur on our path.
   
  The first question to deal with is where in the file to place our 
code. The easiest way is to append our code to the last section of 
notepad.exe. Lets examine the header of the last section, which 
happens to be the .reloc section.

  At the dos prompt type 'pedump notepad.exe > out.txt'. This will 
make a file with the header information of notepad.

  The last section header shows :
           
   06 .reloc    VirtSize: 0000091E  VirtAddr:  0000B000
    raw data offs:   00008000  raw data size: 00000A00
    relocation offs: 00000000  relocations:   00000000
    line # offs:     00000000  line #'s:      00000000
    characteristics: 42000040
      INITIALIZED_DATA  MEM_DISCARDABLE  MEM_READ
  
  We see that there is a space of A00h-91Eh = E2h bytes left in the
section. For me this was not enough, mainly becos i am a bad coder and
produce too big code. So, first thing that should be done is to 
increase the size of this section. I increased both Virtual Size and
raw data size to B00h.
  Our code needs also to write to its variables, so another thing we
have to do with this section is to add a MEM_WRITE property to its
flags.  
  An easy way to find the file-offsets of the places we want to change
is to load notepad.exe with Hiew. You will find the header easily 
because the first 8 bytes contain its name, ".reloc" in this case .

  This section header tells us also what the RVA of our code is going
to be. The RVA of the section itself is B000h , it has 91eh bytes, so 
that means the RVA of our code will be B91Eh. (As a reminder, a RVA 
is just an offset/distance to the image base)    
  This knowledge is needed for the jumps from notepad to our code and
vice versa. Knowing that in 32 bit programs all jumps get compiled to
relative jumps (opcode is E9), we can compile those jumps (total of 4)
in tasm with :
   
	jmp $+ (RVA_of_destination_code - RVA_of_current_instruction)    

  For example, we needed a jump from 00401156 to Our_code_1. 
We know the RVA of Our_code_1 is B91Eh. So we can produce the opcode
for this jump with : jmp $+(B91Eh - 1156h) . 

   Another point of concern is that our code makes use of 'local' 
variables, like "mov   dwHeigth,ebx". In order to be able to 
read/write to variables without needing relocation we can use what
all exe-protectors and virii have been using untill today :
  
	call next_instruction
next_instruction:  
	pop ebp
	sub ebp, offset next_instruction  ;ebp has now 'delta' offset
  
        mov [ebp + offset dwHeigth], ebx

  This code is independant of the memory location it gets placed at.

  There is just one more thing left to take cafe of : the calls to
the api functions. If you examine with Hiew the calls to api's from 
the original code of notepad, you will see that in reality they have
the form : 
         
	call [address_of_a_dword_var]

  So, they are infact indirect calls trough a dword variable which
contains the address of the api function in question.
  Win95 uses this method of calling api's because in this way it  
needs to put the address of the api function at only one place. 
  So, for us to make use of an api function we need to find out the 
RVA of the dword variable that contains the address of the api
function we want to use. 
  This can be done by examining the operand of the inscruction in Hiew.
For example for a SendMessageA call Hiew shows :

	FF1554744000		call   SendMessageA ;USER32.dll

  Which in reality is 
  
	FF1554744000		call   [00407454]

  So, the RVA of this variable is 7454. To calculate the address of 
this variable in memory you still have to calculate the image base, 
which is : EIP_At_start_of_own_code - B91Eh. Then the address of the 
variable is ofcourse : image base + RVA.

  In practice : 

Our_code_1:                                ; <-- RVA = B91Eh  
  ...
  ...
	call next_instruction
next_instruction:  
	pop ebp
	sub ebp, offset next_instruction   ; ebp has now 'delta' offset
   ...  
   ...
        mov eax,ebp
        
        add eax,  offset Our_code_1        ; <-- EAX has now  the
                                           ;  the EIP at Our_code_1

        sub eax, B91eH                     ; <-- EAX has image base        

        add eax, 7454h                     ; <-- [EAX] has now the
                                           ;  address of SendMessageA 

        call [eax] 			   ; call SendMessageA	

  The same method can be used to address variables of the original
code of notepad, like the variable with (virtual) address 406000h that
contained the handle of the main window. 
  
 The complete source to patch notepad.exe and add the extra code 
is included with this tutorial. Also is included is the notepad.exe
that i have. 

 


                         Final notes

 
  We have seen that we can add any code we want to win32 programs. 
The question now is how we can know what code we have add to a 
cryppled program ?

  Sometimes it is obvious. For example when we are dealing with a 
save disabled program and the file it should generate is a text file. 
If the output file is not a text file, it can be helpfull to check
the Swag file format encyclopedia.
(available at http://www.gdsoft.com/swag/swag.html).
 
  Sometimes examining old versions of a program can help. Or examining 
'lite' versions of programs which are not cryppled. 
  Also examining the load function can be helpfull.

  Another question is what if we need to use api functions which are
not imported. 
  The easiest solution to that is just to replace 2 entries in the 
import table with the kernel32 functions GetModuleHandle and 
GetProcAdress. With those two functions you can get the address of 
every function.
  If you also change the entry point RVA to point at some code that 
you add, which will put the addresses of the two original functions
at the places they were supposed to get, then there will be no
problem.
 
                         The Greetings

   I would like to take advantage of this oppurtunity and thank the
following persons for everything they thought me in the past :
 
  THE_OWL, rANDOM, aCP, madmax, lost_soul and xygorf.     
       
  Also i would like to greet the wonderfull ppl in #cracking,
#cracking4newbies and #Pc97 :
 
  Psychotrn, lordbyte,j0b, ThePharao, musashi, sharp, mailman, dwolf,
niabi, josephco, StarDogg Champion (Brain is fried dude ;--), tHATDUDE, 
cyberlatin, blorgth, sice_boy, jacky_x, teraphy and everybody
else i forgot..

 Finally my special thanks go to +ORC, +fravia and +gthorne.

 

 august 1997 - razzia 
  
  

 


