summaryrefslogtreecommitdiff
path: root/reference/C/CONTRIB/SNIP/checkexe.c
blob: 8ea43cb4f5f58fcb90ebbc048485f147db931db4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*
** CHECKEXE.C - checksum protection for executable files
**
** by: Bob Jarvis
*/

#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>

static struct {
      unsigned char marker[16];
      unsigned long checksum;
} marker_struct = {"CHECKEXE MARKER",0L};

void checkexe(char *fname)
{
      FILE *fptr;
      unsigned int c;
      int first_time = 0, i;
      char buffer[14];
      unsigned long chksum = 0L;
      unsigned long l;
      unsigned long marker_offset;
      unsigned char *charptr;
      time_t tm;

      fptr = fopen(fname,"r+b");
      if(fptr == NULL)
      {
            fprintf(stderr,"checkexe : unable to open input file '%s'\n",
                  fname);
            exit(99);
      }

      setvbuf(fptr, NULL, _IOFBF, 32767);    /* try to get a 32K buffer */

   /* 
    * If this is the first time the check has been run, scan the entire file
    * to find the marker.  Otherwise proceed.
    */

      if(marker_struct.checksum == 0L)
      {
            first_time = 1;

            c = fgetc(fptr);
            while(!feof(fptr))
            {
                  if(c == (unsigned int)marker_struct.marker[0])
                  {
                        fread(buffer,sizeof(buffer),1,fptr);
                        if(memcmp(buffer,&marker_struct.marker[1],
                              sizeof(buffer)) == 0)
                        {
                              marker_offset = ftell(fptr) + 1L;
                              break;
                        }
                        fseek(fptr,-13L,SEEK_CUR);
                  }

                  c = fgetc(fptr);
            }

            if(feof(fptr))
            {
                  fprintf(stderr,"checkexe : unable to locate marker\n");
                  exit(99);
            }

      /* Change the marker field to random values */

            tm = time(NULL);

            srand((unsigned int)tm);

            for(i = 0 ; i < sizeof(marker_struct.marker) ; ++i)
                  marker_struct.marker[i] = (unsigned char) rand();

            fseek(fptr,marker_offset - sizeof(marker_struct.marker),SEEK_SET);

            fwrite(marker_struct.marker,sizeof(marker_struct.marker),1,fptr);
      }

   /* Calculate the checksum for the entire file */

      rewind(fptr);

      c = fgetc(fptr);
      for(l = 0 ; !feof(fptr) ; ++l)
      {
            chksum += (unsigned long)c;
            c = fgetc(fptr);
      }

      if(first_time)
      {
            marker_struct.checksum = chksum;
            fseek(fptr,marker_offset,SEEK_SET);
            fwrite(&marker_struct.checksum,sizeof(unsigned long),1,fptr);
      }
      else
      {
            charptr = (unsigned char*) &marker_struct.checksum;

            for(i = 0 ; i < sizeof(marker_struct.checksum) ; ++i)
                  chksum -= (unsigned long)(charptr[i]);

            if(chksum != marker_struct.checksum)
            {
                  fprintf(stderr, "\acheckexe : %s has been altered, "
                        "possibly by a virus\n", fname);
                  exit(99);
            }
      }

      fclose(fptr);
      return;
}

main(int argc, char *argv[])
{
      checkexe(argv[0]);
      return EXIT_SUCCESS;
}