
*** IMPORTANT ***
Disclaimer: Use this program at your own risc, should the world blow up when
you run this program it's your own responsibility!

*** IMPORTANT TOO ***
The source is included in seperate files may be slightly different to
the source in this file. The source in this file is more vigurously commented


How to use this program:
I'm one lazy mofo so there is no user interface in this program - besides
it would be outta thread with the purpose of this program, I'll explain that 
later. So what you do, is you take your .exe file, put it in the directory
with execrypt.com renames it to input.exe - then you run execrypt.com and
the output will be stored as output.exe. Simple and annoying - I know!
Also remember this was'nt meant for actual use, it's not well suited for
anything but enlightenment and as the very basic for building your own 
execrypter.

Why did I write this program:
I wrote the comcrypter two month ago and released the sourcecode. Despite that
I've made *NO* effort what so ever to spread it I've been getting a few mails
about it, and a few comments on irc/phone. Some of the comments was requests
to make a .exe fileencrypter. So I went ahead and did it. Again the purpose
was a easy-to-read sourcecode with no intention of actual use. Hence no user-
interface and a poor encryption routine. Due to the more advanced struture
of a exe-encrypter and my inabillities in pascal (I'm no programmer so my asm
sucks too) I chose to do this in pure assembler opposed to the com-encrypter.


Tech stuff:
So far so good, time for some technical stuff - if you already know how
to make exe-encryptors, don't read this it would be a waste of time.

First I wanted to deciede on an decryption/encryption scheme. To keep it simple
and most understandable I choose the simplest scheme possible - the scheme
I used for comcrypt too.
This scheme is remarkably similar to the one I used when passing around love
notes in a distant past. The scheme is to exchange each letter with the next
in the alphabet - the computer equivalence is ofcouse to add 1 to each your
encrypting. Decrypting is then just subtracting one from each byte. Very simple
I think you'll have to agree on that!

So having decieded on that, the next we need is to figure out how an exe-file
is build and how it's loaded. Any exe-file is seperated into two parts:
A header and a part where the code is stored. This part is called the image of
the exefile. The header among other information contains where in the image
the execution of the program should start. So what we want to do is:
1: encrypt the image of the exefile
2: append a decryption routine to the image
3: modify the header so our decryption routine is run first
4: jump to the place the execution would've normally started
Unfortunately it get's a little more complicated than that - first we need
to examine the header a little more

To understand the header of a exe-file two data-types must be 
understood. Like a word is two bytes, a paragraph is 16 bytes and a page is 512
bytes. The first part of the header, the part we're interested in looks as
follows:
   Offset Description
     00h  00d   ID word, either 'MZ' or 'ZM'
     02h  02d   Number of bytes in the last (512 byte) page in the image
     04h  04d   Total number of 512 byte pages in the file
     06h  06d   Number of entries in the segment table
     08h  08d   Size of the header in (16 byte) paragraphs
     0Ah  10d   Minimum memory required in paragraphs
     0Ch  12d   Maximum memory requested in paragraphs
     0Eh  14d   Initial offset in paragraphs to stack segment from header
     10h  16d   Initial offset in bytes of stack pointer from stack segment
     12h  18d   Negative checksum (ignored)
     14h  20d   Initial offset in bytes of instruction pointer from code segment
     16h  22d   Initial offset in paragraphs of code segment from header
     18h  24d   Offset of relocation table from start of file
     1Ah  26d   Overlay number (ignored)
The word at offset 4 is the filesize in pages, rounded up. E.g. a 517 bytes
large exefile would have a 2 here. A 1025 would have a 3 here. The offset at
2 is'nt usually used - due to a bug in an early microsoft linker that made this
word wrong - but if you're doing like you're supposed to, and we are. This
should be: (filesize-headersize) mod 512. So the words at 2 and 4 is connected
like this: (offset4-1)*512+offset2 = filesize. With an exeception, that is if
offset2=0 then offset4*512=filesize.

At offset A (10d) we find the minimum memory in paragraphs. We should be aware
than when we add our decryption code this should be increased with the 
decryptioncode, in paragraphs, since our decryption code needs to be loaded
into memory too.


Offset 0Eh and 10h (14d and 16d) is important to us too. We need to make sure
to get the stack far away from our decryption code, and we would also like
the program to have the same stack once we return return to the program.

Offsets 12h and 14h is very important to us too. This is where the code starts
executing. So these needs to point to our code, and we also need to save these
so when we're done decrypting we can jmp to the right place. Note this is
written as a displacement from where the first segment of the code will be 
loaded.

These are the relevant parts of the exe-header. This short description will 
hopefully be elaborated in the code.

Moving on from the header to how the exefile is loaded. First the exeheader is
read and checked for inconsistensies. Then memory is allocated. Then a PSP
is created (Program Start Prefix) - this is 100h bytes large, e.g. 10 
paragraphs loaded in each it's own segment. It can however be addressed just
like the image - more about that just below. Then the image is loaded, on top 
of the PSP, paragraph for paragrah, each on top of each other all in their own
segment. E.g. 1132:0000 are the same as 1131:0010 again the same as 1130:0020. 
and so forth. Then DS and ES is made to point to the PSP's start. So ds+10h is
where our code is at. Then SP and SS is loaded correctly and finally a jmp
to the entry point is made.

Having covered the theory I'll now present parts of the code with as much 
explaining as possible. I will not cover the basic procedure, the file stuff
or anything like that - just what is relevant to exe-encryption in general.

The over all structure of the program is:
1:Find the file to encrypt
2:copy the header
3:copy and encrypt the image
4:calculate a new header
5:write the new header to the file
6:append the decryption code
7:exit

The two parts of this I'm not gonna comment on - if you cannot understand
what I'm doing in the code, I doubt you have a chance of understanding it at
all - you should go read an assembly book!

The encryption routine is as follows:
enc_buffer:                                  ; Procedure to encrypt a
                                             ; paragraph in cryptbuffr
	    xor   bp,bp                      ; xero bp
            encrypt_loop:            
            sub byte ptr ds:[bp+cryptbuffr],1; encrypt byte at 
                                             ; cryptbuffr +bp
            inc bp                           ; let bp point to the next byte
            cmp bp,10h                       ; are we done yet?
            jnz encrypt_loop                 ; next byte
            ret
This encrypts the paragraph we have loaded onto thr cryptbuffr, using the above
mentioned encryption method.

The header calculation:
calc_header:
            les  ax, dword ptr [header+14h]  ; Save old entry point
            mov  word ptr [jmpsave], ax      ; patch final-jump with entrypoint
            mov  word ptr [jmpsave+2], es
^^^^ Here we get the original entry point from the original header. We patch
this into the code we're gonna append in a short while
  
            les  ax, dword ptr [header+0Eh]  ; Save old stack
            mov  word ptr [stacksave], es    
            mov  word ptr [stacksave+2], ax
^^^^^The same for the stack

            mov  ax, word ptr [header + 8]   ; Get header size
            mov  cl, 4                       ; convert to bytes
            shl  ax, cl                      ; shl ax,4 <=> ax*16
            xchg bx, ax                      ; let dx be the header size in bytes
We  now get the header size in paragraphs and convert it to bytes.

            les  ax, dword ptr [newDTA+26]   ; Get file size
            mov  dx, es                      ; to DX:AX
            push ax
            push dx
Get the filesize from the DTA that was build when we did the findfirst
  
            sub  ax, bx                      ; Subtract header size from
            sbb  dx, 0                       ; file size
Then subtract header size from the totalsize leaving DX:AX to be the image size
in bytes
  
            mov  cx, 10h                     ; Convert to number of paragraphs
            div  cx                          ; form
We then make a division with 10h to make it into paragraphs. AX is now the number 
of full paragraphs and DX is the number of bytes in the last.
  
            mov  word ptr header+14h, dx     ; Save  New entry point in header
            mov  word ptr header+16h, ax   
We now save this in the header so we have a correct entry  

            mov  word ptr header+0Eh, ax     ; and stack
Make the SS in the header point to where we are gonna add the code.
  
            pop  dx                          ; get file length from stack
            pop  ax
Get the filelength again
  
            add  ax,code_end-append_this     ; add decrypter size
            adc  dx, 0
find the length of the exe-file after we have appended our decryption program
  
            mov  cl, 9                       ; 2**9 = 512
            push ax                          ; save ax
            shr  ax, cl                       
            ror  dx, cl
            stc
            adc  dx, ax                      ; filesize in pages
            pop  ax
            and  ah, 1                       ; mod 512
Transform it from bytes into pages. And find the number of bytes in the last
page.
  
            mov  word ptr [header+4], dx     ; new file size
            mov  word ptr [header+2], ax      
save this on the header
  
            push cs                          ; restore ES
            pop  es
We have been messing with ES - we better leave it pointing at CS

Next I'll figure that you yourself can easily figure out how the rest of the
steps works. Nothing in it is too difficult. So I'll move on to the decryption
routine

  Append_this:                               ; decryption code starts here
            call next                        ; calculate delta offset
  next:     pop  bp                          ; bp = IP next
            sub  bp,offset next              ; bp = delta offset
Given that in our original execrypter the offset of this is displaced with the
number of bytes in all the code above this point +100h for the psp we need
to figure out a nice way to point at our data. A call instruction pushes the
return offset onto the stack. We use this and call the next instruction wich
is a pop bp. So that the current address is in bp. We then subtract how much
this code was displaced in our exe-encryption program and we now have a way 
of pointing to our data.
  
            push ds                          ; save ds and es (*IMPORTANT*)
            push es
            push cs                          ; DS = CS
            pop  ds
            push cs                          ; ES = CS
            pop  es
We now use the codesegment as extrasegment and datasegment so we don't over
write anything else and we can keep this little thing in one segment. We also
remember to save the ds and es that we entered with since these will point to
the PSP and therefore is our clue to where the image is loaded.

;*** Decrypt all paragraphs from start till end
            pop es                           ; fetch es
            pop ax                           ; fetch the address of the PSP
We then fetch this right way.

            push es                          ; see to it that the stack is
            push ax                          ; unchanged
Saving them again

offparag:            
            mov cx, 0ffffh                   ; mov cx, imagesize in paragraphs           
                                             ; 0ffffh was patched by the 
                                             ; encryption
            add ax,0fh                       ; let ax point to the last segment
                                             ; of the PSP
the mov cx instruction was patched in the by the exeencrypter program before
it was written to the exefile. with adding 0f to ax it now points to the last
segment of the PSP - or the segment just before where the image was loaded.

loopme:
            inc ax                           ; point one segment further
            mov ds,ax
            xor bx,bx                        ; byte ptr ds:[bx]= first byte in ds
loopme1: 
            add byte ptr ds:[bx],1           ; decrypt! this byte
            inc bx                           ; move the point to next byte
            cmp bx,10h                       ; are we done with this paragraph?
            jne loopme1
            loop loopme
;**** end decrypt all paragraphs
This is basically just the decryption routine.

;**** Decrypt the last couple of bytes
offsetdx:                                    ; Reference so we can patch 
                                             ; next line
            mov cx, 0ffffh                   ; is patched to mov cx, ????
                                             ; where ???? = number of bytes 
                                             ; not in any paragraph

The mov CX was also patched by the execrypting program before it was written 
to the exefile. CX is now the number of bytes in the last paragraph we hav'nt
decrypted yet.

            test cx,cx                       ; is there more bytes to decrypt?
            jz no_more             
If this is zero bytes we just want to continiue

            inc ax                           ; Update ds to point to 
            mov ds,ax                        ; current segment
            xor bx,bx                        ; ds:bx = first byte in current segment
more:
            add byte ptr ds:[bx],1           ; decrypt it
            inc bx                           ; point to next byte
            loop more                        ; do it for all bytes nessecary
no_more:
Otherwise we should decrypt these bytes in that segment


            pop  es  
            pop  ds                          
            mov  ax,es                       ; AX = PSP segment
            add  ax,10h                      ; Adjust for PSP
We now fetch the es and ds as they were given to us when we started our code.
We move it into ax and add 10 so that ax points past the PSP onto the start
of where the image is loaded.

            add  word ptr cs:[bp+jmpsave+2],ax
            add  ax,word ptr cs:[bp+stacksave+2]
We now add this starting segment to where we are gonna jump to and where the
stack is gonna end up.

            cli                              ; Clear intrpts for stack manip.
            mov  sp,word ptr cs:[bp+stacksave]
            mov  ss,ax
            sti
We now disable interupts so it all does'nt fuck up while were messing with the
stack. We leave the stack pointing to where we would like it.

            db   0eah                        ; jmp ssss:oooo
  jmpsave             dd ?                   ; Original CS:IP
ea???????? is the opcode for a jmp to ????:???? so when we get here we'll 
jump right into the original execode since jmpsave has been patched by the
execrypter and the starting segment of the program has been added.

  stacksave           dd ?                   ; Original SS:SP
Here the stack is patched by the execrypter



That's it and that's that!
Now as stated earlier - this code is simplyfied  to the maximum, no error checking
no user interface, no nothing. Any cracker with 3 mins of time could decrypt
this no problem! But changing the encryption algorithm to something powerful,
adding antidebug code and crc-sums should be very straight forward!!

Another way to use this is to remove the encryption/decryption and instead
make another program run before the exe... adding intro's to things you crack
or whatever...

Useful litterature: 40hex no.8 - article on exe-virii by Dark Avenger, various
other 40 hex's, Ralph Brown's interrupt list, turbo assembler manual...

I can be emailed as stone@ftp.one.se - I will try to answer all emails!
Greets goes to my favorite bird in the world, Winterhawk, my regular cracking
partner, landlord, cook and friend, Patriarch, Sci my drinking partner, Uvejr
another drinking partner and last but not least Mr. Mox.


This program, the sourcecode and txt file is to beconsidered beerware - meaning
that if you like it and use it you gotta gimme a beer if you ever meet me!

                                                     /Stone 1996
