COC C-Source

on Michael Vorburger's Personal Homepage
Home Personal Projects alpha ware

 

Dies ist der Source-Code in C von COC (Checksum on Code)
Weitere Seiten: COC Artikel ] [ COC C-Source ] COC Pascal Binding ]

COC.C

/* PROJECT     : COC - checksum on code
   AUTHOR      : Michael Vorburger, CH-SG
   DATE        : October/November/December 1992
   LAST CHANGE : 8.7.93

   MODULE      : main function
   OUTPUT      : <0 -> Virus,
                 =0 -> OK,
                 >0 -> troubles!

   EXPLANATION :

   Es werden Prüfsummen über das ganze Text-
   segment berechnet und verglichen oder (beim
   ersten Durchlauf) direkt ins Programm ge-
   schrieben. Falls die gefundene Prüfsumme
   identisch mit der gespeicherten war oder
   zum ersten Mal berechnet wurde, liefert
   die Funktion Null (0x0) als Rückgabewert.
   Andere mögliche Werte (=Fehler!) sind:
    -4 : Prüfsumme(n) stimmt nicht mehr. Virus!
    -3 : Länge der Segmente oder gesamten Datei
           hat sich geändert!
    -2 : Länge der Segmente in Basepage und
           Programmheader stimmen nicht überein!
     0 : ALLES OK
     1 : Die Programmdatei konnte nicht gefunden
           werden (Dateiname in SaPrProgName ?)
     2 : Die Prüfsumme konnte (beim ersten Durch-
           lauf) nicht geschrieben werden (wegen
           GEMDOS-Dateifehler). Schreibschutz oä.

  KNOWN PROBLEMS:
     relocation offset should never be 2 or 3
*/


#define HowManyBytesToTest MyBP->p_tlen

#include <portab.h>
#include <tos.h>
#include "coc.h"

extern char SaPrProgName[];

#define mod(x,y) (x % y)
#define MyBP _BasPag

ULONG SaPrLongs[2] = {0,0};     /* Globale    */
ULONG SaPrLens[4] = {0,0,0,0};  /* Variablen! */

WORD SaPrSelfTest( void )
{
  WORD  ec;         /* ExitCode                */
  PH    PHeader;    /* GEMDOS Programmkopf     */
  WORD  FHandle;    /* Dateihandle             */
  ULONG PrgLength;  /* Länge der Programmdatei */
  ULONG ChgdLong[2]; /* re-relozierte Longs    */
  ULONG *ReRelocAdr;
            /* Zeiger auf Longword in ChdgLong */
  UBYTE *PrgBegin = MyBP->p_tbase;
            /* Zeiger auf Beginn TEXT-Segments */
  UBYTE *PrgEnd = PrgBegin + HowManyBytesToTest;
       /* Zeiger auf letztes zu prüfendes Byte */
#pragma warn -sus
  ULONG *curr = PrgBegin;
#pragma warn +sus
                 /* Zeiger auf aktuelle Stelle */
  ULONG FirstRelocAdr;/* erste Relozierungsadr */
  UBYTE RelocOffset;  /* Puffer beim Einlesen  */
  UBYTE *RelocAdr;
     /* Zeiger auf zu (re)relozierende Adresse */
  UBYTE *RelocRnd;
             /* 'abgerundete' Relozierungsadr. */
  ULONG CurLongs[2] = {0,0};  /* Prüfsummen    */

  if ( ( FHandle = Fopen( SaPrProgName,
             SaPrLens[0] == 0 ? FO_RW : FO_READ )
       ) > -1 ) /* evt. wird auch geschrieben */
  {
    PrgLength = Fseek(0, FHandle, 2);
      /* Dateilänge bestimmen, Position jetzt */
      /* Fileende, darum wieder an den Anfang */
    Fseek(0, FHandle, 0);

    Fread(FHandle, sizeof(PH), &PHeader);
                  /* Header einlesen          */
    if ( ( PHeader.tlen == MyBP->p_tlen ) &
                  /* Wenn Header und Basepage */
         ( PHeader.dlen == MyBP->p_dlen ) &
                  /* nicht identisch, stimmt  */
         ( PHeader.blen == MyBP->p_blen ) )
                  /* etwas nicht!             */
    {

      if ( SaPrLens[0] == 0 )
      /* beim ersten Duchlauf SaPrLens setzen */
      {
        SaPrLens[0] = PrgLength;
        SaPrLens[1] = MyBP->p_tlen;
        SaPrLens[2] = MyBP->p_dlen;
        SaPrLens[3] = MyBP->p_blen;

        Fseek( sizeof( PH ) + (ULONG)SaPrLens
                 - (ULONG)PrgBegin, FHandle, 0);
        Fwrite( FHandle, sizeof( SaPrLens ),
                                      SaPrLens );
        /* Diese beiden Zeilen schreiben SaPrLens
           direkt ins DATA-Segment der Programm-
           datei! Beim nächsten Start sind sie
           damit initialisiert. */

      }
      if ( ( SaPrLens[0] == PrgLength ) &
                    /* vergleiche Dateilänge, */
           ( SaPrLens[1] == MyBP->p_tlen ) &
                    /* Länge des TEXT-, DATA- */
           ( SaPrLens[2] == MyBP->p_dlen ) &
                    /* und BSS-Segments mit   */
           ( SaPrLens[3] == MyBP->p_blen ) )
                    /* urspr. Werten          */
      {
        Fseek( sizeof( PH ) + PHeader.tlen
            + PHeader.dlen + PHeader.slen,
            FHandle, 0);
        Fread(FHandle, 4, &FirstRelocAdr);
        /* lies erste Relokationsadresse; Wenn */
        /* es die nicht gibt? - Pech!          */
        RelocAdr = PrgBegin + FirstRelocAdr;
        RelocRnd = (ULONG)RelocAdr - (
            ( (ULONG)RelocAdr - (ULONG)PrgBegin )
                                          % 4 );

        do
        {
          for ( ;
               (ULONG)curr < (ULONG)RelocRnd;
               curr++                           )
          {
            CurLongs[0] ^= *curr;
            CurLongs[1] += *curr;
            /* Prüfsummen über unveränderte d.h.
               nicht relozierte Bytes bilden  */
          }
          ChgdLong[0] = *curr++;
          ChgdLong[1] = *curr++;
          /* lies die nächsten beiden Longs   */

          if ( FirstRelocAdr != 0L )
          /* falls Relozierungsinformationen  */
          {
            do {
              #pragma warn -rpt
              ReRelocAdr = (ULONG)ChgdLong +
                  (ULONG)( RelocAdr - RelocRnd );
              #pragma warn +rpt
              /* Schnautze bei der Warnung <Non
                 portable pointer assignment>
                 Compiler meckert trotzdem...  */

              *ReRelocAdr -= (ULONG)PrgBegin;

              CurLongs[0] ^= ChgdLong[0];
              CurLongs[1] += ChgdLong[0];

              do {
                Fread(FHandle, 1, &RelocOffset);
                if ( RelocOffset == 1 )
                  RelocAdr += 254L;
              } while ( RelocOffset == 1 );
              RelocAdr += RelocOffset;
              RelocRnd = (ULONG)RelocAdr - (
            ( (ULONG)RelocAdr - (ULONG)PrgBegin )
                                          % 4 );
              /* nächste zu re-relozierende
                             Adresse bestimmen */

           if ( ( (ULONG)RelocAdr < (ULONG)curr )
                 & ( RelocAdr < PrgEnd )
                 & ( RelocOffset != 0 ) )
              /* betr. Long schon im Puffer?   */
              {
                ChgdLong[0] = ChgdLong[1];
                ChgdLong[1] = *curr++;
                /* wenn ja, nur weiterschieben */
              }
              else
              {
                CurLongs[0] ^= ChgdLong[1];
                CurLongs[1] += ChgdLong[1];
                /* nein, dann jetzt auch zweiten
                               Teil verrechnen */
              }

            } while ( ( (ULONG)RelocAdr <
                        (ULONG)curr       ) &
                      ( RelocAdr < PrgEnd ) &
                      ( RelocOffset != 0  ) );
          }
        } while ( ( (ULONG)RelocAdr <
                    (ULONG)PrgEnd     ) &
                  ( RelocOffset != 0  ) );

        for ( ;
             (ULONG)curr < (ULONG)PrgEnd;
             curr++ )
        {
          CurLongs[0] ^= *curr;
          CurLongs[1] += *curr;
        }; /* evt. noch bis zum allerletzen
              Byte des TEXT-Segments machen */

        if ( SaPrLongs[0] != 0 )
        /* War das nicht der erste Durchlauf?
           Ja, dann je nach dem, ob Prüfsumme
           mit alter übereinstimmt, 0 oder -4
           zurückliefern.                     */
          ec = ( ( SaPrLongs[0]==CurLongs[0] ) &
                 ( SaPrLongs[1]==CurLongs[1] ) ?
                                       0 : -4 );
        else
        /* sonst (beim ersten Durchgang) Prüf-
           summe direkt in die Datei schreiben */
        {
          Fseek( sizeof( PH ) + (ULONG)SaPrLongs
                - (ULONG)PrgBegin, FHandle, 0 );
          ec = ( Fwrite( FHandle,
                         sizeof(CurLongs),
                         CurLongs )
                  == sizeof(CurLongs) ? 0 : 2 );
        }
      }
      else
        ec=-3;
    }
    else
      ec=-2;

    Fclose(FHandle);
    return ec;
  }
  else   /* Problems while opening programfile */
    return 1;
}

COC.H

#include <portab.h>

WORD SaPrSelfTest( void );

typedef struct
{
	WORD branch;
	LONG tlen;
	LONG dlen;
	LONG blen;
	LONG slen;
	LONG res1;
	LONG prgflags;
	WORD absflag;
} PH;

DEMO.C

/* PROJECT     : COC
   AUTHOR      : Michael Vorburger, CH-SG
   LAST CHANGE : 11.12.92 / 28.6.93

   MODULE      : demo program

   EXPLANATION : This program shows the usage
                 of the virus defence COC.
*/

#include "coc.h"

#include <portab.h>
#include <tos.h>

char *mess[] =
    {"\r\n COC - checksum on program /// "
                        "Testprogramm.\r\n",
     "\r\n 1.Durchlauf: Prüfsumme wird "
         "bestimmt und geschrieben.\r\n\n"};


const char SaPrProgName[] = "DEMO.TOS";

char *err[] = {" VIRUS! checksum has changed!",
        " VIRUS! text-, data- or bss-segment's "
          "or whole file's length has changed!",
        " VIRUS! length of text-, data- or"
          " bss-segment in basepage and"
          "\n\r program-header are not equal!",
        "???",
        " OK - no virus.",
        " PROBLEM: program-file not found! "
          "should be <DEMO.TOS>.",
        " PROBLEM: checksum not written to "
          "file because of gemdos-problem"};


WORD main( void )
{
  extern long SaPrLongs[2];
  WORD i;

  Cconws(mess[0]);
  if ( ( SaPrLongs[0] & SaPrLongs[1] ) == 0 )
    Cconws(mess[1]);

  i=SaPrSelfTest();
  Cconws(err[i+4]);

  Cconws("\r\n");
  Cconin();

  return i;
}

DEMO.PRJ

DEMO.TOS
=
PCSTART.O
DEMO.C
COC.C

PCTOSLIB.LIB
PCSTDLIB.LIB

SAVE_VAR.C

/* PROGRAM     : SAVE_VAR; demoprogram
   AUTHOR      : Michael Vorburger, CH-SG
   DATE        : june 1993
   LAST CHANGE : 28.6.93

   EXPLANATION : Stores a global & initialized
                 variable into the text segment
                 of the executable's program
                 file so that it is initialized
                 with the old value at restart.

         compile this with STANDARD.PRJ
*/

#include <stdio.h>
#include <tos.h>

unsigned int value = 18;
char string[255] = "Miky";

int main( void )
{
    int FHandle;

    printf("\n Last user's age: %u",value);
    printf("\r\n Your age: ");
    scanf("%d",&value);

    printf("\n Last user's name: %s",string);
    printf("\r\n Your age: ");
    scanf("%s", &string);

    printf("\r\n Inputs are directly written "
            "to program's data-segment in file.");

    FHandle = Fopen( "SAVE_VAR.PRG", FO_RW );
    if ( FHandle > -1 )
    {
        Fseek( 28 + (long)&value -
            (long)_BasPag->p_tbase, FHandle, 0 );
        Fwrite( FHandle, sizeof(value), &value );
        Fseek( 28 + (long)string -
              (long)_BasPag->p_tbase, FHandle, 0);
        Fwrite( FHandle, sizeof(string), string );
        Fclose( FHandle );
    }
    else
        return FHandle;

    return(0);
}

Go to TOP of page
Page last modified on 03-Mai-98
© Copyright 1998-99 homepage@vorburger.ch [E-MAIL]

Site hosted by
ItaWeb, Peruggia (Italy)

KISSfp FrontPage Add-On
KISSfp FrontPage

  URL: http://www.vorburger.ch/projects/coc/coc_src.html