Scrigroup - Documente si articole

     

HomeDocumenteUploadResurseAlte limbi doc
BulgaraCeha slovacaCroataEnglezaEstonaFinlandezaFranceza
GermanaItalianaLetonaLituanianaMaghiaraOlandezaPoloneza
SarbaSlovenaSpaniolaSuedezaTurcaUcraineana

AdministracjaBajkiBotanikaBudynekChemiaEdukacjaElektronikaFinanse
FizycznyGeografiaGospodarkaGramatykaHistoriaKomputerówKsiążekKultura
LiteraturaMarketinguMatematykaMedycynaOdżywianiePolitykaPrawaPrzepisy kulinarne
PsychologiaRóżnychRozrywkaSportowychTechnikaZarządzanie

Konwencje stosowane przez programy antywirusowe - standard CARO

komputerów



+ Font mai mare | - Font mai mic



DOCUMENTE SIMILARE

Konwencje stosowane przez programy antywirusowe - standard CARO

12.1. Skaning

Historycznie jest to najstarsza technika stosowana przez programy antywirusowe. Skaning polega na wyszukiwaniu w zainfekowanym obiekcie zadanej sekwencji bajtów (sygnatury wirusa).



Poniżej przedstawiono kilka przykładowych sygnatur istniejących wirusów:

B8 ED FE CD 21 A3 03 01 0E 8F 06 6F 01 BA ; sygnatura wirusa Atomie 1.0

BE 30 01 8B 16 17 01 B9 35 01 2E 31 14 83 ; sygnatura wirusa Human Greed

8B FC 36 8B 2D 81 ED 03 01 44 44 1E 06 OE ; sygnatura wirusa DOOM!

5D 83 ED 03 E8 15 00 EB 27 90 E8 OF 00 B4 ; sygnatura wirusa Ethernity

5D 81 ED 03 01 EB 1B 90 B8 24 35 CD 21 ; sygnatura wirusa OLG

Jak widać, tradycyjna sygnatura jest to ciąg bajtów o nieustalonej z góry długości, zapisanych heksalnie, które program antywirusowy konwertuje na rozumianą przez siebie postać binarną (maszynową) i dopiero taki łańcuch poszukiwany jest w przeszukiwanym obiekcie. Z czasem pojęcie sygnatury rozszerzono. Dzisiejsze skanery potrafią interpretować różne symbole oraz znaki globalne (ang. wildcards) np. ? czy *. Poniżej podano przykłady kilku prostych, nieznacznie rozszerzonych sygnatur używających znaków globalnych:

BB ?2 B9 10 01 81 37 ?2 81 77 02 ?2 83 C3 04 E2 F2 ; sygnatura wirusa FireFly

B9 CC 01 BB ?2 2E 81 07 ?2 83 C3 02 ; sygnatura wirusa K-CMOS

1E 06 OE OE 1F 07 2E FE 06 ?2 2E A1 ; sygnatura wirusa Geodesic Propagation

33 CO 8E D8 BE ?2 FF 34 FF 74 02 C7 04 ; sygnatura wirusa 1984

Poniżej zamieszczono listing programu, który umożliwia wyszukiwanie zadanego ciągu bajtów w podanym jako parametr pliku. Zadany ciąg bajtów może być podany Jako łańcuch w apostrofach lub jako zapisane heksalnie dane (możliwa jest także kombinacja podanych metod).

;

Czesc ksiazki : 'Nowoczesne techniki wirusowe i antywirusowe' ;

;

SKANER v1.0, Autor : Adam Blaszczyk 1997 ;

;

Program sluzy do przeszukiwania plikow w celu znalezienia zadanego ;

lancucha bajtow (np. stalej sygnatury wirusa) podanego jako parametr ;

przy wywolaniu programu. ;

;

DANE TECHNICZNE ;

;

; _ Wywolanie: SKANER NazwaPliku CiagBajtow ;

; _ Ciag moze skladac sie z liczb zapisanych heksalnie lub zwyklego tekstu ;

np: ;

_ CD 21 - szuka wywolania przerwania 21h ;

_ 'wirus' - szuka slowa 'wirus' ;

_ 'abc'80C5'def'EE F6 - szuka lancucha 'abc╟+def_≈' ;

; _ Maksymalna dlugosc wyszukiwanego ciagu = 128 bajtow. ;

; _ Dlugosc jednorazowo odczytywanych danych z pliku = 65024 bajtow ;

65024=512*127=127 sektorow, 512 bajtowych ;

; _ Maksymalna ilosc zliczanych wystapien ciagu = 2^32 razy ;

; _ Pliki z atrybutami Hidden, System przed odczytem maja zmieniany atrybut ;

na Archive; po skonczeniu programu przywracany jest oryginalny atrybut ;

; _ Procedura obslugi INT 24h <dialog ARIF-Abort,Retry,Ignore,Fail> ;

zastapiona zostala sekwencja sygnalizujaca blad programowi ;

; _ Wyszukiwane sa wszystkie mozliwe wystapenia ciagu ;

(takze zachodzace na siebie) ;

;

; Definicje Stalych

JUMPS

;stale logiczne

Falsz equ 00h ; definicja dwoch stalych logicznych

Prawda equ Falsz+1 ; / 0=Falsz i 1=Prawda

; stale ogolne

RozmiarStosu equ 128 ; rozmiar stosu w slowach dwubajtowych

RozmiarCiagu equ 128 ; rozmiar bufora na wyszukiwany ciag

RozmiarBuforaDanych equ 127*512 ; rozmiar bufora na dane = segment 64K-512

DlugNazwyPliku equ 128 ; dlugosc pelnej nazwy pliku

LiniaPolecen equ 80h ; adres (w PSP) do parametrow

; stale znakowe

ZnakTabulacji equ 09h ;

ZnakSpacji equ ' ' ;

ZnakKoncaLinii equ 0Dh ; - stale znakowe

CR equ 0Dh ; /

LF equ 0Ah ; /

; stale bledow

; na ich podstawie nastepuje obliczenie ofsetu komunikatu o bledzie

BlBezBledu equ 00h ; nie ma bledu

BlBrakParametrow equ 01h ; blad : nie ma parametrow

BlBrakNazwyPliku equ 02h ; blad : brak nazwy pliku w parametrach

BlBrakCiagu equ 03h ; blad : brak ciagu do wyszukania

BlZlyCiag equ 04h ; blad : ciag zawiera bledy

BlBrakPlikuNaDysku equ 05h ; blad : brak pliku podanego jako parametr

BlBlad_ARIF equ 06h ; blad : brak dostepu do pliku (int 24h)

BlZlyAtrybutPliku equ 07h ; blad : nie plik tylko etykieta dysku lub katalog

BlBrakDostepuDoPliku equ 08h ; blad : nie mozna zmienic atrybutow na archive

BlNieMogeOtworzyc equ 09h ; blad : nie moge otworzyc pliku

BlNieMogeCzytac equ 0Ah ; blad : nie moge czytac pliku

BlNieMogeZamknac equ 0Bh ; blad : nie moge zamknac pliku

BlPlikZaKrotki equ 0Ch ; blad : plik krotszy niz dlugosc ciagu

; stale drukowania wrostkow

7 bit=1 wywolaj procedure konwersji, ktorej adres w [si+1]

7 bit=0 wyswietl tekst, ktorego adres jest pod [si+1]

DrPlik equ 01h ; stala dla wrostka NazwaPliku

DrCiag equ 02h ; stala dla wrostka Ciag

DrUnIntDec equ 83h ; stala dla wrostka - liczby bez znaku typu Int (dziesietne)

DrUnIntHex equ 84h ; stala dla wrostka - liczby bez znaku typu Int (szesnastkowo)

IleWrostkow equ 04h ; ile maksymalnie wrostkow

; stale DOS-owe

TrybOtwarciaPliku equ 00000000b ; oznacza otwarcie pliku tylko do odczytu

AtReadOnly equ 00000001b ;

AtHidden equ 00000010b ;

AtSystem equ 00000100b ;

AtVolumeID equ 00001000b ; - atrybuty pozycji katalogu

AtDirectory equ 00010000b ; /

AtArchive equ 00100000b ; /

AtAll equ 00111111b ; /

; definicja bufora DTA (Disk Transfer Area)

DTA_STRUC struc ; struktura potrzebna dla funkcji

NieWazne db 21 dup(?) ; 4E i 4F sluzacych do poszukiwania

Atrybut db ? ; pierwszego (4E) i nastepnego (4F)

Czas dw ? ; wystapienia w katalogu (pliku, katalogu,itp.)

Data dw ? ; opisuje wszystkie parametry pliku

Dlugosc dd ? ; zawarte w FAT z wyjatkiem pierwszego numeru JAP

Nazwa db 13 dup(?)

DTA_STRUC ends

; Segment Kodu

SKANER SEGMENT

ASSUME CS:SKANER, ds:SKANER

Start: ; poczatek programu

Call UstawParametrySystemu ; ustaw DS+nowe (DTA i int 24h)

mov si,Offset TeCopyRight ;

Call DrukLn ; wyswietl komunikat o programie

Call CzytajParametry ; Wez z PSP:80h parametry : Plik+Ciag

jc Blad ; gdy CF=1, to blad

Call SprawdzPlik ; czy plik istnieje ?

jc blad

Call SzukajLancuch ; Szukaj lancucha w pliku

jc Blad

mov NumerBledu,BlBezBledu ; wszystko OK !

Blad: ; skacz tu, jesli jakis blad

Call PrzywrocParametrySystemu ; stare DTA+INT 24h

Call OstatniKomunikat ; zwraca 0=bez bledu lub FF=blad

mov ah, 4Ch ; funkcja powrotu do systemu DOS

int 21h ; wywolaj funkcje

OstatniKomunikat proc near ; wyswietla komunikat na koncu programu

pushf ; zachowaj znaczniki, potrzebne pozniej

mov ax,seg SKANER

mov ds,ax ; DS=segment danych

mov al, NumerBledu ; al=numer bledu

cbw ; ax=numer bledu

shl ax,1 ; ax=ax*2, bo kazdy ofset=2 bajty

add ax,Offset OffsetyKomunikatow ; ax=tablica z adresami komunikatow bledow

xchg ax,bx ; bx=tablica z adresami komunikatow bledow

; [bx]=tablica[blad]

mov si,[bx] ; dx=offset do komunikatu o bledzie (lub 'OK')

Call DrukLn ; wypisz komunikat

popf ; przywroc znaczniki

mov al,0 ; w al przekaz kod bledu, 0=bez bledu

sbb al,0 ; jezeli blad, to al=FF

ret

OstatniKomunikat endp

SzukajLancuch proc near ; otwiera plik i szuka zadany ciag

; w calym pliku

mov ax,seg ProgDTA ; ustaw ES na segment, do ktorego beda

mov es,ax ; wczytywane dane =127 sektorow

mov ax,word ptr [BufDTA.Dlugosc] ; -DX:AX = dlugosc pliku

mov dx,word ptr [BufDTA.Dlugosc+2] ; /

or dx,dx ; czy b. znacz. czesc dlugosci =0

jnz DlugiPlik ; nie -> dlugosc<>0

cmp ax,DlugoscCiagu ; b. znacz. czesc=0, czy mniej znacz. czesc

jae DlugiPlik ; dlugosci > dlugosc ciagu

mov NumerBledu,BlPlikZaKrotki ; Blad : plik krotszy od ciagu !

jmp short NieMogeOtworzyc ; wyswietl blad

DlugiPlik:

mov si,offset TeSzukamCiagu ; wyswietl informacje o szukaniu

Call DrukLn ; lancuchu w pliku

mov NumerBledu,BlNieMogeOtworzyc ; ewentualny numer bledu

mov dx,Offset NazwaPliku ; nazwa pliku w DS:DX, tryb dostepu w AL

mov ax,3D00h+TrybOtwarciaPliku ; funkcja DOS - otworz plik

int 21h ; DOS : otworz plik

jc NieMogeOtworzyc ; CF=1 -> blad

xchg ax,bx ; BX=uchwyt pliku

Call CzytajSzukaj ; szukaj lancucha w calym pliku

jc NieMogeOtworzyc

mov ah,3Eh ; zamknij plik

int 21h ;

mov ax,word ptr [IleZnalezionych] ; wyswietl, ile razy ciag

mov dx,word ptr [IleZnalezionych+2] ; wystapil w pliku

mov si, offset TeZnalazlem

or dx,dx ; sprawdz, czy przynajmniej

jnz CosZnalazl ; raz, jak ani razu to

or ax,ax ; / inny komunikat

jnz CosZnalazl ; /

mov si, offset TeNieZnalazlem

CosZnalazl:

Call DrukLn ; wyswietl komunikat spod DS:SI

clc ; nie ma bledu

NieMogeOtworzyc:

ret ; powrot z procedury

SzukajLancuch endp

CzytajSzukaj proc near ; czytaj w pliku i szukaj lancuch

; na wejsciu numer pliku w BX

xor ax,ax ;

mov word ptr [IleZnalezionych] ,ax ;

mov word ptr [IleZnalezionych+2],ax ; - wyzeruj zmienne

mov word ptr [AdresCzytania],ax ; /

mov word ptr [AdresCzytania+2],ax ; /

mov NumerBledu,BlNieMogeCzytac ; ewent. blad

xor bp,bp ; BP oznacza odstep od poczatku bufora,

; pod ktory wczytujemy dane, na poczatku=0

dec DlugoscCiagu ; zmniejsz o 1 dlugosc ciagu potrzebne

; w pozniejszej operacji porownania

cld ; w oper. lancuchowych INC(SI,DI)

CzytajDoBufora: ; petla glowna

push ds ; zachowaj DS na stosie

mov ax,es

mov ds,ax ; DS=ES=segment na dane z pliku

mov cx,RozmiarBuforaDanych ; ile czytac danych

mov dx,offset BuforDanych ; DS:DX = tu wczytuj dane

add dx,bp ; dodaj dlug. danych, ktore zostaly z poprz. odczytu

mov ah,3Fh ; DOS : funkcja czytania

int 21h ; DOS : wykonaj funkcje

pop ds ; przywroc DS

jc NieMogeCzytac ; gdy CF=1, to blad

add word ptr [AdresCzytania],ax ; dodaj do pozycji odczytu ilosc

adc word ptr [AdresCzytania+2],0 ; /odczytanaych bajtow

mov [Przeczytane],ax

add ax,bp ; do ilosci odczytanych bajtow dodaj dlugosc danych

; /pozostalych z poprzedniego odczytu

cmp ax,DlugoscCiagu ; ax=dlugosc danych do porownania

jb KoniecPliku ; - jesli mniej niz ciag, to nie trzeba porownywac

; / bo i tak ciag sie nie znajdzie

xchg ax,cx ; cx=dlugosc danych do porownania

push cx ; zachowaj do pozniejszego porownania

mov di,offset BuforDanych ; poczatek danych

SzukajPierwszej:

mov si,Offset Ciag ; ofset do wyszukiwanego ciagu

lodsb ; al=pierwsza litera ciagu, INC(SI)

repnz scasb ; szukaj, az znajdzie w danych pierwsza litere

jnz NieMaPierwszej ; jesli nie znalazl, to czytaj dalej z pliku

cmp cx,DlugoscCiagu ; czy wystarczy danych w buforze do porownania ?

jae PorownajCaly ; jest co najmniej tyle lub wiecej to OK

inc cx ; - za malo danych

dec di ; - cofnij DI,CX na poprzednie wartosci

mov si,di ; - skopiuj koncowke bufora na poczatek

mov di,offset BuforDanych ; - zachowaj w BP dlugosc tej koncowki

mov bp,cx ; - w nastepnym odczycie dane wczytane

rep movs byte ptr es:[di],es:[si] ; - umieszczone beda za ta koncowka

jmp short NieMaPierwszej ; - a porownywanie sie powtorzy, ale teraz beda dane

PorownajCaly:  ; - do porownania, po skoku czytaj dalej dane

push cx ;

push di ; zachowaj aktualna pozycje w buforze i licznik

mov cx,DlugoscCiagu ; dokladniej : dlugosc ciagu-1 bo nie musimy porownywac

; pierwszej litery, ktora juz byla sprawdzona

jcxz JednoLiterowy ; jesli CX=0, to ciag byl jednoliterowy

rep cmpsb ; porownaj cx bajtow

jne NieMaLancucha ; jesli ZF=0, nie znalazl ciagu

JednoLiterowy:

mov ax,word ptr [AdresCzytania] ; DX:AX=32 bitowa pozycja odczytu pliku

mov dx,word ptr [AdresCzytania+2]

sub ax,[Przeczytane]

sbb dx,0

sub ax,bp

sbb dx,0

pop di ; przywroc odleglosc od poczatku bufora

push di ; zachowaj di

dec di ; zmniejsz wskaznik, zeby wskazywal na pierwsza litere

add ax,di

adc dx,0 ; dodawanie 32 bitowe

; DX:AX = adres fizyczny wzgledem pocz. pliku

mov word ptr [AdresZnalezienia],ax ; -zapamietaj ten adres w zmiennej, bo procedura

mov word ptr [AdresZnalezienia+2],dx; /konwersji korzysta z ofsetu do zmiennej, zeby ja wyswietlic

mov si,offset TeZnalezionyNaPozycji ; -wyswietl tekst ze znalazl

Call DrukLn ; /adres : wyswietl szesnastkowo i dziesiatkowo

add word ptr [IleZnalezionych],1 ; -zwieksz 32 bitowy licznik wystapien

adc word ptr [IleZnalezionych+2],0 ; /dodaj ewentualne przeniesienie z 15 na 16 bit

NieMaLancucha:

pop di ;

pop cx ; przywroc aktualna pozycje w buforze+licznik

jcxz NieMaPierwszej ; czy juz caly bufor pusty ?

; xor bp,bp ; zeruj dlugosc koncowki

jmp short SzukajPierwszej ; skocz i szukaj nastepnego wystapienia

NieMaPierwszej:

pop ax ; zdejmij ilosc odczytanych danych ze stosu

cmp ax,RozmiarBuforaDanych ; i porownaj, czy tyle ile bylo wczytywanych

jb KoniecPliku ; jesli nie tyle samo, to koniec pliku

; jesli tyle samo, to czytaj dalej

jmp CzytajDoBufora ; skocz i czytaj dalej dane

KoniecPliku:  ; dane sie skonczyly

clc ; nie ma bledu

NieMogeCzytac:

ret ; wroc z procedury

CzytajSzukaj endp

PrzywrocParametrySystemu proc near ; przywraca stare adresy DTA+Int 24h

; i ewentualnie atrybuty pliku

; (jezeli sytemowy, ukryty)

pushf ; zachowaj flagi z ew. bledem

cmp ZmienAtrPliku,Prawda ; czy przywrocic atrybut ?

jne NiePrzywracajAtrybutu ; skocz jesli nie

mov ax,4301h ; DOS: funkcja 43xxh wez(xx=0)/ustaw(xx=1) atr. pliku

xor ch,ch ; ch=0

mov cl,[BufDTA.Atrybut] ; cx=stare atrybuty

mov dx,Offset NazwaPliku ; DS:DX =nazwa pliku

int 21h ; DOS : zmien atrybuty

NiePrzywracajAtrybutu:

push ds ; zachowaj segment danych

push ds ; 2 razy -> na pozniej

lds dx,dword ptr [StareI24Ofs] ; przywroc stara obsluge bledow

mov ax,2524h ; ustaw Int 24h

int 21h ; funkcja 25h - ustaw wektor (numer w AL)

pop ds ; przywroc segment danych

lds dx,dword ptr [StareDTAOfs] ; przywroc stare DTA

mov ah,1Ah ; funkcja 1Ah - ustaw DTA

int 21h ; wywolaj funkcje

pop ds ; przywroc segment danych

popf ; przywroc znaczniki z ew. bledem

ret ; powrot z procedury

PrzywrocParametrySystemu endp

UstawParametrySystemu proc near ; ustaw obsluge przerwania 24h

; nowy bufor DTA

mov ax,seg SKANER

mov ds,ax ; DS=segment danych

mov MojAdresPSP,es ; zachowaj PSP

mov ax,3524h ; funkcja wez adres przerwania (num. w AL)

int 21h ; wez stare INT 24h do rejestrow ES:BX

mov StareI24Ofs,bx ; - zachowaj stare przerwanie

mov StareI24Seg,es ; / ES=segment, BX=offset

mov ah,2Fh ; wez stare DTA do rejestrow ES:BX

int 21h

mov StareDTAOfs,bx

mov StareDTASeg,es ; ES=segment, BX=ofset

mov dx,Offset BufDTA

mov ah,1Ah ; ustaw nowe DTA na adres zawarty w DS:DX

int 21h

push ds ; zachowaj DS

push cs ; -DS=CS

pop ds ; /

mov dx,offset NoweInt24 ; ustaw nowe przerwanie 24h

mov ax,2524h ; w DS:DX

int 21h

pop ds ; przywroc DS

ret ; powrot z procedury

UstawParametrySystemu endp

NoweInt24 proc near ; procedura obslugi przerwania programowego bledow

; krytycznych wywolywana przez DOS w razie bledu

push ds ;

push ax ; -zachowaj DS i AX

mov ax,seg SKANER

mov ds,ax ; ds=segment danych

mov NumerBledu,BlBlad_ARIF ; zachowaj numer bledu

pop ax ;

pop ds ; -przywroc DS i AX

mov al,3 ; pomin blad-program sam zadecyduje co dalej

iret ; nie wywoluj standardowego dialogu ARIF

NoweInt24 endp ; powrot z procedury obslugi przerwania programowego

SprawdzPlik proc near ; szukaj plik podany jako parametr

mov ZmienAtrPliku,Falsz ; na razie nie znamy atrybutow, wiec nie trzeba

; przywracac oryginalnych

mov NumerBledu,BlBrakPlikuNaDysku ; ustaw ew. numer bledu

mov ah,4Eh ; funkcja szukaj pozycji katalogu

mov dx,offset NazwaPliku ; DS:DX nazwa pliku

mov cx,AtAll ; w CX podaj atrybut szukanej pozycji

int 21h ; wywolaj funkcje

jc NieMaPliku ; gdy CF=1, to blad

mov si,offset BufDTA ; nie ma bledu , info o pliku jest w buforze DTA

mov al,[BufDTA.Atrybut] ; wez atrybut pliku

mov NumerBledu,BlZlyAtrybutPliku ; ewent. blad

test al,AtVolumeID+AtDirectory ; sprawdz, czy etykieta lub katalog (testuj bity)

stc ; ustaw ewent. blad

jnz NieMaPliku ; skocz, bo etykieta lub dysk

test al,AtHidden+AtSystem ; testuj bity : ukryty lub system

mov NumerBledu,BlBrakDostepuDoPliku ; ewent. blad

jz NieZmienAtr ; nie sa ustawione, to skocz dalej

mov ZmienAtrPliku,Prawda ; trzeba zmienic atrybut, zeby mozna bylo odczytac

mov ax,4301h ; funkcja ustaw atrybut pliku

mov cx,AtArchive ; cx=atrybyt jaki ustawic

mov dx,Offset NazwaPliku ; DS:DX nazwa pliku

int 21h ; wywolaj funkcje

jc NieMaPliku ; gdy CF=1, to blad

NieZmienAtr:

clc ; nie ma bledu, plik gotowy do odczytu

NieMaPliku:

ret ; wroc z procedury

SprawdzPlik endp

CzytajParametry proc near ; wez parametry z PSP:80h

push ds ; zachowaj DS

mov ax,ds ; ES=DS=segment z danymi

mov es,ax

mov ds,MojAdresPSP ; DS=blok PSP

mov si,LiniaPolecen ; ofset w PSP do linii polecen

mov es:NumerBledu,BlBrakParametrow ; ewentualny numer bledu

cmp byte ptr ds:[si],0 ; dlugosc linii polecen

je BladParametrow ; jezeli pusta, to nie ma parametrow

inc si ; pomin licznik

inc si ; pomin spacje

cld ; INC(SI,DI) w oper. na lancuchach

Call OpuscSpacje ; czytaj az znak <> SPACJA lub TAB

mov es:NumerBledu,BlBrakNazwyPliku ; ewentualny numer bledu

cmp al,ZnakKoncaLinii ; czy koniec parametrow ?

je BladParametrow ;- jesli tak, to powrot z procedury

mov di, offset NazwaPliku ; es:di : tu zapisz wyniki

Call KopiujDoSpacji ; kopiuj nazwe pliku

mov es:NumerBledu,BlBrakCiagu ; ewentualny numer bledu

cmp al,ZnakKoncaLinii ; czy koniec parametrow ?

je BladParametrow ;- jesli tak, to powrot z procedury

xor al,al ; plik ASCIIZ, wiec dodaj zero

stosb

Call OpuscSpacje ; czytaj az znak <>SPACJA lub TAB

cmp al,ZnakKoncaLinii ; czy koniec parametrow

je BladParametrow ; jesli tak, to blad

mov es:NumerBledu,BlZlyCiag ; ewentualny numer bledu

mov di, offset Ciag ; es:di : tu zapisz ciag

Call KopiujCiagDoKonca ; kopiuj parametr : ciag

jc BladParametrow ; jesli TAK, to blad

mov ax,di

sub ax,offset Ciag

jz BladParametrow ; jesli TAK, to lancuch pusty

mov es:DlugoscCiagu ,ax ; - zachowaj dlugosc ciagu

mov es:AbsDlugoscCiagu ,ax ; - zachowaj 2-i raz dlugosc ciagu

clc ; nie ma bledu

jmp short $+3 ; skocz i pomin rozkaz STC

BladParametrow:

stc ; jest blad

pop ds

ret ; wroc z procedury

CzytajParametry endp

OpuscSpacje proc near

lodsb ; czytaj znak z ds:[si], inc si

cmp al,ZnakSpacji ;

je OpuscSpacje ; czy spacja lub znak tabulacji ?

cmp al,ZnakTabulacji ; / jezeli tak, to czytaj nastepny znak

je OpuscSpacje ;/

dec si ; zmniejsz wskaznik na poprzedni znak

ret ; powroc z procedury

OpuscSpacje endp

KopiujDoSpacji proc near

KopiujZnak:

lodsb ; czytaj znak z ds:[si], inc si

cmp al,ZnakSpacji ;

je NieKopiuj ; czy spacja lub znak tabulacji

cmp al,ZnakTabulacji ; lub koniec linii polecen

je NieKopiuj ; /jezeli tak, to koncz kopiowanie

cmp al,ZnakKoncaLinii ; /

je NieKopiuj ;/

stosb ; skopiuj znak

jmp short KopiujZnak ; skocz i wez nastepny znak

NieKopiuj:

dec si ; zmniejsz wskaznik na poprzedni znak

ret ; powroc z procedury

KopiujDoSpacji endp

KopiujCiagDoKonca proc

Pa_Nic = 00

Pa_Apostrof = 01

mov bl,Pa_Nic ; nie bylo znaku specjalnego

mov bh,0

KopiujParamZnak:

lodsb ; czytaj znak z ds:[si], inc si

cmp bl,Pa_Apostrof ; czy tekst w apostrofach ?

jne ZwyklyTekst ; NIE - dane heksalne

cmp al,39 ; czy znak apostrofu ?

jne NieKoniecTekstu ; Nie - idz dalej

mov bl,Pa_Nic ; koniec tekstu w apostrofach

jmp KopiujParamZnak ; idz po kolejny znak

NieKoniecTekstu:

stosb ; kopiuj zwykly tekst

jmp KopiujParamZnak ; wez kolejny znak

ZwyklyTekst:

cmp al,39 ; czy apostrof poczatkowy

jne NiePoczatektekstu ; NIE - sprawdzaj dalej

mov bl,Pa_Apostrof ; ustaw flage

jmp KopiujParamZnak ; idz po nastepny znak

NiePoczatektekstu:

cmp al,ZnakKoncaLinii ; pomin, gdy znak=CR

je KoniecParamTekstu ; /

cmp al,ZnakSpacji ; pomin, gdy znak=spacja

je KopiujParamZnak ; /

cmp al,ZnakTabulacji ; pomin, gdy znak=TAB

je KopiujParamZnak ; /

cmp al,'0' ; czy znak >=0 ?

jb KoniecParamTekstuBlad ; < blad

cmp al,'9' ; czy znak 0..9 ?

jbe ToCyfra09 ; TAK - cyfra

and al,0DFh ; 'a'..'z'->'A'..'Z'

cmp al,'A' ; czy znak <'A' ?

jb KoniecParamTekstuBlad ; TAK - blad

cmp al,'F' ; czy znak >'F' ?

ja KoniecParamTekstuBlad ; TAK - blad

; znak '0'..'F'

ToCyfra09:

cmp bh,0 ; czy licznik znakow=0 ?

je ToPierwszyZnak ; TAK - zachowaj znak na pozniej

cmp al,'9' ; czy znak to cyfra ?

jbe ALJest09 ;

sub al,'A'-'0'-10 ; konwertuj na liczbe

ALJest09:

cmp ah,'9' ; czy drugi znak to cyfra ?

jbe AHJest09

sub ah,'A'-'0'-10 ; konwertuj na liczbe

AHJest09:

sub ax,'00' ;

mov bh,al ; konwersja liczby

mov al,16 ; heksalnej zapisanej

mul ah ; / jako lancuch, na zwykla

add al,bh ; / liczbe (znak ASCII)

stosb ; / i zapisz znak

mov bh,0 ; licznik znakow znow=0

mov bl,Pa_Nic ; 'czyste' wyjscie

jmp KopiujParamZnak ; wez nastepny znak

ToPierwszyZnak:

mov ah,al ; zachowaj pierwszy znak liczby

mov bh,1 ; jest juz jeden znak

jmp KopiujParamZnak ; idz po nastepny znak

KoniecParamTekstu:

cmp bx,Pa_Nic ; czy 'czyste' wyjscie ?

je KoniecParamTekstu2 ; jezeli nie, to blad

dec si ; zmniejsz wskaznik na poprzedni znak

KoniecParamTekstuBlad:

stc ; gdy CF=1, to nie ma bledu

jmp $+3 ; przeskocz 'CLC'

KoniecParamTekstu2:

clc ; gdy CF=0, to nie ma bledu

ret ; powrot z procedury

KopiujCiagDoKonca endp

DrukLn proc near ; drukowanie tekstu ACSIIZ spod DS:SI

; z przejsciem do nastepnej linii

Call Druk ; wydrukuj tekst

push si ;

mov si,Offset TeCRLF ;

Call Druk ;

pop si ; --- przejdz do nastepnej linii

ret ; powrot z procedury

DrukLn endp

Druk proc near ; drukowanie tekstu ACSIIZ spod DS:SI

push ax ;

push bx ;

push cx ;

push si ; --- zachowaj zmieniane rejestry

DrukZnak: ; petla drukowania jednego znaku

cmp si,offset CiagStart ;

jb ToNieParamtekst ; jezeli drukowany jest

cmp si,offset CiagKoniec ; w obszarsze lancucha 'CiagBajtow'

jae ToNieParamtekst ; to pozwol drukowac kazdy znak

mov cx,AbsDlugoscCiagu ;

add cx,offset CiagStart ; /

cmp si,cx ; /

jae KoniecDruku ; /

lodsb ; /

jmp short ToParamtekst ; /

ToNieParamtekst:

lodsb ; wez kolejny znak z lancucha

or al,al ; sprawdz, czy ostatni znak ?

jz KoniecDruku ; jesli tak, to wszystko wydrukowane

mov cx,IleWrostkow ; Ile zdefiniowanych wrostkow

mov bx,Offset TablicaWrostkow ; tablica z definicjami

SzukajWrostka: ; -sprawdz, czy al nie oznacza wrostka

cmp ds:[bx],al ; /

jne NastepnyWrostek ; jesli nie, to sprawdz nastepny w tablicy

test al,80h ; czy 7 bit ustawiony ?

jz NormalnyDruk ; nie - to ofset do tekstu

Call ds:[bx+1] ; tak - to procedura konwersji

xor al,al ; zeruj dla pozniejszego porownania

inc si ; - pomin ofset do liczby do konwrsji

inc si ; /

jmp short NastepnyWrostek ; sprawdz nastepny wrostek w tablicy

NormalnyDruk:

push si ; wrostek to tekst spod ofsetu w tablicy

mov si,ds:[bx+1] ; wrostkow

Call Druk ; wyswietl wrostek

pop si

xor al,al ; zeruj dla pozniejszego porownania

NastepnyWrostek:

add bx,3 ; zwieksz index do tablicy wrostkow

loop SzukajWrostka ; powtorz cx razy

or al,al ; czy to byl wrostek (al=0) ?

jz DrukZnak ; jesli tak, to wez nastepny znak

ToParamtekst:

mov ah,02h ; wyprowadz znak na

mov dl,al ; standardowe wyjscie DOSa

int 21h

jmp short DrukZnak ; skocz i wez nastepny znak lancucha

KoniecDruku:

pop si ; --- przywroc zmienione rejestry

pop cx ; /

pop bx ; /

pop ax ; /

ret ; wracaj

Druk endp

Bin2HexUnInt32 proc near ; procedura wyswietla 32 bitowa liczbe szesnastkowa

; ofset do liczby znajduje sie w si

push ax ;

push bx ;

push dx ;

push si ; --- zachowaj zmieniane rejestry

mov bx,[si] ; wez ofset do liczby 32 bitowej

mov ax,[bx] ; - wczytaj liczbe do DX:AX

mov dx,[bx+2] ; /

mov si,offset Hex2DecBufor ; ustaw na poczatek bufora

mov bx,offset HexChars ; wez ofset do tablicy z cyframi szesnastkowymi

push ax ; zapamietaj mniej znacz. slowo

mov ax,dx ; najpierw bar. znacz. slowo

Call Bin2HexUnInt16 ; konwertuj liczbe 16 bitowa

pop ax ; przywroc mniej znacz. slowo

Call Bin2HexUnInt16 ; terax mniej znacz. slowo

mov word ptr [si],'h' ; ustaw na koncu znak 'h' i 0

mov si,offset Hex2DecBufor ; - wyswietl liczbe

Call Druk ; /

pop si ; --- przywroc zmienione rejestry

pop dx ; /

pop bx ; /

pop ax ; /

ret ; powrot

Bin2HexUnInt16: ; wewnetrzna procedura wywoluje 'zstepujaco'

; kolejne nizsze ranga procedury konwersji

push ax

mov al,ah ; konwertuj b. znacz. czesc AX

Call Bin2HexUnInt8

pop ax ; konwertuj m. znacz. czesc AX

Bin2HexUnInt8: mov ah,al

shr al,1 ;

shr al,1 ; wyizoluj 4 bity (4..7)

shr al,1 ; / al=gorna polowa liczby

shr al,1 ; / szesnastkowej

Call Bin2HexUnInt4 ; konwertuj b. znacz. bity (4..7)

mov al,ah

and al,15 ; wyizoluj 4 bity (0..3)

Bin2HexUnInt4:

xlatb ; al=byte ptr ds:[bx+al]

mov [si],al ; zachowaj znak w buforze

inc si ; zwieksz indeks

ret ; powrot z wen. procedury

Bin2HexUnInt32 endp

Bin2DecUnInt32 proc near ; wyswietla liczbe 32 bitowa bez znaku dziesietnie

push ax ;

push bx ;

push dx ;

push si ; --- zachowaj zmieniane rejestry

mov si,[si] ; wez ofset do liczby 32 bitowej

mov ax,[si] ; - wczytaj liczbe do DX:AX

mov dx,[si+2] ; /

mov si,offset Hex2DecBufor+10 ; ustaw na koniec bufora, bo zapis od konca

mov byte ptr ds:[si],0 ; utworz ASCIIZ (dodaj zero na koncu)

DzielPrzez10:

mov bx,10 ; dziel DX:AX przez BX

Call Dziel32 ; w bx reszta z dzielenia

add bl,'0' ; dodaj ASCII '0'

dec si ; zmniejsz indeks do tablicy

mov byte ptr ds:[si],bl ; zapisz cyfre

or dx,dx ;

jnz DzielPrzez10 ;

or ax,ax ;

jnz DzielPrzez10 ; --- czy liczba jest juz 0 ?

Call Druk ; wyswietl lancuch z liczba po konwersji

pop si ; --- przywroc zmienione rejestry

pop dx ; /

pop bx ; /

pop ax ; /

ret ; powrot

Bin2DecUnInt32 endp

Dziel32 proc near ; dziel (dx:ax)/bx

push bp ; zachowaj bp

push ax ; zachowaj mniejsza czesc liczby 32 bitowej

mov ax,dx ; przenies b. znacz. czesc do mniej. znacz.

xor dx,dx ; i wyzeruj dx , dx:ax = > 0:dx

div bx ; podziel (0:dx)/bx

mov bp,ax ; calosc z dzielenia, to wieksza czesc wyniku

pop ax ; przywroc do AX mniej znaczaca liczbe z poczatku

div bx ; dx jest reszta z dzielenia b. znacz. czesci przez BX

mov bx,dx ; w bx reszta z dzielenia

mov dx,bp ; dx:ax=liczba podzielona przez bx,

pop bp ; a w bx reszta z dzielenia

ret

Dziel32 endp

; (teksty komunikatow+zmienne ogolne)

TeCopyRight db CR,LF,'SKANER v1.0, Autor : Adam Blaszczyk 1997'

db CR,LF

db CR,LF,' Wywolanie: SKANER NazwaPliku CiagBajtow'

db CR,LF

db CR,LF,' CiagBajtow moze skladac sie z liczb zapisanych heksalnie lub zwyklego'

db CR,LF,' tekstu np: '

db CR,LF,' _ CD 21 - szuka wywolania przerwania 21h'

db CR,LF,' _ ''wirus'' - szuka slowa 'wirus''

db CR,LF,' _ ''abc''80C5''def''EE F6 - szuka lancucha 'abc╟+def_≈''

TeCRLF db CR,LF,0

TeSzukamCiagu db 'Szukam lancuch '',DrCiag ,'' w pliku '',DrPlik,''',0

TeBezBledu db 'OK !',0

TeBrakParametrow db 'BLAD : Podaj Parametry !',0

TeBrakNazwyPliku db 'BLAD : Podaj nazwe pliku !',0

TeBrakCiagu db 'BLAD : Podaj ciag do wyszukania',0

TeZlyCiag db 'BLAD : Podany ciag zawiera bledy !',0

TeBrakPlikuNaDysku db 'BLAD : Nie moge znalezc pliku '',DrPlik,''',0

TeBlad_ARIF db 'BLAD : Brak dostepu do pliku '',DrPlik,'' (int 24h) !',0

TeZlyAtrybutPliku db 'BLAD : '',DrPlik,'' to etykieta dysku lub katalog !',0

TeBrakDostepuDoPliku db 'BLAD : Brak dostepu do pliku - nie mozna chwilowo zmienic atrybutow ! ',0

TeNieMogeOtworzyc db 'BLAD : Nie moge otworzyc pliku '',DrPlik,''',0

TeNieMogeCzytac db 'BLAD : Nie moge czytac pliku '',DrPlik,''',0

TeNieMogeZamknac db 'BLAD : Nie moge zamknac pliku '',DrPlik,''',0

TePlikZaKrotki db 'BLAD : Plik '',DrPlik,'' jest krotszy niz ciag !',0

OffsetyKomunikatow dw offset TeBezBledu ; BlBezBledu equ 00h

dw offset TeBrakParametrow ; BlBrakParametrow equ 01h

dw offset TeBrakNazwyPliku ; BlBrakNazwyPliku equ 02h

dw offset TeBrakCiagu ; BlBrakCiagu equ 03h

dw offset TeZlyCiag ; BlZlyCiag equ 04h

dw offset TeBrakPlikuNaDysku ; BlBrakPlikuNaDysku equ 05h

dw offset TeBlad_ARIF ; BlBlad_ARIF equ 06h

dw offset TeZlyAtrybutPliku ; BlZlyAtrybutPliku equ 07h

dw offset TeBrakDostepuDoPliku ; BlBrakDostepuDoPliku equ 08h

dw offset TeNieMogeOtworzyc ; BlNieMogeOtworzyc equ 09h

dw offset TeNieMogeCzytac ; BlNieMogeCzytac equ 0Ah

dw offset TeNieMogeZamknac ; BlNieMogeZamknac equ 0Bh

dw offset TePlikZaKrotki ; BlPlikZaKrotki equ 0Ch

TeNieZnalazlem db 'Nie znalazlem lancucha '',DrCiag ,'' w pliku '',DrPlik,'' !',0

TeZnalazlem db 'Ciag '',DrCiag ,'' wystapil '

db DrUnIntDec

dw offset IleZnalezionych

db ' raz(y) w pliku '',DrPlik,'' !',0

TeZnalezionyNaPozycji db 'Ciag '',DrCiag ,'' wystapil na pozycji '

db DrUnIntHex

dw offset AdresZnalezienia

db ','

db DrUnIntDec

dw offset AdresZnalezienia

db 0

HexChars db '0123456789ABCDEF'

TablicaWrostkow db DrPlik

dw offset NazwaPliku

db DrCiag

dw offset Ciag

db DrUnIntDec

dw offset Bin2DecUnInt32

db DrUnIntHex

dw offset Bin2HexUnInt32

NumerBledu db ?

MojAdresPSP dw ?

AdresCzytania dd ?

AdresZnalezienia dd ?

Przeczytane dw ?

IleZnalezionych dd ?

DlugoscCiagu dw ?

AbsDlugoscCiagu dw ?

StareDTAOfs dw ?

StareDTASeg dw ?

StareI24Ofs dw ?

StareI24Seg dw ?

ZmienAtrPliku db ?

Hex2DecBufor db 11 dup(?)

CiagStart:

Ciag db RozmiarCiagu dup(?)

CiagKoniec:

NazwaPliku db DlugNazwyPliku dup(?)

BufDTA DTA_STRUC <>

SKANER ENDS

; Segment DTA

; do wczytywania danych (127 sektorow 512 bajtowych=65024 bajtow)

ProgDTA SEGMENT

BuforDanych db RozmiarBuforaDanych dup(?) ; bufor na dane z pliku

ProgDTA ENDS

; Segment Stosu

ProgStos segment word stack 'STACK' ; ustaw STOS

dw RozmiarStosu dup(?)

ProgStos ends

end start

12.2. Heurystycze wyszukiwanie wirusów

Jak wspomniano we wstępie, większość istniejących wirusów to najczęściej przeróbki, stąd techniki wykorzystywane w pierwowzorach są bez większych zmian implementowane w kolejnych, nowych pokoleniach wirusów.

Wykorzystując ten fakt, twórcy programów antywirusowych zaczęli stosować technikę heurystycznego wykrywania kodu, polegającą na tym, iż na podstawie znajomości charakterystycznych, klasycznych sekwenqi instrukcji zawartych w typowych wirusach, można znaleźć nieznane jeszcze, ale wykorzystujące je wirusy. Typowe instrukcje wykorzystywane przez wirusy zostały wymienione w poprzednich rozdziałach, np. przy okazji omawiania instalacji w systemie i przejmowania przerwań. Poniżej pokazano kilka instrukcji podatnych na heurystykę lub sekwencji znajdujących się najczęściej w kodzie typowego wirusa plikowego. Jeżeli program antywirusowy, przeszukując pamięć lub plik, zidentyfikuje je (lub też inne), najczęściej informuje o tym użytkownika. Często wykrycie nawet kilku charakterystycznych bajtów w pamięci może umożliwić wykrycie nieznanego jeszcze wirusa. Poszukiwanie sekwencji może być prowadzone bądź to przy okazji zwykłego skaningu, bądź też podczas kontrolowanego uruchamiania programów (tryb krokowy, emulacja procesora).

CMP AX, 4B00h ; sprawdƒ czy jest uruchamiany jaki£ program

; 3D,00,4B kod maszynowy rozkazu

CMP DS:[0],Z ; czy ostatni blok pamiΩci

; 80,3E,00,00, 5A kod maszynowy rozkazu

MOV AX, 2521h ; funkcja DOS ustaw adres przerwania 21h

INT 21h ; wywo│aj funkcjΩ B8,21,25,CD,21 kod maszynowy

; sekwencji

MOV WORD PTR [l],0008 ; ustaw blok jako systemowy w nag│≤wku MCB

; C7,06,01,00,08,00 kod maszynowy instrukcji

CALL NEXT ; weƒ relatywny offset NEXT:

; E8,00,00 kod instrukcji

Zamieszczony poniżej program stara się znaleźć w całej wykorzystywanej przez programy użytkowe pamięci operacyjnej sekwencje, które zwykle są wykorzystywane przez wirusy.

;

Czesc ksiazki : 'Nowoczesne techniki wirusowe i antywirusowe' ;

;

HEUR v1.0, Autor : Adam Blaszczyk 1997 ;

;

; Program przeglada bloki MCB obecne w systemie i poszukuje w ;

; nich kilku standardowo wystepujacych w wirusach sekwencji ;

; Przy jego uzyciu mozna wykryc w pamieci niektore wirusy ;

; rezydetne ;

; Dane techniczne ;

;

; Pierwszy bajt sygnatury jest w pliku zXORowany z wartoscia 0AAh, a po ;

; uruchomieniu programu przywraca oryginalna wartosc pierwszego bajtu ;

; Dzieki temu program nie wykryje sygnatur np. w buforach dyskowych lub ;

; buforach programow cache (np. SMARTDRV) ;

;

; Program nie sprawdza blokow wolnych (wskaznik PSP w polu bloku MCB=0) ;

;; ;; ;;

JUMPS

HEUR SEGMENT

ORG 100h

ASSUME CS:HEUR, DS:HEUR

NUL = 00h ;

LF = 0Ah ; - stale znakow

CR = 0Dh ; /

IleSygnZebyAlarm = 10 ; okresla, ile sygnatur musi wystapic

; w badanym bloku MCB, aby potraktowac

; jego zawartosc za podejrzana

; i wyswietlic ostrzezenie

DlugProgPara = (Offset Koniec-Offset Start+15)/16+10h

; okresla dlugosc programu w pamieci

Sygn struc ;

SygnNazwa db 45 dup (?) ;

SygnDlug dw 0 ;

Sygn00 db 0 ;

Sygn01 db 0 ;

Sygn02 db 0 ; struktura opisujaca

Sygn03 db 0 ; / sygnature wirusa

Sygn04 db 0 ; /

Sygn05 db 0 ; /

Sygn06 db 0 ; /

Sygn07 db 0 ; /

Sygn ends ; /

DlugoscSygnatury = Size Sygn ; dlugosc struktury

Start:

lea si,TeCopyRight ; SI=ofset do informacji o programie

Call DrukLn ; wyswietl info o programie

Call SzukajHeur ; szukaj sekwencji w pamieci

mov ax,4C00h ; funkcja DOS - koncz program

int 21h ; wywolaj funkcje

SzukajHeur:

push es ax bx cx dx ; zachowaj zmieniane rejestry

mov bx,IleSygnatur ; ile sygnatur do odXORowania

lea si,Sygnatury ; skad pobierac sygnatury

add si,size SygnNazwa+size SygnDlug

; i gdzie XORowac bajt

XORujSygnature:

xor byte ptr [si],0AAh ; przywroc prawdziwy bajt sygnatury

add si,DlugoscSygnatury ; wez kolejna sygnature

dec bx ; zmniejsz licznik sygnatur

jnz XORujSygnature ; powtarzaj dla kazdej sygnatury

mov IloscSygn,0

mov ax,5802h ; funkcja DOS - czy UMB dolaczone ?

int 21h ; wywolaj funkcje

push ax ; zachowaj informacje na pozniej

mov ax,5803h ; funkcja DOS - dolacz/odlacz bloki UMB

mov bx,1 ; sprobuj dolaczyc bloki UMB

int 21h ; wywolaj funkcje

mov ah,52h ; funkcja DOS - wez adres listy list LL

int 21h ; wywolaj funkcje

mov ax,es:[bx-2] ; wez adres pierwszego bloku MCB

NastepnyMCB: ; kolejne bloki MCB

mov es,ax ; ES=MCB

mov bl,byte ptr es:[0] ; zachowaj info o znaczniku bloku

mov dx,es:[0003] ; DX=rozmiar bloku MCB

mov cx,es:[0001] ; CX=adres PSP z bloku MCB

Call SzukajWBloku

stc ; +1 w dodawaniu ponizej

adc ax,word ptr es:[0003] ; dodaj rozmiar bloku MCB+1

; AX=nastepny blok MCB

cmp bl,'M' ; czy to posredni blok ?

je NastepnyMCB ; TAK - przegladaj

cmp bl,'Z' ; czy to ostatni blok ?

je OstatniBlokMCB ; TAK - zakoncz przegladanie

; zly blok MCB - naruszona struktura

lea si,TeZlyMCB ; wyswietl komunikat

Call DrukLN ; / o blednym bloku MCB

OstatniBlokMCB:

pop bx ; przywroc info o UMB

mov bh,0 ; BX=BL

mov ax,5803h ; funkcja DOS - dolacz/odlacz bloki UMB

int 21h ; wywolaj funkcje

pop dx cx bx ax es ; przywroc zmieniane rejestry

cmp IloscSygn,0 ;

jne SzukajHeurPowrot ;

; - jezeli nie znalazl zadnej

lea si,TeNieMaSygnatur ; / sygnatury to wyswietl komunikat

Call DrukLN ; /

SzukajHeurPowrot:

ret ; powrot

SzukajWBloku: ; szuka sygnatury w bloku MCB

; AX=blok MCB

; DX=dlugosc bloku w paragrafach

push ds es ax bx cx dx si di ; zachowaj zmieniane rejestry

or cx,cx ; czy blok jest nieuzywany ?

je SzukajWBlokuPowrot ; TAK - nie sprawdzaj i powroc

mov AdresMCB,ax ; zapamietaj adres MCB

inc ax ; ES:0= MCB+1:0

mov es,ax ; ES wskazuje na dane w bloku

lea si,TeSprawdzam ;

Call Druk ;

lea si,TeBlokMCB ;

Call Druk ;

mov ax,AdresMCB ;

Call DrukHEX16 ; wypisz info o szukaniu

lea si,TeRozmiar ; / w bloku MCB i podaj jego

Call Druk ; / adres, dlugosc

mov ax,dx ; /

Call DrukHex16 ; /

lea si,TeParagraf ; /

Call DrukLn ; /

mov bx,cs ;

mov ax,es ; czy to MCB programu HEUR ?

cmp ax,bx ; / TAK-nie sprawdzaj kodu programu

jne InnyBlok ; / ale sprawdz poza nim

mov ax,DlugProgPara

sub dx,ax ; odejmij dlugosc kodu

or dx,dx ; czy nie odjete za duzo ?

jz SzukajWBlokuPowrot ; /

add ax,AdresMCB ; ES=dane poza kodem programu

mov es,ax ; /

InnyBlok:

or dx,dx ; pomin blok, gdy dlugosc =0

je SzukajWBlokuPowrot ; /

mov IloscBiezSygn,0 ; licznik wystapien w bloku

cld ; SI:=SI+1, DI:=DI+1 po oper. lancuchowych

xor di,di ; dane sa pod ES:0000

SzukajDalej:

mov bx,IleSygnatur ; ustaw licznik sygnatur

lea si,Sygnatury ; podaj, skad pobierac sygnatury

SzukajSygnature:

push si ; zachowaj zmieniane SI

mov bp,si ; zachowaj ofset do nazwy sygnatury

add si,size SygnNazwa+size SygnDlug

; dodaj ofset do sygnatury

lodsb ; wez 1-szy bajt sygnatury

scasb ; czy=bajt w pamieci ?

jnz NastepnaSygnatura ; NIE - sprawdz kolejna sygnature

; TAK - porownaj cala sygnature

mov cx,word ptr ds:[si-3] ; wez dlugosc sygnatury

dec cx ; pierwszego bajtu nie trzeba

; porownywac

push di ; DI jest pozniej potrzebne wiec zachowaj

rep cmpsb ; porownaj sygnature z pamiecia

pop di ; przywroc DI

jnz NastepnaSygnatura ; NIE - nie ma sygnatury

; TAK - sygnatura znaleziona

inc IloscSygn ; zwieksz ilosc wystapien (globalna)

inc IloscBiezSygn ; zwieksz ilosc wystapien (w MCB)

lea si,TeAdres ;

Call Druk ; wyswietl jaka sygnatura

mov ax,es ; zostala znaleziona

Call DrukHEX16 ; i pod jakim adresem

mov ax,0E3Ah ;

int 10h ;

mov ax,di ;

dec ax ; /

Call DrukHex16 ; /

lea si,TeSygnatura ; /

Call Druk ; /

mov si,bp ; /

add si,SygnNazwa ; /

Call DrukLn ; /

NastepnaSygnatura:

pop si ; przywroc SI

add si,DlugoscSygnatury ; i ustaw na nastepna sygnature

dec di ; ustaw wskaznik na poprzedni bajt

dec bx ; zmniejsz licznik sygnatur

jnz SzukajSygnature ; jezeli nie, to sprawdz kolejna sygnature

NastepnyBajt:

inc di ; wskaznik na nastepny bajt w bloku

and di,15 ; czy ofset>15

jnz SzukajDalej ; NIE - szukaj sygnatur

; TAK - zwieksz numer segmentu

mov di,es ;

inc di ; ES:DI=ES:0010:=ES+1:0

mov es,di ; /

xor di,di ; /

NieZmienSeg:

dec dx ; zmniejsz ilosc paragrafow w bloku

jnz SzukajDalej ; NIE - kontynuuj sprawdzanie

cmp IloscBiezSygn,IleSygnZebyAlarm

; czy ilosc wykrytych sygnatur jest

; odpowiednio duza ?

jb SzukajWBlokuPowrot ; NIE - powrot

lea si,TePrawdopodWirus ; TAK - wypisz o tym komunikat

Call DrukLn ; /

SzukajWBlokuPowrot:

pop di si dx cx bx ax es ds ; przywroc zmieniane rejestry

ret ; powrot

DrukLn:

push si ; zachowaj zmieniany rejestr

call Druk ; wyswietl tekst z CS:SI

lea si,TeCRLF ; i przejdz do nastepnej linii

Call Druk ; /

pop si ; przywroc zmieniany rejestr

ret ; powrot

Druk:

push ax si ; zachowaj zmieniane rejestry

DrukPetla:

lods byte ptr cs:[si] ; wez kolejny znak tekstu

or al,al ; czy NUL ?

jz DrukPowrot ; TAK - koniec tekstu

mov ah,0Eh ; funkcja BIOS - wyswietl znak

int 10h ; wywolaj funkcje

jmp short DrukPetla ; pobierz kolejny znak tekstu

DrukPowrot:

pop si ax ; przywroc zmieniane rejestry

ret ; powrot

DrukHEX16:

push ax ; zachowaj 8 dolnych bitow

mov al,ah ; AL=AH=wyzsze 8 bitow

Call DrukHEX8 ; wyswietl wyzsze 8 bitow

pop ax ; przywroc 8 dolnych bitow

DrukHEX8:

push ax ; zachowaj 4 dolne bity

shr al,1 ; wez 4 gorne bity

shr al,1 ; do AL (podziel przez 16)

shr al,1 ; /

shr al,1 ; /

Call DrukHEX4 ; wyswietl 4 gorne bity

pop ax ; przywroc 4 dolne bity

and al,15 ; utworz z nich liczbe 0..F

DrukHEX4:

push bx ; BX bedzie potrzebne wiec zachowaj

lea bx,HexZnaki ; ustaw BX na tablice konwersji

xlatb ; konwertuj 0..F na '0'..'Z','A'..'Z'

; AL=cyfra

mov ah,0Eh ; funkcja BIOS - wyswietl znak z AL

int 10h ; wywoluje funkcje

pop bx ; przywroc BX

ret ; powrot

HexZnaki db '0123456789ABCDEF' ; tablica konwersji

TeCopyRight db CR,LF,'HEUR v1.0, Autor : Adam Blaszczyk 1997'

db CR,LF

db CR,LF,'_ Szukam sygnatur ',NUL

db CR,LF

TeCRLF db CR,LF,NUL

TeZlyMCB db CR,LF,'_ Struktura blokow MCB pamieci jest zaklocona !',NUL

TeSygnatura db ': Znaleziona sygnatura : ',NUL

TeNieMaSygnatur db CR,LF,'_ Nie znalazlem zadnej sygnatury !',NUL

TePrawdopodWirus db CR,LF,'_ UWAGA : W ostatnio sprawdzanym bloku MCB moze byc wirus !'

db CR,LF,' Swiadczy o tym ilosc znalezionych w nim sygnatur !',NUL

TeAdres db ' Adres=',NUL

TeBlokMCB db ' MCB=',NUL

TeRozmiar db ', Rozmiar MCB=',NUL

TeParagraf db ' paragrafow',NUL

TeSprawdzam db '_ Sprawdzam',NUL

Sygnatury:

Sygn <'CALL $+3; POP BX ',4,0E8h xor 0AAh,000h,000h,05Bh>

Sygn <'CALL $+3; POP BP ',4,0E8h xor 0AAh,000h,000h,05Dh>

Sygn <'CALL $+3; POP SI ',4,0E8h xor 0AAh,000h,000h,05Eh>

Sygn <'CALL $+3; POP DI ',4,0E8h xor 0AAh,000h,000h,05Fh>

Sygn <'CMP AX,4B00h; JZ ?? ',4,03Dh xor 0AAh,000h,04Bh,074h>

Sygn <'CMP AX,4B00h; JNZ ?? ',4,03Dh xor 0AAh,000h,04Bh,075h>

Sygn <'CMP AX,'MZ' ',4,03Dh xor 0AAh,05Ah,04Dh,075h>

Sygn <'CMP AX,'ZM' ',4,03Dh xor 0AAh,04Dh,05Ah,075h>

Sygn <'MOV AX,2521h; INT 21h ',5,0B8h xor 0AAh,021h,025h,0CDh,021h>

Sygn <'MOV AH,52h; INT 21h ',4,0B4h xor 0AAh,052h,0CDh,021h>

Sygn <'MOV AX,4300h; CALL NEAR [] ',4,0B8h xor 0AAh,000h,043h,0E8h>

Sygn <'MOV AX,4300h; PUSHF; CALL D PTR CS:[]',6,0B8h xor 0AAh,000h,043h,02Eh,09Ch,0FFh>

Sygn <'MOV AX,4301h; CALL NEAR [] ',4,0B8h xor 0AAh,001h,043h,0E8h>

Sygn <'MOV AX,4301h; PUSHF; CALL D PTR CS:[]',6,0B8h xor 0AAh,001h,043h,02Eh,09Ch,0FFh>

Sygn <'MOV AX,5700h; CALL NEAR [] ',4,0B8h xor 0AAh,000h,057h,0E8h>

Sygn <'MOV AX,5700h; PUSHF; CALL D PTR CS:[]',6,0B8h xor 0AAh,000h,057h,02Eh,09Ch,0FFh>

Sygn <'MOV AX,5701h; CALL NEAR [] ',4,0B8h xor 0AAh,001h,057h,0E8h>

Sygn <'MOV AX,5701h; PUSHF; CALL D PTR CS:[]',6,0B8h xor 0AAh,001h,057h,02Eh,09Ch,0FFh>

Sygn <'MOV AX,3D02h; CALL NEAR [] ',4,0B8h xor 0AAh,002h,03Dh,0E8h>

Sygn <'MOV AX,3D02h; PUSHF; CALL D PTR CS:[]',6,0B8h xor 0AAh,002h,03Dh,02Eh,09Ch,0FFh>

Sygn <'MOV AX,4200h; CALL NEAR [] ',4,0B8h xor 0AAh,000h,042h,0E8h>

Sygn <'MOV AX,4200h; PUSHF; CALL D PTR CS:[]',6,0B8h xor 0AAh,000h,042h,02Eh,09Ch,0FFh>

Sygn <'MOV AX,4202h; CALL NEAR [] ',4,0B8h xor 0AAh,002h,042h,0E8h>

Sygn <'MOV AX,4202h; PUSHF; CALL D PTR CS:[]',6,0B8h xor 0AAh,002h,042h,02Eh,09Ch,0FFh>

Sygn <'MOV AH,3Fh; CALL NEAR [] ',3,048h xor 0AAh,03Fh,0E8h>

Sygn <'MOV AH,3Fh; PUSHF; CALL D PTR CS:[] ',5,0B4h xor 0AAh,03Fh,02Eh,09Ch,0FFh>

Sygn <'MOV AH,40h; CALL NEAR [] ',3,048h xor 0AAh,040h,0E8h>

Sygn <'MOV AH,40h; PUSHF; CALL D PTR CS:[] ',5,0B4h xor 0AAh,040h,02Eh,09Ch,0FFh>

Sygn <'CMP DS:[0],'Z'; JZ ?? ',4,080h xor 0AAh,03Fh,05Ah,074h>

Sygn <'CMP DS:[0],'Z'; JNZ ?? ',4,080h xor 0AAh,03Fh,05Ah,075h>

Sygn <'CMP ES:[0],'Z'; JZ ?? ',5,026h xor 0AAh,080h,03Fh,05Ah,074h>

Sygn <'CMP ES:[0],'Z'; JNZ ?? ',5,026h xor 0AAh,080h,03Fh,05Ah,075h>

Sygn <'MOV DS:[1],0008h ',6,0C7h xor 0AAh,006h,001h,000h,008h,000h>

Sygn <'MOV ES:[1],0008h ',7,026h xor 0AAh,0C7h,006h,001h,000h,008h,000h>

Sygn <'MOV DS:[100h],???? ',4,0C7h xor 0AAh,006h,000h,001h>

Sygn <'MOV ES:[100h],???? ',5,026h xor 0AAh,0C7h,006h,000h,001h>

Sygn <'MOV AX, 100h; PUSH AX; RET ',5,0B8h xor 0AAh,000h,001h,050h,0C3h>

Sygn <'MOV CX, 100h; PUSH CX; RET ',5,0B9h xor 0AAh,000h,001h,051h,0C3h>

Sygn <'MOV DX, 100h; PUSH DX; RET ',5,0BAh xor 0AAh,000h,001h,052h,0C3h>

Sygn <'MOV BX, 100h; PUSH BX; RET ',5,0BBh xor 0AAh,000h,001h,053h,0C3h>

Sygn <'MOV AX, 100h; JMP AX ',5,0B8h xor 0AAh,000h,001h,0FEh,0E0h>

Sygn <'MOV CX, 100h; JMP CX ',5,0B9h xor 0AAh,000h,001h,0FEh,0E1h>

Sygn <'MOV DX, 100h; JMP DX ',5,0BAh xor 0AAh,000h,001h,0FEh,0E2h>

Sygn <'MOV BX, 100h; JMP BX ',5,0BBh xor 0AAh,000h,001h,0FEh,0E3h>

Sygn <'MOV DS:[0086],CS ',4,08Ch xor 0AAh,00Eh,086h,000h>

Sygn <'MOV ES:[0086],CS ',5,026h xor 0AAh,08Ch,00Eh,086h,000h>

Sygn <'MOV AX,DS; DEC AX; MOV DS,AX ',5,08Ch xor 0AAh,0D8h,048h,08Eh,0D8h>

Sygn <'MOV AX,ES; DEC AX; MOV ES,AX ',5,08Ch xor 0AAh,0C0h,048h,08Eh,0C0h>

Sygn <'MOV AL,3; IRET ',3,0B4h xor 0AAh,003h,0CFh>

IleSygnatur = ($-offset Sygnatury)/DlugoscSygnatury

AdresMCB dw ?

IloscBiezSygn dw ?

IloscSygn dw ?

Koniec:

HEUR ENDS

END Start

12.3. Tryb krokowy

Do wykrywania zaawansowanych polimorficznych wirusów nie można stosować zwykłego skaningu, gdyż kod wirusa za każdym razem wygląda zupełnie inaczej. Możliwym wyjściem jest w tej sytuacji wykorzystanie trybu krokowego procesora. Program antywirusowy uruchamia sprawdzany program w trybie krokowym pod kontrolą odpowiedniego monitora tego przerwania przy użyciu np. (4B01/21). Po każdej wykonanej instrukcji wywoływany jest monitor, który sprawdza, czy np. aktualnie wykonywana instrukcja pasuje do listy chararakterystycznych, stałych instrukcji wirusa (jego wersji odszyfrowanej). Jeżeli instrukcja spełnia wymagania, monitor - przy użyciu dozwolonego w tym przypadku skaningu - sprawdza, czy w kodzie jest już odszyfrowany wirus. Jeżeli po przekroczeniu jakiejś wartości granicznej wykonanych instrukcji monitor nie wykryje żadnego podejrzanego kodu, sztucznie kończy program i sygnalizuje, iż nie ma w nim wirusa.

12.4. Emulacja procesora

Ze względu na to, iż omówiony w poprzednim punkcie tryb krokowy można oszukać, autorzy programów AV musieli zastosować inną metodę kontrolowanego uruchamiania programów. W tym celu wbudowali w swe programy interpretator asemblera, dzięki któremu mogą emulować wykonywanie początkowych intrukcji programu, mając jednocześnie nad nim pełną kontrolę. Ze względu na ciągły rozwój procesorów linii 80x86 interpretator asemblera musi być stale rozwijany. Nieuwzględnienie instrukcji wszystkich procesorów spowoduje bowiem, iż przy najbliższym wystąpieniu instrukcji, której monitor jeszcze nie potrafi rozpoznać, jego działanie zostanie zakończone z wynikiem negatywnym. Do niedawna sprawa miała się tak na przykład z kodami 66h, 67h, będącymi interfejsem rozszerzoych instrukcji dla procesorów 386 i wyższych. Niektóre wirusy celowo wykorzystywały je do oszukiwania programów antywirusowych, które po ich napotkaniu kończyły sprawdzanie pliku.

12.5. Przynęty (ang. baits, decoys)

Jedną z technik używanych do łapania prostych wirusów są przynęty. Są to programy, dające się zainfekować ewentualnemu wirusowi. Najczęściej na kod takiego programu składa się kilkaset lub kilka tysięcy razy powtórzona operacja NOP oraz instrukcja zakończenia programu. Program antywirusowy może tworzyć kilka lub więcej takich plików i następnie wykonywać z nimi różne operacje: uruchamiać, otwierać, czytać i zapisywać do nich na różne sposoby, aby dać szansę ewentualnemu wirusowi na ich zainfekowanie.

Wygenerowana przynęta powinna jak najbardziej przypominać typowy program, i to zarówno pod względem długości, jak i zawartości. Jeżeli bowiem długość pliku jest znacząca, tzn. np. wynosi jakąś wielokrotność liczb 10 czy 16, wirus może nie zainfekować takiego pliku.

12.6. Odświeżanie programów systemowych w sektorach

Ta dość trywialna technika służy do nadpisywania programów istniejących w BOOT-sektorach lub Głównych Rekordach Ładujących. Jednym z efektów wykonania takiego odświeżania może być usunięcie nieznanego jeszcze wirusa z zajmowanego przez niego sektora. Podczas przeprowadzania operacji odświeżania należy pamiętać, iż niektóre wirusy całkowicie przejmują kontrolę nad danymi zawartymi w sektorach systemowych, tak więc zamazanie wirusa może spowodować, iż podczas następnego startu systemu system nie będzie się ładował z twardego dysku lub też - co gorsza - nie będzie można odczytać zapisanych na dysku danych.

Możliwe wyjście z tej sytuacji polega na zapisaniu aktualnego stanu dysku (zawartości sektorów) w kopii bezpieczeństwa np. na czystej dyskietce, aby można było później odtworzyć operację odświeżania. Ze względu na możliwość stosowania przez wirusa techniki stealth odczyty najlepiej, byłoby wykonywać przez porty.

12.7. Blokowanie programów używających trybu krokowego

Niektóre monitory antywirusowe posiadają wbudowane mechanizmy blokowania wirusów, które używają trybu krokowego do znalezienia oryginalnych wejść do przerwań.

Zainstalowany monitor przejmuje najbardziej narażone na tracing przerwania (13h, 21h, 2Fh) i podczas ich wywoływania ustawia procedurę obsługi przerwania INT 0lh (trybu krokowego) na pustą procedurę, zakończoną rozkazem IRET, a po wywołaniu oryginalnej procedury chronionego przez siebie przerwania przywraca starą procedurę przerwania l. Dzięki temu wirus próbujący znaleźć oryginalną procedurę przerwania znajdzie adres będący częścią monitora antywirusowego. W efekcie wszystkie wykonywane przez wirusa czynności będą przechodzić przez monitor, który nie pozwoli na niebezpieczne działania.

Powyższą technikę demonstruje poniższy program.

;

Czesc ksiazki : 'Nowoczesne techniki wirusowe i antywirusowe' ;

;

; ANTYTRAC v1.0, Autor : Adam Blaszczyk 1997 ;

;

; Program nie pozwala przejsc w trybie krokowym ;

; przez przerwania 13h i 21h. ;

; W efekcie wirusy uzywajace tracingu do odnalezienia ;

; oryginalnych procedur obslugi tych przerwan nie znajda ;

; ostatniego elementu lancucha, a tylko element posredni. ;

;

; Kompilacja :  ;

; TASM ANTYTRAC.ASM ;

; TLINK /t ANTYTRAC.OBJ ;

;

NUL = 00h ;

LF = 0Ah ; - stale potrzebne do deklaracji

CR = 0Dh ; / lancuchow napisowych

ANTYTRAC SEGMENT ; segment kodu i danych

ORG 100h ; program jest typu COM

ASSUME CS:ANTYTRAC, DS:ANTYTRAC, ES:ANTYTRAC, SS:ANTYTRAC

DlugoscKoduTSR = (offset KoniecKoduTSR-offset PoczatekKoduTSR+15)/16+10h

; oblicza, ile pamieci zajmie TSR

PoczatekKoduTSR:

Start:  ; tu zaczyna sie program

jmp Poczatek ; skocz i zainstaluj lub odinstaluj program

NoweInt21h:

cmp ax,3521h ; czy to funkcja 3521h ?

jne Nie3521 ; NIE - skocz na koniec obslugi

cmp bp,0BACAh ; czy to ponownie uruchomiony program ?

; wywolal te funkcje ?

jne Nie3521 ; NIE - skocz na koniec obslugi

; TAK - odinstaluj wirusa

push es ds ; zachowaj zmieniane rejestry

lds dx,dword ptr cs:[StareInt21] ; pobierz stary adres INT 21h

mov ax,2521h ; funkcja DOS - ustaw nowe przerwanie

int 21h ; wywolaj funkcje (rekurencyjnie)

lds dx,dword ptr cs:[StareInt13] ; pobierz stary adres INT 13h

mov ax,2513h ; funkcja DOS - ustaw nowe przerwanie

int 21h ; wywolaj funkcje

push cs

pop es ; ES=zwalniany segment

mov ah,49h ; funkcja DOS - zwolnij blok pamieci

int 21h ; wywolaj funkcje

pop ds es ; przywroc zmieniane rejestry

mov ax,bp ; przekaz informacje do wywolujacego

; programu

iret ; powrot z przerwania

Nie3521:

Call Wylacz_TF ; jezeli bit TF=1, ustaw TF=0

db 0EAh ; czesc rozkazu JMP FAR

StareInt21 dd ? ; koncowka rozkazu JMP FAR

NoweInt13h:

Call Wylacz_TF ; jezeli TF=1, ustaw TF=0

db 0EAh ; czesc rozkazu JMP FAR

StareInt13 dd ? ; koncowka rozkazu JMP FAR

Wylacz_TF:

cli ; zablokuj przerwania

push ax bx ds ; zachowaj zmieniane rejestry

push ss ; za pomoca tej sztuczki zwykle

pop ss ; mozna pobrac 'prawdziwy' obraz

pushf ; / rejestru znacznikow

pop ax ; /

test ah,1 ; czy TF ustawiony ?

jz TF_NieUstawiony ; NIE - nie trzeba nic robic

mov ax,0123h ;

push ax ; ss:[sp]:=0123

pop ax ; ax:=ss:[sp]:=0123

dec sp ; sp=sp-2-wskazuje na wartosc,

dec sp ; ktora byla sciagana ze stosu

pop ax ; ax:=ss:[sp]:=0123 jezeli TF=0

cmp ax,0123h

jz TF_NieUstawiony ; NIE - nie trzeba nic robic

xor ax,ax ; DS wskazuje na tablice przerwan

mov ds,ax ; /

lds bx,ds:[01h*4] ; DS:BX wskazuje na adres obslugi

; przerwania krokowego INT 1

mov al,0CFh ; kod 0CFh oznacza IRET

xchg al,ds:[bx] ; wymien pierwszy bajt w procedurze

; obslugi INT 1 - teraz jest tylko

; IRET

push ax ; zachowaj pierwszy bajt procedury

pushf ;

pop ax ; zeruj TF

and ah,0FEh ; -

push ax ; /

popf ; /

pop ax ; przywroc pierwszy bajt

mov ds:[bx],al ; i zapisz go z powrotem

TF_NieUstawiony:

pop ds bx ax ; przywroc zmieniane rejestry

ret ; powrot z procedury

KoniecKoduTSR:

Poczatek:

mov es,ds:[2Ch] ; ES=blok otoczenia programu

mov ah,49h ; funkcja DOS - zwolnij blok pamieci

int 21h ; wywolaj funkcje

lea si,TeCopyRight ; pokaz info o programie

Call Print ; /

mov bp,0BACAh ; wez stare INT 21h i jednoczesnie

mov ax,3521h ; - odinstaluj program, jezeli juz

int 21h ; / byl wczesniej zainstalowany

cmp ax,0BACAh ; czy zostal odinstalowany ?

je Deinstal ; TAK - wyswietl komunikat i koncz

mov word ptr [StareInt21],bx ; zachowaj stare INT 21

mov word ptr [StareInt21+2],es ; /

mov ax,3513h ; funkcja DOS - wez stare INT 13h

int 21h ; wywolaj funkcje

mov word ptr [StareInt13],bx ; zachowaj stare INT 13

mov word ptr [StareInt13+2],es ; /

lea si,TeZainstalowany ; pokaz info o programie

Call Print ; /

lea dx,NoweInt21h ; DS:DX wskazuje na nowa procedure

mov ax,2521h ; funkcja DOS - ustaw nowa INT 21

int 21h ; wywolaj funkcje

lea dx,NoweInt13h ; DS:DX wskazuje na nowa procedure

mov ax,2513h ; funkcja DOS - ustaw nowa INT 13

int 21h ; wywolaj funkcje

mov dx,DlugoscKoduTSR ; ile kodu zostanie jako TSR

mov ah,31h ; funkcja DOS - koncz i zostaw TSR

int 21h ; wywolaj funkcje

Deinstal:

lea si,TeOdinstalowany ; pokaz info o deinstalacji

Call Print ; /

mov ax, 4C00h ; funkcja DOS - koncz program

int 21h ; wywolaj funkcje

Print proc near ; procedura wyswietla tekst ASCIIZ

; spod adresu CS:SI

push ax ; zachowaj zmieniane rejestry

push si ; /

GetNextChar:

lods byte ptr cs:[si] ; wez kolejny znak

or al,al ; czy znak jest zerem ?

jz PrintExit ; tak=koniec napisu; wyjdz z petli

Call PrintChar ; nie=wyswietl znak w AL

;

jmp short GetNextChar ; i wez nastepny znak

PrintExit:

pop si ; przywroc zmieniane rejestry

pop ax ; /

ret ; powrot z procedury

Print endp

PrintChar proc near ; procedura wyswietla znak w AL

push ax ; zachowaj zmieniany rejestr

mov ah,0Eh ; funkcja BIOS

int 10h ; wyswietl znak w AL

pop ax ; przywroc zmieniany rejestr

ret ; powrot z procedury

PrintChar endp

TeCopyRight db CR,LF,'ANTYTRAC v1.0, Autor : Adam Blaszczyk 1997'

TeCRLF db CR,LF,NUL

TeZainstalowany db CR,LF,' _ ANTYTRAC zainstalowany!',NUL

TeOdinstalowany db CR,LF,' _ ANTYTRAC odinstalowany!',NUL

ANTYTRAC ENDS ; koniec segmentu kodu i danych

END Start ; koniec programu, pierwsza instrukcja

; pod etykieta Start

12.8. Pobieranie wielkości pamięci operacyjnej

Ze względu na to, iż większość wirusów rezydentnych instaluje się w pamięci poprzez modyfikację nagłówków pamięci MCB, możliwe jest wykrycie większości takich intruzów poprzez obliczenie wielkości dostępnej pamięci na różne sposoby i następnie na porównaniu, czy uzyskane wartości zgadzają się ze sobą. Poniższy program pobiera na cztery sposoby wielkość pamięci operacyjnej poniżej 640K i następnie rozmiar ten wyświetla na ekranie.

;

Czesc ksiazki : 'Nowoczesne techniki wirusowe i antywirusowe' ;

;

MEM640 v1.0, Autor : Adam Blaszczyk 1997 ;

;

; Programik pobiera i wyswietla rozmiar pamieci ponizej 640kb ;

; Wielkosc pamieci jest pobierana kilkoma metodami ;

; Przy jego uzyciu mozna wykryc w pamieci obecnosc wirusa ;

; rezydetnego (gdy odczytane dlugosci pamieci beda rozne) ;

;

PROG SEGMENT

ORG 100h

ASSUME CS:PROG, DS:PROG

NUL = 00h ;

LF = 0Ah ; - stale znakow

CR = 0Dh ; /

Start:

lea si,TeCopyRight ; SI=ofset do info o programie

Call DrukLn ; wyswietl info o programie

Call Pokaz_CMOS ; ile zapisane w CMOS

call Pokaz_ZmiennaBIOS ; ile w komorce 0000:0413

call Pokaz_Int12 ; ile zwraca INT 12

Call Pokaz_MCB ; ile z sumy MCB

mov ax,4C00h ; funkcja DOS - koncz program

int 21h ; wywolaj funkcje

Pokaz_CMOS:

push ax dx si ; zachowaj zmieniane rejestry

lea si,TeCMOS ; wyswietl info skad czytany

Call Druk ; / rozmiar pamieci

mov al,16h ; wez z CMOS starsza czesc

Call WezCMOS ; / rozmiaru pamieci

mov ah,al ; i przepisz do AH

mov al,15h ; wez z CMOS starsza czesc

Call WezCMOS ; / rozmiaru pamieci

; AX= rozmiar w CMOS w kilobajtach

mov dx,1024 ; oblicz ile bajtow

mul dx ; /

Call DrukDec32 ; wyswietl ile bajtow

pop si dx ax ; przywroc zmieniane rejestry

ret ; powrot

WezCMOS:

out 70h,al ; zapisz do portu CMOS,

; ktora komorke czytac

jmp $+2 ; czekaj

in al,71h ; czytaj z CMOS

ret ; powrot

Pokaz_Int12:

push ax dx si ; zachowaj zmieniane rejestry

lea si,TeInt12 ; wyswietl info skad czytany

Call Druk ; / rozmiar pamieci

int 12h ; przerwanie BIOS - dostepna pamiec

; AX=rozmiar pamieci w kilobajtach

mov dx,1024 ; oblicz ile bajtow

mul dx ; /

call DrukDec32 ; wyswietl ile bajtow

pop dx ax si ; przywroc zmieniane rejestry

ret ; powrot

Pokaz_ZmiennaBIOS:

push es ax dx si ; zachowaj zmieniane rejestry

lea si,TeZmiennaBIOS ; wyswietl info skad czytany

Call Druk ; / rozmiar pamieci

xor ax,ax ; czytaj zmienna BIOS 0000:0413

mov es,ax ; ES=0000

mov ax,es:[413h] ; AX=0000:0413= rozmiar pamieci

; w kilobajtach

mov dx,1024 ; oblicz ile bajtow

mul dx ; /

Call DrukDec32 ; wyswietl ile bajtow

pop si dx ax es ; przywroc zmieniane rejestry

ret ; powrot

Pokaz_MCB:

push es ax bx cx dx ; zachowaj zmieniane rejestry

lea si,TeMCB ; wyswietl info skad czytany

Call Druk ; / rozmiar pamieci

mov ax,5802h ; funkcja DOS - czy UMB dolaczone ?

int 21h ; wywolaj funkcje

push ax ; zachowaj informacje na pozniej

mov ax,5803h ; funkcja DOS - dolacz/odlacz bloki UMB

mov bx,1 ; sprobuj dolaczyc bloki UMB

int 21h ; wywolaj funkcje

mov ax,5802h ; funkcja DOS - czy UMB dolaczone ?

int 21h ; wywolaj funkcje

xor cx,cx ; CX=0 - UMB nieobecne w systemie

or al,al ; 01=jezeli UMB sa dolaczone

jz UMB_NieDolaczone ; 00=jezeli UMB nie sa dolaczone

inc cx ; CX=1 - UMB obecne w systemie

mov ax,5803h ; funkcja DOS - dolacz/odlacz bloki UMB

xor bx,bx ; odlacz bloki UMB

int 21h ; wywolaj funkcje

UMB_NieDolaczone:

mov ah,52h ; funkcja DOS - wez adres listy list LL

int 21h ; wywolaj funkcje

mov ax,es:[bx-2] ; wez adres pierwszego bloku MCB

NastepnyMCB: ; kolejne bloki MCB

cmp ax,0A000h ; czy >640kB ?

jae Tylko640 ; TAK - pomin

mov es,ax ; ES=MCB

stc ; +1 w dodawaniu ponizej

adc ax,word ptr es:[3] ; dodaj rozmiar bloku MCB+1

; AX=nastepny blok MCB

cmp byte ptr es:[0],'Z' ; czy to ostatni blok MCB ?

jne NastepnyMCB ; NIE - dodaj koleny blok

; TAK - wyswietl sume

Tylko640:

add ax,cx ; dodaj ewentualny blok MCB

; opisujacy bloki MCB w pamieci UMB

; AX=pamiec w paragrafach

mov bx,16 ;

mul bx ; / oblicz ile bajtow

call DrukDec32 ; wyswietl ile bajtow

pop bx ; przywroc info o UMB

mov bh,0 ; BX=BL

mov ax,5803h ; funkcja DOS - dolacz/odlacz bloki UMB

int 21h ; wywolaj funkcje

pop dx cx bx ax es ; przywroc zmieniane rejestry

ret ; powrot

DrukDec32: ; wyswietl liczbe w DX:AX

push ax bx dx si ; zachowaj zmieniane rejestry

mov si,offset Hex2DecBufor+10 ; ustaw na koniec bufora, bo zapis od konca

mov byte ptr [si],0 ; utworz ASCIIZ dodaj zero na koncu

DzielPrzez10:

mov bx,10 ; dziel DX:AX przez BX

Call Dziel32 ; w BX reszta z dzielenia

add bl,'0' ; dodaj ASCII '0'

dec si ; zmniejsz index w tablicy

mov byte ptr ds:[si],bl ; zapisz cyfre

or dx,dx ;

jnz DzielPrzez10 ;

or ax,ax ;

jnz DzielPrzez10 ; --- czy liczba jest juz rowna 0

; NIE - dziel dalej

call DrukLn ; TAK - wyswietl bufor

pop si dx bx ax ; przywroc zmieniane rejestry

ret ; powrot

Dziel32: ; dziel (DX:AX)/BX

push bp ; zachowaj BP

push ax ; zachowac mniejsza czesc liczby 32 bitowej

mov ax,dx ; przenies b. znacz. czesc do mniej. znacz.

xor dx,dx ; i wyzeruj DX, DX:AX = > 0:DX

div bx ; podziel (0:DX)/BX

mov bp,ax ; calosc z dzielenia to wieksza czesc wyniku

pop ax ; przywroc do AX mniej znaczaca liczbe z poczatku

div bx ; DX jest reszta z dzielenia b. znacz. czesci przez BX

mov bx,dx ; w BX reszta z dzielenia

mov dx,bp ; DX:AX=liczba podzielona przez BX,

; a w BX reszta z dzielenia

pop bp ; przywroc zmieniany rejestr

ret ; powrot

DrukLn:

push si ; zachowaj zmieniany rejestr

call Druk ; wyswietl tekst z CS:SI

lea si,TeCRLF ; i przejdz do nastepnej linii

Call Druk ; /

pop si ; przywroc zmieniany rejestr

ret ; powrot

Druk:

push ax si ; zachowaj zmieniane rejestry

DrukPetla:

lods byte ptr cs:[si] ; wez kolejny znak tekstu

or al,al ; czy NUL ?

jz DrukPowrot ; TAK - koniec tekstu

mov ah,0Eh ; funkcja BIOS - wyswietl znak

int 10h ; wywolaj funkcje

jmp short DrukPetla ; pobierz kolejny znak tekstu

DrukPowrot:

pop si ax ; przywroc zmieniane rejestry

ret ; powrot

TeCopyRight db CR,LF,'MEM640 v1.0, Autor : Adam Blaszczyk 1997'

db CR,LF

db CR,LF,'Wielkosc pamieci w bajtach :',NUL

TeCMOS db ' _ CMOS : ',NUL

TeInt12 db ' _ INT 12 : ',NUL

TeZmiennaBIOS db ' _ Zmienna BIOS 0000:0412 : ',NUL

TeMCB db ' _ Suma blokow MCB (<640kB) : ',NUL

TeCRLF db CR,LF,NUL

Hex2DecBufor db 11 dup(?) ; bufor na liczbe dzisietna

PROG ENDS

END Start



Politica de confidentialitate | Termeni si conditii de utilizare



DISTRIBUIE DOCUMENTUL

Comentarii


Vizualizari: 617
Importanta: rank

Comenteaza documentul:

Te rugam sa te autentifici sau sa iti faci cont pentru a putea comenta

Creaza cont nou

Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved