/*
 * Manipuler le checksum 16 bit et 32 bit d'un fichier executable
 * sous windows/dos; peut facilement être adapté à la modification du checksum
 */
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
void Calc16ChkSum(FILE *fp);
void Calc32ChkSum(FILE *fp);
void main(int, char **);
FILE *fp; unsigned long NewHdrOffset, FileSize = 0L; 
unsigned int PageCnt;
#define NEWHDROFFSET  0x3C   /* Emplacement dans l'ancien header
                                avec offset du nouveau header dans l'exe */
void main (int argc, char * argv[])
{ 
   if (argc != 2)
      {
      printf("\n\nUsage: %s \n\n", argv[0]);
      exit(-1);
      }
   if ((fp = fopen(argv[1], "rb")) == NULL)
      {
      printf("\n\nErreur: impossible d'ouvrir : %s\n\n", argv[1]);
      exit(-1);
      }
   fread(&PageCnt, sizeof(int), 1, fp); /* Lire après la signature */
   fread(&PageCnt, sizeof(int), 1, fp); /* Lire la taille de la dèrnière page */
   FileSize = PageCnt;
   fread(&PageCnt, sizeof(int), 1, fp); /*Lire la page entière du compte */
   if (FileSize == 0L)
      FileSize = PageCnt * 512;
   else
      FileSize += (PageCnt - 1) * 512;
   fseek(fp, NEWHDROFFSET, SEEK_SET);  /* Retrouver le nouveau offsetde l'EXE */
   fread(&NewHdrOffset, sizeof(long), 1, fp);  /* et le lire */
   if (NewHdrOffset == 0L)
      Calc16ChkSum(fp);
   else
      Calc32ChkSum(fp);
   fcloseall();
   return;
} 
void Calc16ChkSum(FILE *fp)
{ 
   unsigned int sum16, NxtInt, x;
   unsigned char NxtChar;
   sum16 = 0;
   fseek(fp, 0, SEEK_SET);
   for (x = 0L; x < FileSize / 2L; x++)
      {
      fread(&NxtInt, sizeof(int), 1, fp);
      sum16 += NxtInt;
      }
   /* Prendre le dernier octet si la taille est bizarre */
   if (FileSize % 2)
      {
      fread(&NxtChar, sizeof(char), 1, fp);
      sum16 += (unsigned int)NxtChar;
      }
   printf("\nLe checksum 16bit devrait etre FFFF, et il est %x\n\n",
         sum16);
}
void Calc32ChkSum(FILE *fp)
{ 
   unsigned long sum32, NxtLong, CheckSum32, x;
   unsigned char NxtByte, y;
   sum32 = 0;
   fseek(fp, 0, SEEK_SET);
   /* Caculer le nombre de DWords avant le checksum et les ajouter */
   x = (NewHdrOffset + 8) / 4;
   for ( ; x; x--)
      {
      fread(&NxtLong, sizeof(long), 1, fp);
      sum32 += NxtLong;
      }
   /* Lire le checksum */
   fread(&CheckSum32, sizeof(long), 1, fp);
   /* Ensuite, le reste des DWord dans le fichier */
   for (x = 0; x < (FileSize - NewHdrOffset - 12) / 4; x++)
      {
      fread(&NxtLong, sizeof(long), 1, fp);
      sum32 += NxtLong;
      }
   /* On doit compter les octets en plus du fichier. Normalement, ils
      forment un long avec les bits de poids fort à zéro
   */
   if (0L != (x = FileSize % 4L))
      {
      NxtLong = 0L;
      for (y = 0 ; y < x ; y++)
         {
         fread(&NxtByte, sizeof(char), 1, fp);
         NxtLong += (unsigned long)NxtByte << (8 * y);
         }
      sum32 += NxtLong;
      }
   printf("\nLe checksum 32 bits devrait etre %lx, et il est %lx\n\n",
           CheckSum32, sum32);
}
 | l |