/* Header file for .EXE file validation system. To use the .EXE file */
/* Validation system within your program, #include "exevalid.h", and */
/* add exevalid.c to your program's makefile / project file.         */

/* Other required headers. */
#include <stdio.h>

/* Boolean definitions. */
#ifndef BOOL
typedef int BOOL;
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif

/* Macro definitions */
#define MIN(x, y) ((x) < (y) ? (x) : (y))
#define MAX(x, y) ((x) > (y) ? (x) : (y))

/* Size of buffer to use for reading file. */
#define FILE_BUFFER_SIZE 16000

/* Hash code type definition. */
typedef unsigned long tHash;

/* EXE validation result codes. */
typedef enum
{
   kValid,
   kInvalid,
   kGeneralFailure
} eEXEValidResult;

/* Function prototypes. */
BOOL GetFileHash(FILE *pFile, long lnBytes, tHash *pnHash);
void UpdateHash(tHash *pnHash, char *pBuffer, long lnBytes);
eEXEValidResult ValidateEXE(char *pszEXEFileName);


/* Source for the .EXE file validation fuction ValidateEXE(), along   */
/* with support functions used by ValidateEXE(). To use the .EXE file */
/* Validation system within your program, #include "exevalid.h", and  */
/* add exevalid.c to your program's makefile / project file. See      */
/* exedemo?.c for an example of how to use ValidateEXE(). When your   */
/* program's executable has been built, use the exestamp program to   */
/* create a hash stamp before running your program. To customize the  */
/* hash code used by this program, simply alter or replace the        */
/* UpdateHash() function.                                             */

/* Standard header files. */
#include <stdlib.h>
#include <stdio.h>

/* Our header file. */
#include "exevalid.h"


/* Table used for calculating CRC32s */
unsigned long ulCRC32Table[256] =
   {
   0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL,
   0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L,
   0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L,
   0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L,
   0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
   0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L,
   0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL,
   0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L,
   0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L,
   0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
   0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L,
   0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L,
   0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L,
   0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL,
   0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
   0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL,
   0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL,
   0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L,
   0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L,
   0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
   0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL,
   0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L,
   0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL,
   0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L,
   0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
   0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL,
   0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L,
   0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L,
   0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L,
   0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
   0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L,
   0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL,
   0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL,
   0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L,
   0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
   0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L,
   0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL,
   0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L,
   0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL,
   0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
   0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L,
   0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL,
   0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L,
   0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L,
   0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
   0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL,
   0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L,
   0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL,
   0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL,
   0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
   0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L,
   0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L,
   0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL,
   0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L,
   0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
   0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L,
   0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L,
   0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL,
   0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L,
   0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
   0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L,
   0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL,
   0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L,
   0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL
};
      

      
/*     Function : GetFileHash()
 *
 *      Purpose : Calculates the hash code for the specified number of
 *                bytes beginning at the current position in an open file.
 *
 *   Parameters :   pFile - Pointer to an open stream to calculate hash
 *                          value from.
 *
 *                lnBytes - Number of bytes from file to calculate hash
 *                          on.
 *
 *                 pnHash - Pointer to a variable of type tHash to store
 *                          hash code in.
 *
 * Return Value : TRUE on success, FALSE on failure.
 */
BOOL GetFileHash(FILE *pFile, long lnBytes, tHash *pnHash)
{
   char *pBuffer;
   long lnRead;
   
   /* Initialize hash value. */
   *pnHash = 0xffffffffL;

   /* Allocate a buffer for file reads. */
   pBuffer = (char *)malloc(FILE_BUFFER_SIZE);

   /* If allocation failed, return with an error. */   
   if(pBuffer == NULL)
   {
      return(FALSE);
   }

   /* Loop while there are still more bytes to be read from file. */
   while(lnBytes > 0)
   {
      /* Read next segment from file. */
      lnRead = fread(pBuffer, sizeof(char),
           (size_t)MIN(lnBytes, FILE_BUFFER_SIZE), pFile);

      /* If read did not obtain any characters, return with failure. */         
      if(lnRead == 0)
        {
           return(FALSE);
        }

      /* Update hash value with each byte in the buffer */
      UpdateHash(pnHash, pBuffer, lnRead);

      /* Update number of bytes remaining to be read. */        
      lnBytes -= lnRead;
   }

   /* Release memory for buffer. */
   free(pBuffer);

   /* Return with success. */   
   return(TRUE);
}


/*     Function : UpdateHash()
 *
 *      Purpose : Updates hash code based on passed bytes.
 *                This implementation uses a CRC32 algorithm to calculate
 *                the hash code. You can customize the .EXE file validation
 *                system by using a different algorithm to calculate this
 *                hash code. If you change this algorithm, be sure to also
 *                recompile the exestamp utility.
 *
 *   Parameters :  pnHash - Pointer to variable where old hash value is
 *                          stored, and where new hash value will be
 *                          stored.
 *
 *                pBuffer - Pointer to buffer containing bytes to be
 *                          used to update hash code.
 *
 *                lnBytes - Number of bytes to validate from buffer.
 *
 * Return Value : N/A
 */
void UpdateHash(tHash *pnHash, char *pBuffer, long lnBytes)
{
   /* Work with local copy of hash value. */
   unsigned long nHash = *pnHash;

   /* Loop for each byte in the buffer. */
   while(lnBytes--)
   {
      /* Update hash code with this byte. */
      nHash = ulCRC32Table[(unsigned char)(nHash ^
                           (unsigned long)(*pBuffer++))]
                    ^ ((nHash << 8) & 0x00ffffffL);
   }

   /* Copy hash value back to passed variable. */
   *pnHash = nHash;
}


/*     Function : ValidateEXE()
 *
 *      Purpose : Determines whether or not an .EXE file contains a
 *                valid hash code stamp.
 *
 *   Parameters : pszEXEFileName - Filename of .EXE file to validate.
 *
 * Return Value : One of the following constants:
 *                        kValid - .EXE is valid.
 *                       kInvalid - .EXE is not valid.
 *                kGeneralFailure - Unable to access file or allocate memory.
 */
eEXEValidResult ValidateEXE(char *pszEXEFileName)
{
   FILE *pEXEFile;
   tHash nActualFileHash;
   tHash nRecordedFileHash;
   long lnFileLength;
    
   /* Attempt to open .EXE for read in binary mode. */
   pEXEFile = fopen(pszEXEFileName, "rb");

   /* If open failed, return with failure. */
   if(pEXEFile == NULL)
   {
      return(kGeneralFailure);
   }
  
   /* Determine length of .EXE file. */
   fseek(pEXEFile, 0, SEEK_END);
   lnFileLength = ftell(pEXEFile);
   fseek(pEXEFile, 0, SEEK_SET);

   /* Determine actual hash code of file. */
   if(!GetFileHash(pEXEFile, lnFileLength - sizeof(tHash), &nActualFileHash))
   {
      return(kGeneralFailure);
   }

   /* Read hash code stored in file. */
   if(fread(&nRecordedFileHash, sizeof(tHash), 1, pEXEFile) != 1)
   {
      return(kGeneralFailure);
   }

   /* Close .EXE file. */
   fclose(pEXEFile);
   
   /* File is valid iff recorded hash code and actual hash code are equal. */
   if(nRecordedFileHash == nActualFileHash)
   {
      return(kValid);
   }
   else
   {
      return(kInvalid);
   }
}


/* Source code for .EXE file stamping program. Opens an existing .EXE file, */
/* calculated and writes a hash stamp to the end of the file. If you have   */
/* modified the .EXE file validation system in exevalid.c, you will want to */
/* also recompile this program. To do so, create a "makefile" or "project   */
/* file", and add the exestamp.c and exevalid.c files. Then rebuild the     */
/* exestamp.exe program.                                                    */

/* Standard header files. */
#include <stdio.h>

/* Our header file. */
#include "exevalid.h"

/* Program execution begins here. */
int main(int argc, char *argv[])
{
   FILE *pEXEFile;
   tHash nFileHash;
   long lnFileLength;

   /* Check that correct number of parameters have been provided. */
   if(argc != 2)
   {
      printf("Format: EXEVALID <Program's .EXE filename>\n");
      return(1);
   }

   /* Attempt to open .EXE for read and write in binary mode. */
   pEXEFile = fopen(argv[1], "r+b");

   /* If open failed, return with failure. */
   if(pEXEFile == NULL)
   {
      printf("Unable to access file %s.\n", argv[1]);
      return(1);
   }
  
   /* Determine length of .EXE file. */
   fseek(pEXEFile, 0, SEEK_END);
   lnFileLength = ftell(pEXEFile);
   fseek(pEXEFile, 0, SEEK_SET);

   /* Determine hash code of file. */
   if(!GetFileHash(pEXEFile, lnFileLength, &nFileHash))
   {
      printf("Unable to calculate hash code of file.\n");
      fclose(pEXEFile);
      return(1);
   }

   /* Move to position to write hash code. */
   fseek(pEXEFile, lnFileLength, SEEK_SET);

   /* Write hash code to file. */
   if(fwrite(&nFileHash, sizeof(tHash), 1, pEXEFile) != 1)
   {
      printf("Unable to add hash stamp to file.\n");
      fclose(pEXEFile);
      return(1);
   }

   /* Close .EXE file. */
   fclose(pEXEFile);

   /* Finish with success. */
   printf("Hash stamp has been added to file.\n");
   
   return(0);
}


MZ    	      P    PKLITE Copr. 1994 PKWARE Inc. All Rights Reserved              >    0jr                                 ; s Ӽ S 3WH˴	6! Not enough memory$S-ھ͋+ 3 ,56;]^_rJts33JtJtӅtJtӀrJu.^
tt3ۃt*Jtr#JtJtJuӀs.nV+&^JuӀrJuӀrJuӁ 뽬Ȁ <u[3Î&ЭSPŎ3؋ȋЋ 
      	          	
     .50!.   , ڣ  . =>  ǋعaC&8 
ùى  5 =+> s2,r( @>r"G;r
 t u *w@IN +؎JW _ҋ3.[+P
 /* DOS VERSION */

/* This sample program demonstrates the use of the .EXE file validation */
/* system. This program simply checks whether its .EXE file is valid,   */
/* and displays a message accordingly. To rebuild this file, create a   */
/* "makefile" / "project file" that includes exedemo.c and exevalid.c.  */
/* After compiling the .EXE file, use the exestamp program to create a  */
/* valid hash stamp in the .EXE file.                                   */

/* Include the EXEValid header file. */
#include "exevalid.h"

    
/* Program execution begins here. */
int main(int argc, char *argv[])
{
   if(argc < 1)
   {
      /* Check that EXE filename has been provided. */
      printf("EXE file name is unknown.\n");
      return(0);
   }

   /* Validate EXE and act accordingly. */
   switch(ValidateEXE(argv[0]))
   {
      case kInvalid:
         printf("EXE file does not have a valid hash stamp; aborting.\n");
         return(1);
      case kGeneralFailure:
         printf("Internal error - not enough system resources available.\n");
         return(1);
   }
   
   /* Program execution will only get to this point if .EXE is valid. */
   printf("EXE file is valid, proceeding normally.\n");

   /* Exit program. */   
   return(0);
}


/* WINDOWS VERSION */

/* This sample program demonstrates the use of the .EXE file validation */
/* system. This program simply checks whether its .EXE file is valid,   */
/* and displays a message accordingly. To rebuild this file, create a   */
/* "makefile" / "project file" that includes exedemo.c and exevalid.c.  */
/* After compiling the .EXE file, use the exestamp program to create a  */
/* valid hash stamp in the .EXE file.                                   */

#include "windows.h"

/* Include the EXEValid header file. */
#include "exevalid.h"

/* Program execution begins here. */
int PASCAL WinMain(HINSTANCE hinstCurrent,
                   HINSTANCE hinstPrevious,
                   LPSTR lpszCmdLine,
                   int nCmdShow)
{
   char szEXEFileName[100];

   if(!GetModuleFileName(hinstCurrent, szEXEFileName, sizeof(szEXEFileName)))
   {
      MessageBox(NULL, "Unable to determine .EXE file name.",
         ".EXE Validation Demo", MB_OK);
   }

   /* Validate EXE and act accordingly. */
   switch(ValidateEXE(szEXEFileName))
   {
      case kInvalid:
           MessageBox(NULL,
              "EXE file does not have a valid hash stamp; aborting.",
            ".EXE Validation Demo", MB_OK);
         return(1);
      case kGeneralFailure:
           MessageBox(NULL,
              "Internal error - not enough system resources available.",
            ".EXE Validation Demo", MB_OK);
         return(1);
   }
   
   /* Program execution will only get to this point if .EXE is valid. */
   MessageBox(NULL, "EXE file is valid, proceeding normally.",
      ".EXE Validation Demo", MB_OK);

   /* Exit program. */   
   return(0);
}


MZw    	      P    PKLITE Copr. 1994 PKWARE Inc. All Rights Reserved      w       >    0jr                                ; s Ӽ S 3WH˴	6! Not enough memory$S-ھ͋+ 3 ,56;]^_rJts33JtJtӅtJtӀrJu.^
tt3ۃt*Jtr#JtJtJuӀs.nV+&^JuӀrJuӀrJuӁ 뽬Ȁ <u[3Î&ЭSPŎ3؋ȋЋ 
      	          	
     .50!.   , ڣ  . =>  ǋعaC&8 
ùى  5 =+> s2r( @>r"G;r
 t u *w@IN +؎JW _ҋ3.[+P
 MZ                @                                       	!L!This program requires Microsoft Winshit.
$       NE2m         (2       @ P P \ `          f  
 PzQzEXEDEMOW      KERNELUSER EXEDEMOW.exe                                                                     U VW^Gh>	 F~ t    y v~
 ~ }
 ~>r	 FV
 >  Pjv
   FV~ t ~ t   H vvvv l FV)FV
~
 ~~}	 ~ vpvH    _^U
  VW^WFVF
Vn
^ =  t  uN  FV % ^FFV3F3V% FV3 3 FVFV^W_^ːU #VWhv
F~ t   jj j vvFVj j j vFPFVRPv  =  t  Q vjjFP
= u  0 v	FV9Ft 9Vt	   	     _^Uf *VWvFRPjd  =  t j )RPRPj   FPxa= j bRPMRPj    P j RPRPj    3  = u= u  j RPRPj       _^
                  P3U  tX r"6$>&(*,  ģZ0.( t  !^ģ\.( u a3P  6&  t0@%666P | ؐEU6&6$6*6(6,X]MˌؐEUظ 5.( tv  !DF %R.( t  !)X&6, 3sz X&, >3&= t4 6t3u!j,Ar,Ar
ª   ]MˌؐEU3/ؐEUع  ؐEUVW ؐEUVW.Q
uzzx o vV\ S ' X
uFL.( tA  !_^]Mˋ D %.( tr  !;sEt ؐEUظ P P]M  k[@$+sE69
 w<69 v6 [Z@$+s69
 w69 v6 RSˋBt.    RP6&RPPr  [&    X< t<	t<to
tkGN< t<	t<t\
tX<"t$<\tB3A<\t<"tӋѨuN<t+
t'<"t<\tB3A<\t<"tۋѨu>GB+ģ667CC6X 3< t<	t<t|
tx6?CCN< t<	t<tb
t^<"t'<\t3A<\t<"t\Ѱ\s"N<t.
t*<"t<\t3A<\t<"t\ٰ\s"3  . ؐEU  t  ڎ333t&>   tFu@$F	 P ϋ3_I&6;6uQVW6 _^Yt&?CC
u&]M PPep 5 3t	 =Mu W" ]XSP   P   ؐEUVWV0;t@t3_^]M ؐEUW> tvt3Id_]M USQ QP[Yt[ ] r3]MsP$ X2]Ms ]M2 ˢb
u<"s< r<vטRÊ EUWVFG@tG  Du VށFVD*F;d~3Pv
} D*P3
|3FuX9FtVPFPO
FF~\tPFPf
N
 Pvv0r
FP 	tD ^_f]MːEUVp
u3Vv
vv
^f]MEU3Pvv
	f]MˌؐEU؃VWFf
]F^v-DutE FDut/Dt(;vPSQP4SY[X+)DlY;Nr-3ҋv+SQPS3DP"Y[t&t'+SQVQ YY[tCIEF므LL F+3vF
_^]M U

tL]ˌؐEUVWvDtY@uUuBDǈu
uV XDuP3ۊ\ShtuThis package contains the complete source code for an .EXE file
validation system that can be used in C and C++ programs. Using this
system you can make it more difficult for people to tamper with your
program's executable file. This can be of benifit to prevent users from
altering copyright notices, copy protection schemes and other
information stored in your program's .EXE file.

This package consits of two components:

1.) A small utility program, named exestamp, that will place a hash code
    "stamp" in your program's .EXE file. Currently, this hash code is a
    CRC32.
    
2.) The source code for a routine, named ValidateEXE(), that your
    program can use to determine whether or not it has been tampered
    with. This is done by comparing almost all of your program's .EXE
    file with the hash code stamp that was created using the exestamp
    utility.
    
The steps typically invovled in using this system are:

1.) Include the exevalid.h header file in your program's main module,
    using the line:
    
       #include "exevalid.h"

2.) Add a call to the ValidateEXE() function at the beginning of your
    program's main function, as demonstrated in the exedemod.c/
    exedemow.c files. The ValidateEXE() function accepts a single
    parameter, which must be a pointer to a string containing the full
    path and filename of your program's .EXE file. In DOS, this path and
    filename will be stored in the argv[0] parameter that is passed to
    the main() function. In Windows, this path and filename can be
    obtained by calling the GetModuleFileName() function. The
    ValidateEXE() function will return one of three values. A value of
    kValid indicates that the .EXE file is valid, a value of kInvalid
    indicates that the .EXE file is not valid or does not contain a hash
    code stamp, and kGeneralFailure indicates that ValidateEXE() was
    unable to allocate enough memory or was unable to access the
    specified .EXE file. If you find that ValidateEXE() is unable to
    allocate enough memory, you can adjust the size of its internal
    buffer by chaing the value of FILE_BUFFER_SIZE, in the exevalid.h
    file.
    
3.) Configure your compiler to also build and link in the exevalid.c
    file, or copy the contents of the exevalid.c file to one of your
    program's source code files. Configuring your compiler to build and
    link the exevalid.c file usually involves creating a "makefile" or
    "project file" that lists your program's source code files, along
    with the exevalid.c file.
    
4.) After building your program's .EXE file, but before executing it,
    run the exestamp utility to add a hash code stamp to your program.
    You may wish to automate the creation of the hash code by adding a
    call to the exestamp utility to your makefile. You should try to
    avoid running exestamp more than once on the same .EXE file, as
    doing so will create a second hash code stamp. Running exestamp on
    your program's .EXE file should always be the last thing that you do
    in building the program. If you are compressing the .EXE file using
    a utility such as PKLite, you must do so before running exestamp.
    
5.) When your program executes, the ValidateEXE() function will check
    that the hash code of your program's .EXE file matches the code
    created by exestamp. If the executable file appears valid, your
    program can continue executing normally. If, however, the executable
    has been tampered with, you can abort your program immediately, or
    carry out any other action that you wish.
    
The .EXE file validation system normally stores the hash code at the
very end of the .EXE file, and this hash code is calculated from all
bytes in the file up to the location of the hash code. You could modify
this system to store the hash code elsewhere, but must be careful not to
include the hash code itself in the bytes that are used to generate the
hash code.

How securely does this system prevent tampering with your program's .EXE
file? This system will almost certainly thwart a user attempting to edit
your program's .EXE file using just a hex editor. Unless the user
happens to produce a new .EXE file that generates an identical hash code
to the original, any changes will make the .EXE file appear invalid to
the ValidateEXE() function. Since this system uses a CRC32 as a hash
code, the chances of creating another .EXE file with the same hash code
are very unlikely.

However, if the user knows that your program has been protected using an
unmodified version of this package, they could alter your .EXE file, and
then calculate a new hash code stamp using the exestamp utility. If you
feel that this may happen, you may wish to use a customized version of
this system, that calculates different hash codes. To do this, simply
alter or replace the UpdateHash() function in the exevalid.c file. After
changing the UpdateHash() function, you should recompile your program
and the exestamp utility. Your modification to UpdateHash() could as
simple as adding a constant value to the hash code generated by the
function, or as sophisticated as an entirely new hash function.

This .EXE file validation package was created in 1994 by Brian Pirie,
and is released to the public domain. You are free to do what you wish
with this source code and any programs created with it. I cannot take
any responsibility for any damages incurred due to your use or inability
to use this package. Please keep in mind that no "anti-hacking" system
is 100% secure. It is your responsibility to evaluate the security of
this package in the context of your needs, before using it.

If you have any questions or comments concerning this package, please
feel free to get in touch with me by any of the following means:

   Internet Email : brian@bpecomm.ocunix.on.ca
  FidoNet Netmail : 1:243/8 (you will have to poll for a response.)
            Modem : +1 613 526 4466
Conventional Mail : Brian Pirie
                    #1416 - 2201 Riverside Drive
                    Ottawa, Ontario
                    K1H 8K9
                    Canada
This package contains the complete source
code for an .EXE file validation system that
can be used in C and C++ programs. Using this
system you can make it more difficult for
people to tamper with your program's
executable file. This can be of benifit to
prevent users from altering copyright
notices, copy protection schemes and other
information stored in your program's .EXE
file.