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.TOS
=
PCSTART.O
DEMO.C
COC.C
PCTOSLIB.LIB
PCSTDLIB.LIB

/* 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);
}
|