-----BEGIN PGP SIGNED MESSAGE----- Article Written for Crisnews By: Michael Stowe "Self-Protecting Executables" -- by Michael Stowe Files which protect themselves are probably one of the most effective weapons against virus spreading. A self-protecting file is a file which tests itself when starting up and refuses to run if it has been altered in any way. Often, self-protecting files will provide the first clue that a virus infection has occurred. This article presents simple C source code which may be used in any program to provide a program with an effective technique for sensing its own integrity. There are two components to the protection scheme; a standalone program which determines an .EXE or .COM file's signature, and "brands" the file with the signature, and a module to be compiled into the executable file that verifies this signature. First, the branding program. It uses a very simple checksum technique to generate a signature. As you can see from the code, it simply xor's each byte with its position in the file and appends the total to the end. The code follows: #include unsigned long int file_brand(char *name) { FILE *fin; register c; register long accum=0; register long count=0; int error=0; if ((fin=fopen(name, "rb+"))==NULL) { perror(name); return ERROR; } while ((c=getc(fin))!=EOF) { accum+=c^count++; } fseek(fin, 0, SEEK_END); fwrite(&accum, sizeof(long), 1, fin); if (ferror(fin)) { perror(name); error = -1; } fclose(fin); return error; } void main(int argc, char **argp) { register errors = 0; while( --argc > 0) errors |= file_brand( *++argp); exit(errors != 0); } The above will generate an executable which takes an .EXE or .COM file as an argument. The checksum will be appended to the end of the file, which will make the file a little longer, but do no damage. If you wish to compress the .EXE or .COM file (e.g., with Pklite), do so BEFORE running the branding program. The companion routines belong in the .C source file which generated the .EXE or .COM file which was just branded: #include #include #include #include /* Sanity check for file */ int file_changed(char *filename) { FILE *fin; register c; register long accum=0; long compare; register long count=0; int error=0; if ((fin=fopen(name, "rb"))==NULL) { perror(name); return -1; } length=filelength(fileno(fin))-sizeof(long); for(count=0; count