/* PROJECT : COC - checksum on code AUTHOR : Michael Vorburger, CH-SG DATE : October/November/December 1992 LAST CHANGE : 21.5.93 MODULE : main function OUTPUT : <0 -> Virus, =0 -> OK, >0 -> troubles! EXPLANATION : Es werden Prfsummen ber das ganze Text- segment berechnet und verglichen oder (beim ersten Durchlauf) direkt ins Programm ge- schrieben. Falls die gefundene Prfsumme identisch mit der gespeicherten war oder zum ersten Mal berechnet wurde, liefert die Funktion Null (0x0) als Rckgabewert. Andere m”gliche Werte (=Fehler!) sind: -4 : Prfsumme(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 Prfsumme konnte (beim ersten Durch- lauf) nicht geschrieben werden (wegen GEMDOS-Dateifehler). Schreibschutz o„. KNOWN PROBLEMS: relocation offset should never be 2 or 3 */ #define PP /* PurePascal ! */ #define HowManyBytesToTest MyBP->p_tlen #include #include "coc.h" extern char SaPrProgName[]; #if defined( PP ) #include "tos_coc.h" extern ULONG SaPrLongs[2]; extern ULONG SaPrLens[4]; extern struct baspag *BASEPAGE; #define MyBP BASEPAGE #define mod(x,y) (x - (x / y) * y) else #include ULONG SaPrLongs[2] = {0,0}; ULONG SaPrLens[4] = {0,0,0,0}; #define MyBP _BasPag #define mod(x,y) (x % y) #endif 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 prfendes 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]; /* Prfsummen */ CurLongs[0] = 0; CurLongs[1] = 0; #if defined( PP ) { UBYTE l=SaPrProgName[0]; UBYTE i; for( i=0; i -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 - mod( (ULONG)RelocAdr - (ULONG)PrgBegin, 4); do { for ( ; (ULONG)curr < (ULONG)RelocRnd; curr++ ) { CurLongs[0] ^= *curr; CurLongs[1] += *curr; /* Prfsummen 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 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 - mod( (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 Prfsumme mit alter bereinstimmt, 0 oder -4 zurckliefern. */ ec = ( ( SaPrLongs[0]==CurLongs[0] ) & ( SaPrLongs[1]==CurLongs[1] ) ? 0 : -4 ); else /* sonst (beim ersten Durchgang) Prf- 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; }