e-mail    Debatní kniha    Mapa stránek    Hlavní  
 perličky 
 

Kontrola CRC u EXE souboru

Tomáš Hubálek

Jistě jste si všimli, že mnohé programy (zvláště antivirové) při každém spuštění kontrolují, zda nebyly napadeny počítačovým virem. Pokud byste chtěli takovouto kontrolu zařadit i do svého programu, bude se vám hodit následující perlička.

Princip kontroly je založen na uložení údajů o CRC prvních 5 KB, posledních 5 KB, o délce souboru a čase vytvoření na konec *.EXE souboru a na kontrole těchto údajů při každém spuštěním. Je velmi nesnadné (a asi i nemožné) napsat virus, který nezmění délku a CRC začátku a konce programu. Spuštění programu se při zavádění z hard disku nezpomalí a jakákoli virová nákaza je okamžitě odhalena. Pro úplnost dodávám, že tento postup není odolný proti tzv. stealth virům (řešení by bylo nepoměrně složitější).

Jako variaci na dané téma je vhodné připojit ke zprávě o napadení i reset počítače (oblíbené téma programátorských perliček), nekonečnou smyčku (JMP $) atd. To je vhodné zvláště v případě, že je program určen pro nezkušené uživatele, kteří po přečtení zprávy o poškození souboru zazmatkují a ihned vloží do počítače (nejčastěji) nezalepenou disketu s nejnovější verzí SCANu od (pochybných) známých; a pokud virus hlídá otevření souboru, provedou tak nákazu celého počítače i této diskety.

V příloze přikládám zdrojové texty modulu CRC.C a programu SETCRC.C. Pokud budete chtít, aby program prováděl sebekontrolu, nejprve "nainklůdujete" (hrozné slovo) modul CRC.C. Do procedury main() zařadíte jako první příkaz volání procedury check_crc().

Program odladíte a před vypuštěním mezi uživatele zkompilujete s přepínačem -DSELF_CHECK. Např. takto: tcc -DSELF_CHECK myprog.c. Pak pomocí programu SETCRC připojíte údaje o souboru a program vypustíte do světa. Příkladem použití je i jednoduchý program CRCDEMO.C, který může zároveň sloužit jako udička na viry.

/********************************************************/ /* Modul CRC.C */ /********************************************************/ #include <dos.h> #include <io.h> #include <conio.h> #include <fcntl.h> #include <stdio.h> #include <alloc.h> #define SIZE sizeof(struct FILE_INFO) #define BUFF_SIZE ((long)(5*1024)) /* kontroluje 5 KB */ struct FILE_INFO { char ID[6]; /* vždy CRC-1 */ unsigned long CRC1; /* údaj o CRC začátku */ unsigned long CRC2; /* údaj o CRC konce */ long FDATE; /* datum vytvoř.soub. */ long FSIZE; /* délka souboru */ }; unsigned long check_buffer(char *buff, unsigned size) { unsigned long CRC=0L; unsigned i; for (i=0;i<size;i++) CRC+=*(buff+i)*(i+1); return(CRC); } void check_crc() { #ifdef SELF_CHECK int f; char *buf; struct FILE_INFO FI; unsigned long FSIZE,FDATE; long CRC1,CRC2; buf=malloc(BUFF_SIZE+1); f=_open(_argv[0],O_RDONLY | O_BINARY); getftime(f,(struct ftime *)(&FDATE)); FSIZE=filelength(f); lseek(f,FSIZE-SIZE,SEEK_SET); _read(f,&FI,SIZE); lseek(f,0L,SEEK_SET); _read(f,buf,BUFF_SIZE); CRC1=check_buffer(buf,BUFF_SIZE); lseek(f,FSIZE-BUFF_SIZE-SIZE,SEEK_SET); _read(f,buf,BUFF_SIZE); CRC2=check_buffer(buf,BUFF_SIZE); free(buf); _close(f); if (FI.CRC1 !=CRC1 || FI.CRC2 !=CRC2 || FI.FDATE !=FDATE || FI.FSIZE != FSIZE || strcmp(FI.ID,"CRC-1")!=0) { puts("Soubor je zmenen. Je mozne, ze je napaden pocitacovym virem. Vypnete pocitac,"); puts("nabootujte z ciste systemove diskety a provedte antivirovou kontrolu.\n"); exit(99); } #endif } /********************************************************/ /* program SETCRC.C */ /********************************************************/ #include <dos.h> #include <io.h> #include <conio.h> #include <fcntl.h> #include <stdio.h> #include <alloc.h> #include "crc.c" void set_crc(char *name) { int f; char *buf; struct FILE_INFO FI; long CRC1,CRC2; buf=malloc(BUFF_SIZE+1); strcpy(FI.ID,"CRC-1"); f=_open(name,O_RDWR | O_BINARY); getftime(f,(struct ftime *)(&FI.FDATE)); FI.FSIZE=filelength(f); lseek(f,0L,SEEK_SET); _read(f,buf,BUFF_SIZE); FI.CRC1=check_buffer(buf,BUFF_SIZE); lseek(f,FI.FSIZE-BUFF_SIZE,SEEK_SET); _read(f,buf,BUFF_SIZE); FI.CRC2=check_buffer(buf,BUFF_SIZE); free(buf); FI.FSIZE+=SIZE; lseek(f,0L,SEEK_END); _write(f,&FI,SIZE); setftime(f,(struct ftime *)(&FI.FDATE)); _close(f); } void main(int argc, char *argv[]) { puts("Program pro přidání údajů o kontrolním součtu souboru. "); if (argc==2) set_crc(argv[1]); else puts("Použití: SETCRC <soubor> "); } /******************************************************/ /* Program CRCDEMO.C demonstruje použití modulu CRC.C */ /* Přeložte jej příkazem: */ /* tcc -DSELF_CHECK crcdemo */ /* a pak k němu přidejte údaje o crc příkazem: */ /* setcrc crcdemo.exe */ /******************************************************/ #include <stdio.h> #include "crc.c" void main() { check_crc(); puts("Program je O.K."); }


Pascal - hlavní
Překladače
Vlastní články
Převzaté články
Věci na stáhnutí
Odkazy k tématu
BP7 buglist
Chyba Run-time 200

BASIC