CATEGORII DOCUMENTE |
Bulgara | Ceha slovaca | Croata | Engleza | Estona | Finlandeza | Franceza |
Germana | Italiana | Letona | Lituaniana | Maghiara | Olandeza | Poloneza |
Sarba | Slovena | Spaniola | Suedeza | Turca | Ucraineana |
DOCUMENTE SIMILARE |
|
Przejmowanie przerwań i znajdowanie czystych wejść do systemu
6.1. Najczęściej przejmowane i wykorzystywane przerwania
Wirusy najczęściej wykorzystują i/lub przejmują następujące przerwania:
> 01h - Przerwanie trybu krokowego procesora, wywoływane wewnętrznie, gdy w rejestrze znaczników FLAGS jest ustawiony bit TF. Przerwanie Olh jest używane przez wirusy do poszukiwania w łańcuchu procedur obsługi przerwania jego ostatniego elementu, będącego przeważnie częścią DOS-a lub BIOS-a. W czasie wykonywania wyżej wymienionej operacji możliwe jest także przejęcie obsługi przerwania poprzez włączenie się w istniejący łańcuch obsługi przerwania, dzięki czemu nie trzeba modyfikować tablicy przerwań. Kontrola procedury obsługi tego przerwania pozwala wykryć uruchomiony debugger.
> 03h - Pułapka programowa (ang. breakpoint}, ze względu na 1-bajtową instrukcję (kod 0CCh) stosowana przez debuggery;
powyższa właściwość powoduje, iż instrukcję tę stosują bardzo krótkie wirusy do wywoływania pierwotnej procedury obsługi przejętego przez nie przerwania. Podobnie jak w przypadku przerwania numer 0lh, kontrolując INT 03h można wykryć włączony debugger.
> 08h - Przerwanie sprzętowe IRQ 0 - standardowo zgłaszane 18 razy na sekundę przez układ zegara 8253/8254 (częstotliwość generowania tego przerwania można zmienić programowo). Wewnątrz procedury jego obsługi znajduje się rozkaz wywołania przerwania 1Ch. Najczęściej używane jest ono do realizacji efektów specjalnych, rzadziej do autoweryfikacji wirusa.
> 09h - Przerwanie sprzętowe IRQ l, wywoływane po naciśnięciu lub puszczeniu klawisza na klawiaturze. Odczytany z portu 60h klawisz jest dekodowany przez funkcję (4F/15), a następnie umieszczany w buforze klawiatury, skąd dostępny jest później dla funkcji przerwania 16h. Podobnie Jak IRQ O, przerwanie 09h używane jest zwykle do efektów specjalnych i czasem do autoweryfikacji (na przykład kod wirusa jest sprawdzany przy każdym naciśnięciu lub puszczeniu klawisza).
> 10h - Przerwanie programowe BIOS obsługujące funkcje ekranu;
używane do efektów specjalnych lub w celu informowania innych kopii wirusa o obecności w pamięci.
> 12h - Przerwanie programowe BIOS zwracające po wywołaniu wielkość pamięci operacyjnej podaną w kilobajtach. Zwracana wartość jest odczytywana ze zmiennej systemowej BIOS, znajdującej się pod adresem 0000:0413. Przerwanie to wykorzystują głównie wirusy tablicy partycji i BOOT-sektorów, gdy zmniejszają ilość pamięci dostępnej dla systemu DOS. Aby tego dokonać, nie muszą jednak przejmować przerwania, a tylko zmodyfikować wyżej wymienioną zmienną BIOS. Czasem przerwanie 12h przejmowane jest w celu informowania innych kopii wirusa o obecności w systemie.
> 13h - Przerwanie programowe BIOS odpowiedzialne za obsługę dysków na poziomie sektorów. Obsługując dyskietki wywołuje przerwanie 40h. Jest ono używane najczęściej podczas infekcji
przez wirusy atakujące Główny Rekord Ładujący (MBR), BOOT-sektory i JAP. Jego przejęcie umożliwia zastosowanie techniki stealth dla sektorów, a także informowanie innych kopii wirusa o obecności w systemie.
> 14h - Przerwanie programowe BIOS odpowiedzialne za obsługę łączy szeregowych. Przechwytywane (choć rzadko) dla efektów specjalnych, polegających na przekłamywaniu odczytów7 i zapisów złącza.
> 15h - Przerwanie programowe BIOS odpowiedzialne za dodatkowe funkcje systemowe. Może być przejmowane dla efektów specjalnych, polegających na zmianie obsługi funkcji 4Fh. Powyższa funkcja jest wywoływana przez przerwanie sprzętowe IRQ l (09h) i odpowiada za dekodowanie klawiszy do postaci widzianej później przez przerwanie programowe int 16h. Godna uwagi jest także funkcja (9000/15), wywoływana przez procedurę obsługi przerwania sprzętowego IRQ 14 (76h), której przejęcie umożliwia zastosowanie techniki hardware-level stealth.
> 16h - Przerwanie programowe BIOS odpowiedzialne za obsługę klawiatury. Przejmowane najczęściej dla efektów specjalnych lub w celu informowania innych kopii wirusa o obecności w pamięci.
> 17h - Przerwanie programowe BIOS obsługujące drukarki. Przejmowane (choć rzadko) dla efektów specjalnych, polegających np. na fałszowaniu drukowanych znaków.
> 1Ch - Przerwanie wywoływane przez przerwanie sprzętowe IRQ 0 (08h), najczęściej przejmowane do celów efektów specjalnych (choć w tym wypadku lepiej przejąć obsługę przerwania IRQ 0).
> 21h - Przerwanie programowe DOS odpowiedzialne m.in. za obsługę dysków logicznych na poziomie plików, a także pamięci operacyjnej, czyli newralgicznych części systemu, stąd też jest ono najczęściej przejmowanym przez wirusy przerwaniem. Umożliwia infekcję plików przy ich otwieraniu, zamykaniu, czytaniu, zmianie nazwy, uruchamianiu itd. oraz pozwala na ukrywanie się w systemie. Ze względu na to, iż jest potrzebne wirusom do mnożenia się, nie wykorzystywane przez system numery funkcji często służą innym kopiom wirusa do sprawdzania jego
obecności w systemie (nie musi on już przejmować innego przerwania, gdyż wyżej wymieniona operacja wykonywana jest niejako przy okazji).
> 24h - Przerwanie programowe DOS obsługujące błędy krytyczne systemu. W wypadku wystąpienia błędu wywołuje ono standardowo tzw. dialog ARIF (skrót od ang. Abort Retry Ignore Fail), pozwalający użytkownikowi zadecydować, jaką podjąć operację. Przerwanie to wirusy przejmują na czas infekcji, aby w razie wystąpienia jakiegoś błędu wirus mógł sam zadecydować, jaką akcję chce podjąć. Nowa obsługa przerwania najczęściej zawiera dwie instrukcje nakazujące systemowi DOS sygnalizować błąd programowi wywołującemu (czyli wirusowi). Wyglądają one następująco:
Typowa procedura obs│ugi przerwania int 24h u┐ywana podczas infekcji
MOV
IRET ; powr≤t 2 obs│ugi przerwania
> 25h - Przerwanie programowe DOS odpowiedzialne za odczyt sektorów z dysków logicznych, czasem używane do ukrywania się w systemie, ale głównie do łatwego odczytywania BOOT-se-ktorów.
> 26h - Przerwanie programowe DOS odpowiedzialne za zapis sektorów na dyskach logicznych. Najczęściej używane jest do infekcji BOOT-sektorów. Zwykle wykorzystuj ą je konie trojańskie do destrukcji.
> 27h - Przerwanie programowe DOS. Umożliwia zakończenie programu z pozostawieniem kodu w pamięci. Używają go niektóre, zwłaszcza stare, programy TSR, nowsze korzystają z funkcji (31/21). Wykorzystując działanie tego przerwania lub funkcji (31/21) można napisać prostego wirusa rezydentnego.
> 28h - Przerwanie programowe DOS pozwalające na wykonywanie pewnych operacji w tle, co jest wykorzystywane m. in. przez program PRINT. Może być użyteczne do infekowania plików, gdy DOS nie jest zajęty żadnym zadaniem, tak jak robi to np. wirus DOS-IDLE.
> 2Fh - Przerwanie multipleksowane systemu. Ze względu na różnorodność wykonywanych funkcji umożliwia m. in. znajdowanie oryginalnej procedury przerwania 13h (13h/2F), informowanie innych kopii wirusa o obecności w systemie oraz infekcję plików przy ich zamykaniu. To ostatnie możliwe jest dzięki zastosowaniu funkcji (1216/1220/2F), operujących na systemowych tablicach SFT (ang. System File Table), w których zawarte są wszystkie parametry wskazywanego przez uchwyt pliku.
> 30h/31h - W tablicy przerwań, w miejscu, gdzie powinny być adresy obsługi tych przerwań znajduje się rozkaz dalekiego skoku do DOS w postaci 0EA 00 00 SS SS, gdzie OO OO to ofset, a SS SS to segment (po starcie systemu jest to segment kodu systemu DOS, ale może być podmieniony przez program antywirusowy). Adres wskazywany przez rozkaz skoku może być wykorzystywany do wywoływania funkcji DOS według przestarzałej konwencji CP/M, a także do zlokalizowania w segmencie kodu DOS adresu obsługi przerwania 21h, co umożliwia bezpieczne, omijające większość monitorów antywirusowych, wywoływanie funkcji DOS (metodę tę stosuje m.in. wirus DIR-2).
> 40h - Przerwanie programowe BIOS, które obsługuje dyski elastyczne. W większości BIOS-ów adres tego przerwania jest oryginalnym adresem przerwania 13h podczas inicjacji systemu. Podczas startu systemu BIOS przekierowywuje przerwanie 13h na 40h, o ile wykryje dysk twardy. Rzadko przejmowane; umożliwia dostęp do dyskietek z pominięciem przerwania 13h.
> 76h - Przerwanie sprzętowe IRQ 14, generowane przez sterownik dysku twardego przy wszelkich operacjach dyskowych. Obsługa przerwania polega na wykonaniu odczytu z portu 1F7h (rejestr stanu IDE) i wywołaniu funkcji (9000/15). Przejęcie jego lub funkcji (9000/15) umożliwia zastosowanie techniki hardware-level stealth do ukrywania się w systemie.
Jak widać, jest to znakomita większość wszystkich wykorzystywanych przez programy przerwań. Czasem, w celu zminimalizowania rozmiarów, wirus przejmuje dodatkowo jakieś nie używane przez system przerwanie (najczęściej powyżej numeru 60h), aby przy jego pomocy wywoływać pierwotny program obsługi jakiegoś przejętego przez siebie przerwania. Korzysta z tego, że maszynowy rozkaz wy-
wołania przerwania (INT ??) zawiera tylko 2 bajty (o kodach OCDh/??, gdzie ?? to numer przerwania), gdy tymczasem rozkaz wywołania pierwotnego programu obsługi za pomocą rozkazu wywołania procedury zajmowałby od 3 (wywołanie pośredniej, bliskiej procedury) do 6 bajtów (wywołanie dalekiej, bezpośredniej procedury). Przejęcie jakiegoś przerwania programowego może być także wykorzystywane do sprawdzania, czy wirus został już wcześniej zainstalowany w pamięci, co pozwala mu uniknąć powtórnej, niepotrzebnej instalacji. Sekwencja wykrywająca, czy wirus jest już zainstalowany, ma najczęściej postać:
MOV AX.HASśO ; najczΩ£ciej w AX podaje siΩ jak╣£ nie typow╣ funkcjΩ
INT xx ; xx - numer przerwania (najczΩ£ciej 21h)
CMP REJ,ODPOWIEDÅ ; czy wirus ju┐ zainstalowany (rej - najczΩ£ciej AX)
JE Ju┐Zainstalowany ; skok, gdy zainstalowany wirus zwr≤ci│ odpowied
; zainstaluj siΩ
Ju┐Zainstalowany: ; powr≤µ do nosiciela
Wiedza o najczęściej przejmowanych przerwaniach pozwala często na ręczne przejście przez łańcuch obsługi przerwania przy użyciu de-buggera i sprawdzenie po drodze, czy nie ma gdzieś kodu budzącego podejrzenia, prawdopodobnie należącego do wirusa. Przy takim sprawdzaniu należy pamiętać o kilku niebezpieczeństwach związanych z używaniem debuggera w systemie kontrolowanym przez wirusa. Wirus może kontrolować funkcję (4B01/21), służącą debugge-rom do ładowania programów. Jeżeli jest ona wywoływana, wirus może się deinstalować z pamięci lub podjąć jakieś inne działanie, maskujące lub destrukcyjne. Podobne niebezpieczeństwo grozi ciekawskiemu użytkownikowi ze strony niektórych, najczęściej destrukcyjnych wirusów, kontrolujących stan przerwania INT 01h i INT 03h, a te, jak wiadomo, używane są najczęściej przez programy uruchomieniowe. Zwykle po wykryciu, iż adres procedury obsługi któregoś z tych przerwań nie wskazuje na rozkaz IRET (czyli na pustą procedurę obsługi przerwania), wirus bądź blokuje komputer, bądź brutalnie niszczy dane na dysku twardym. Jeszcze inne niebezpieczeństwo
może grozić użytkownikowi ze strony wirusów, które potrafią sprawdzać poprawność swego kodu. Procedura autoweryfikacji może być wywoływana przez każde z niewinnych przerwań programowych, używanych powszechnie w oprogramowaniu (np.: 10h, 16h) lub też może być podczepiona pod któreś z przerwań sprzętowych. W przypadku wykrycia jakichś zmian (np, zły wynik obliczanej na bieżąco sumy korekcyjnej) wirus może natychmiast podjąć niemile dla użytkownika działanie odwetowe.
Na koniec warto jeszcze wspomnieć, iż zamiast przerwań niektóre wirusy rezydentne przejmują obsługę sterowników urządzeń blokowych, zajmujących się operacjami na urządzeniach masowych, takich jak dysk twardy czy dyskietka, w sposób analogiczny do programów umieszczanych w plikach SYS. Pozwala im to monitorować odwołania do dysków logicznych, zainstalowanych w systemie na poziomie pośrednim między systemem DOS i BIOS (jest to potrzebne np. przy infekcji polegającej na podmianie pierwszej JAP pliku). Tak przejęte odwołanie do systemu będzie dość trudne do wykrycia poprzez ręczne analizowanie kodu jakiegoś przerwania krok po kroku.
6.2. Wykorzystanie funkcji DOS
Najprościej przejąć obsługę przerwania używając dwóch przeznaczonych do tego celu funkcji DOS, tzn. (25/35/21) za pomocą poniższej sekwencji w asemblerze:
; Przejmowanie przerwa± za pomoce DOS-a
MOV AL, NUMER ; podaj w
MOV AH, 35h ; w AH numer funkcji, we adres starej procedury
; obs│ugi przerwania
INT 21h ; wywo│aj funkcjΩ DOS po wywo│aniu funkcji
MOV [StarySEG],ES ; w ES:BX pobrany adres poprzedniej procedury
MOV [StaryOFS],BX ; obs│ugi, kt≤ry najczΩ£ciej zapamiΩtuje siΩ
MOV AH, 25h ; w AH numer funkcji, ustaw now╣ procedurΩ obs│ugi
; przerwania
MOV AL,NUMER ; w
MOV DS, SEG Nowa ; DS:DX zawiera adres do nowej procedury
MOV DX, OFFSET Nowa ; obs│ugi przerwania
INT 21h ; wywo│aj funkcjΩ DOS
Powyższy sposób przejmowania przerwań, zalecany przez twórców systemu DOS, ze względu na możliwość monitorowania funkcji (25/35/21) przez program antywirusowy, stosują najczęściej prymitywne wirusy. Bardziej wyrafinowane, używają metod trochę innych, omówionych poniżej.
6.3. Bezpośrednie zmiany w tablicy wektorów przerwań
Bezpieczniejszym (ze względu na programy antywirusowe) sposobem na przejęcie przerwania jest bezpośrednia manipulacja w tablicy wektorów przerwań, przy użyciu poniższej sekwencji w asemblerze, wykonującej w przybliżeniu to samo, co sekwencja z poprzedniego punktu:
: Przejmowanie przerwa± bezpo£rednio w tablicy przerwa±
MOV BL, NUMER ; w BL numer zmienianego przerwania
XOR BH,BH ; BX=BL
SHL BX,l ; pomn≤┐ je przez 4 (2 razy przesu± w lewo)
SHL BX,l ; jeszcze raz przesu± w lewo
XOR AX,AX ; zeruj rejestr AX
MOV DS,AX ; i z jego pomoc╣ zeruj rejestr segmentu DS
; DS:BX wskazuje na pozycjΩ w tablicy przerwa±,
; gdzie zapisany jest adres obs│ugi przerwania
LDS DX,DS:[BX] ; pobierz segment i offset przerwania (do
; zapamiΩtania)
MOV [StarySEG],DS ; zachowaj segment
MOV [StaryOFS],DX ; zachowaj offset
MOV DS,AX ; ponownie DS=0
CLI ; bezpiecznie zmieniaµ adres obs│ugi przerwania
; przy wy│╣czonych przerwaniach
MOV DS:[BXJ,OFFSET NOWA ; bezpo£rednie warto£ci wskazujΩ
; na adres nowej
MOV DS:[BX+2], SEG NOWE ; procedury obs│ugi przerwania
STI ; teraz mo┐na ju┐ w│╣czyµ przerwania
Oczywiście, w powyższej sekwencji można pominąć rejestr BX i podać offset w postaci absolutnej (np, jako 21h*4), jednak użycie rejestru umożliwia przejmowanie więcej niż jednego przerwania za pomocą tej samej procedury (należy zmieniać tylko wartość BL).
6.4. Włączanie się do istniejącego łańcucha obsługi przerwania i znajdowanie czystych wejść do systemu (ang. tunnelling
Dowolna modyfikacja w tablicy przerwań jest łatwa do wykrycia przez najprymitywniejszy nawet program antywirusowy, stąd też twórcy wirusów poszukiwali innej metody przejmowania przerwań, dzięki której nie trzeba modyfikować tablicy przerwań. Opracowano szereg metod polegających na włączaniu się do istniejącego łańcucha procedur obsługi przerwania, zwanych ogólnie tunelingiem.
Zainstalowany rezydentnie w pamięci wirus musi mieć możliwość wywoływania pierwotnej procedury przejętego przez siebie przerwania (np. podczas infekcji potrzebne są funkcje systemu obsługujące działania na plikach). Wywoływanie aktualnej (tzn. wskazywanej przez tablicę przerwań) procedury obsługującej dane przerwanie lub nawet tej, która została zapamiętana podczas instalacji wirusa w pamięci, grozi szybkim wykryciem przez monitor antywirusowy Najlepiej, gdy wywoływana przez wirusa procedura jest ostatnim elementem w łańcuchu procedur obsługi przerwania, czyli jest to po prostu oryginalna procedura zawarta w BIOS-ie lub DOS-ie.
6.4.1. Korzystanie ze stałych adresów w systemie (przerwania 21h i 2Fh)
Ta metoda tunelingu jest możliwa tylko w wersjach DOS powyżej 5.00. Służy ona do przechwytywania obsługi przerwania 21h i ewentualnie 2Fh (przy okazji znajdowany jest oryginalny adres procedury obsługi tego przerwania, ulokowanej w kodzie systemu DOS). Wykorzystuje ona fakt, iż system DOS posiada w swym pierwszym bloku MCB (oznaczonym jako systemowy) standardową sekwencję kodu (taką samą dla obu przerwań 2 h i 2Fh), która została przedstawiona poniżej.
Sekwencja kodu występująca w DOS od 5.0 wzwyż
DOS używa HMA |
DOS nie używa HMA |
|||
Adres |
Kod |
Znaczenie |
Kod |
Znaczenie |
SEG:OFS |
NOP NOP |
EB 03 |
JMP $+3 |
|
SEG:OFS+2 |
E8 xxxx |
CALL [IP+xxxx] |
E8 xxxx |
CALL [IP+xxxx] |
SEG:OFS+5 |
2E FF 2E yyyy |
JMP FAR CS:[yyyy] |
2E FF 2E |
JMP FAR CS:[yyyy] |
Dla przerwania 21h powyższa sekwencja kodu występuje pod adresem SEG:OFS, gdzie OFS jest równy 109Eh (w wersji DOS od 5.00 do 6,22) lub 0FB2h w wersjach powyżej 6.22 (np. DOS 7.0, występujący z systemem Windows 95).
W przypadku przerwania 2Fh OFS jest równy: 10C6h (dla DOS 5.00 - 6.22) i 0FDAh (dla wersji 7.00).
Wartość SEG jest wartością zwracaną przez funkcję 52h w rejestrze ES. Na podstawie powyższych danych łatwo odczytać adres pierwotnego adresu procedury int 21h, korzystając z następującej sekwencji:
MOV AH,30H ; funkcja - we wersjΩ systemu
INT 21h ; wywo│aj funkcjΩ
XCHG AL,AH ; zabieg kosmetyczny - aby p≤niejsze
; por≤wnanie by│o bardziej przejrzyste
MOV BX,109EH ; offset dla wersji 5.00 - 6.22
CMP AX,0500h ; czy wersja
JB NIEDZIAśA ; je£li tak, to tunneling nie dzia│a
CMP AX,0622h ; czy wersja wiΩksza od 6.22 ?
JB Wer5_6_22
MOV BX,OFB2h ; nowsze wersje DOS - inny offset
Wer5_6_22:
PUSH BX ; zachowaj offset na stosie
MOV AH,52h ; funkcja - podaj adres do LL
INT 21h ; wywo│aj funkcjΩ
POP BX ; teraz ES:BX wskazuje na sekwencjΩ z tabeli
CMP WORD PTR ES:[BX],9090h; czy jedna z sekwencji ?
JE JEST ; jest czΩ£µ sekwencji
CMP WORD PTR ES:[BX],03EBh ; czy druga z sekwencji ?
JNE NIEDZIAśA ; nie ma sekwencji - tuneling nie dzia│a
JEST:
CMP BYTE PTR ES:[BX+2],OE8h; czy druga czΩ£µ sekwencji ?
JNE NIEDZIAśA ; nie ma sekwencji - tuneling nie dzia│a
CMP WORD PTR ES:[BX+5],0FF2Eh ; czy trzecia czΩ£µ sekwencji ?
JNE NIEDZIAśA ; nie ma sekwencji - tuneling nie dzia│a
CMP BYTE PTR ES:[BX+7],02Eh ; czy czwarta czΩ£µ sekwencji ?
JNE NIEDZIAśA ; nie ma sekwencji - tunelling nie dzia│a
; znaleziona pe│na sekwencja
MOV BX,WORD PTR ES:[BX+8]
LES BX,DWORD PTR ES:[BX] ; ES:BX wskazuje na oryginalny adres int 21h
NIEDZIALA:
Dla przerwania 2Fh sekwencja będzia wyglądała bardzo podobnie, z jedyną zmianą w programie wartości 0FS z 109Eh na 10C6h i 0FB2h na 0FDAh.
6.4.2. Wykorzystanie trybu krokowego procesora (ang. tracing)
Do znalezienia oryginalnych wejść do procedur obsługi przerwań można wykorzystać tryb krokowy procesora. Po zainstalowaniu odpowiedniego monitora pod przerwaniem krokowym wykonuje się jakąś testową funkcję, której wynik jest już wcześniej znany (np. przez uprzednie wywołanie tej funkcji bez monitora przerwania krokowego). Na bazie tego możemy stwierdzić (będąc w procedurze obsługi przerwania krokowego), czy znajdujemy się w poszukiwanym, oryginalnym kodzie przerwania, poprzez testowanie zawartości odpowiedniego rejestru lub ich grupy.
Dla przerwania int 21h wygodnie śledzić np. funkcję 62h (weź aktualny adres PSP) lub funkcję 30h (weź numer wersji DOS), dla przerwania int 13h taką funkcją może być 08h (weź informację o parametrach dysku).
6.4.3. Tuneling rekursywny (ang. recursive tunneling)
Ze względu na możliwość blokowania trybu krokowego procesora do znalezienia oryginalnego adresu przerwania 21h można zastosować tzw. tuneling rekursywny. Polega on na tym, iż w otoczeniu aktualnej procedury obsługi przerwania (wskazywanej przez tablicę przerwań), poszukuje się kodów wywołań dalekich procedur lub skoków, dzięki którym zwykle przekazywane jest sterowanie do kolejnego elementu łańcucha obsługi przerwania. Najczęściej łańcuch taki składa się z następujących sekwencji:
Element_l
; pierwszy element │a±cucha
Skok_do_Elementu_2
; pamiΩµ wykorzystywana przez inne programy
Element_2 ; drugi element │a±cucha
Skok_do_Elementu_3
; pamiΩµ wykorzystywana przez inne programy
Element_N ; ostatni element │a±cucha - poszukiwana czΩ£µ systemu Powr≤t_Z_Elementu_N ; powr≤t poprzez rozkaz IRET lub
; RETF 2 do elementu poprzedniego lub bezpo£rednio
; do wywo│uj╣cego programu
Na przykład działanie procedury szukającej adresu przerwania 21h można sprowadzić do następującej sekwencji:
mov ah,52h ; pobierz do ES:BX adres struktury
int 21h ; LL (lista list)
mov bx,es
xor ax,ax ; ustaw adres DS:SI na adres
mov ds,ax ; przerwania 21h wskazywanego
mov si,21h*4 ; przez tablice przerwa±
xchg ax,di ; DI=licznik sprawdzanych bajtow=0
Adres 32:
Ids si,ds:[si] ; pobierz adres
or bx,bx ; czy koniec szukania ?
jz WSegmencieDOS ; TAK - powr≤t DS:SI-adres
mov ax,ds ; czy jest to segment DOS ?
cmp ax, bx ; /
jne NastepnyBajt ; TAK - znaleziony adres
xor bx,bx ; BX=0 oznacza koniec szukania
NastepnyBajt:
lodsw ; we 2 bajty bΩd╣ce czΩ£ci╣ aktualnej procedury dec si ; sprawdzamy co bajt
cmp al,9Ah ; czy jest to CALL FAR PTR ?
je Adres32 ; TAK - we kolejny adres
cmp al,0EAh ; czy jest to JMP FAR PTR ?
je Adres32 ; TAK - we kolejny adres
cmp ax,0FF2Eh ; czy jest to JMP FAR CS:DWORD ?
jne NieJMP_DWORD
cmp byte ptr [si+l],al ; czy dalsz╣ czΩ£µ rozkazu JMP FAR CS:DWORD ?
jne NieJMP_DWORD
mov si,ds:[si+2] ; pobierz offset do danych dla skoku jmp short Adres32 ; TAK - we kolejny adres
NieJMP_DWORD:
inc DI ; licznik sprawdzanych bajt≤w
and DI,4095 ; je┐eli sprawdzono ju┐ 4095 bajt≤w,
je Recursive21_Exit ; to ko±cz, bo tuneling nie dzia│a
jmp NastepnyBajt ; we kolejny bajt
WSegmencieDOS:
; adres zosta│ znaleziony (jest w DS:SI)
RecursNieDzia│a:
; adres nie zosta│ znaleziony
6.4.4. Trik2F/13
Do znalezienia oryginalnego programu obsługi przerwania 13h (obsługa fizycznych dysków) w ROM-BIOS można zastosować funkcję (13/2F), która służy do ustawiania nowej procedury obsługi dysków. Po jej wywołaniu dodatkowo zwracana jest informacja o obecnej i pierwotnej (oryginalnej) procedurze obsługi tego przerwania [dokładniej: zwracane są wartości parametrów z poprzedniego wywołania funkcji (13/2F)]. Funkcję tę wykorzystuje IO.SYS przy starcie sy
stemu, aby przejąć kontrolę nad różnymi błędami pojawiającymi się przy dostępie do dysków. To, że potrzebuje ona parametrów wejściowych, można pominąć, gdyż jej dwukrotne wywołanie przywraca oryginalne ustawienia systemu. Poniższa sekwencja pokazuje, jak za pomocą opisanej funkcji znaleźć oryginalny (o ile nie jest on kontrolowany przez program antywirusowy) adres int 13h w ROM-BIOS-ie:
; Trik 2F/13
MOV AH,13h ; funkcja - ustaw obs│ugΩ dysk≤w DS:DX adres
; procedury obs│ugi (mo┐na pomin╣µ gdy┐ za
; chwilΩ i tak zostanie przywr≤cona w│a£ciwa
; procedura obs│ugi). ES:BX adres procedury, kt≤ra system
; bΩdzie ustawia│ jako procedurΩ obs│ugi przerwania nr 13h
; przy ewentualnym zawieszeniu systemu lub po wywo│aniu
; int 19h (tak┐e mo┐na pomin╣µ)
INT 2Fh ; wywo│aj funkcjΩ 13h
; po wywo│aniu ES:BX zwraca adres procedury, kt≤ra system
; ustawi jako int 13h w wy┐ej wymienionych wypadkach, czyli
; zwykle bΩdzie to oryginalna procedura obs│ugi przerwania
13h MOV SEG_13,ES ; trzeba zapamiΩtaµ adres oryginalnej procedury obs│ugi
MOV OFS_13,BX ; intl3h, znajduj╣cej siΩ w ES:BX
MOV AH,13h ; funkcja - ustaw obs│ugΩ dysk≤w DS:DX i ES:BX to warto£ci
; z poprzedniego wywo│ania funkcji (13/2F)
INT 2Fh ; wywo│aj funkcjΩ 13h
Poniższy program znajduje (o ile to możliwe) wejścia do przerwań 21h, 13h, 2Fh, z wykorzystaniem różnych technik tunelingowych-
;
Czesc ksiazki : 'Nowoczesne techniki wirusowe i antywirusowe' ;
;
TUNEL v1.0, Autor : Adam Blaszczyk 1997 ;
;
Program demonstruje uzycie kilku odmian tunelingu ;
do znalezienia oryginalnych adresow przerwan ;
- 13h (trik 2F/13, tryb krokowy) ;
- 21h (tablica stalych adresow, tryb krokowy, tuneling rekursywny) ;
- 2Fh (tablica stalych adresow) ;
;
; Kompilacja : ;
TASM TUNEL.ASM ;
TLINK /t TUNEL.OBJ ;
;
NUL = 00h ;
LF = 0Ah ; - stale potrzebne do deklaracji
CR = 0Dh ; / lancuchow napisowych
ON = 001h ; stale potrzebne do obslugi
OFF = 002h ; / przerwania 1
PROG segment ; segment kodu i danych
ORG 100h ; program jest typu COM
Assume CS:PROG, DS:PROG, ES:PROG, SS:PROG
CodeStart: ; tu zaczyna sie program
lea si,TeCopyRight ; pokaz info o programie
Call Print ; /
Call GetOriginal13 ; pokaz oryginalny adres 13h
Call GetOriginal21 ; pokaz oryginalny adres 21h
Call GetOriginal2F ; pokaz oryginalny adres 21h
mov ax, 4C00h ; koncz program i powroc do DOSa
int 21h ; /
GetOriginal13 proc near ; procedura pobiera oryginalny adres
; Int 13h (na dwa sposoby) i wyswietla
; go
push si ; zachowaj zmieniany rejestr
lea si,TeGet13 ; pokaz info o przerwaniu 13h
Call Print ; /
Call Trik2F13 ; wez adres 13h
; metoda Trik 2F/13
Call ShowAddr ; pokaz adres 13h
Call Tracing13 ; wez adres 13h
; metoda tracingu
Call ShowAddr ; pokaz adres 13h
pop si ; przywroc zmieniany rejestr
ret ; powrot z procedury
GetOriginal13 endp
Trik2F13 proc near ; procedura pobiera oryginalny adres
; Int 13h wykorzystujac funkcje 13h
; przerwania 2Fh
; (wewnetrzna funkcja DOS)
push ds ;
push es ;
push ax ; zachowaj zmieniane rejestry
push bx ; /
push dx ; /
push si ; /
lea si,TeTrik2F13 ; pokaz info o metodzie
Call Print ; / Trik 2F/13h
xor ax,ax ; zeruj zmienne pomocnicze
mov ShowSeg,ax ; /
mov ShowOfs,ax ; /
mov ah,13h ;
int 2Fh ;
;
mov cs:ShowSeg,es ; trik 2F/13
mov cs:ShowOFS,bx ; /
; /
mov ah,13h ; /
int 2Fh ; /
pop si ;
pop dx ;
pop bx ; przywroc zmieniane rejestry
pop ax ; /
pop es ; /
pop ds ; /
ret ; powrot z procedury
Trik2F13 endp
Tracing13 proc near ; procedura popbiera oryginalny
; adres Int 13h, wykorzystujac
; metode tracingu
push ds ;
push es ;
push ax ; zachowaj zmieniane rejestry
push bx ; /
push cx ; /
push dx ; /
push si ; /
mov ShowError, offset TeTracingFail
; ewentualny komunikat o bledzie
lea si,TeTracing13 ; wyswietl info o metodzie
Call Print ; /
xor ax,ax ; zeruj zmienne pomocnicze
mov ShowSeg,ax ; /
mov ShowOfs,ax ; /
mov ah,8 ; pobierz info o twardym dysku
mov dl,80h ; i zachowaj na pozniej wartosci
int 13h ; / rejestrow CX i DX; beda one
mov MagicNum1,cx ; / potrzebne do sprawdzenia czy
mov MagicNum2,dx ; / tracer jest juz w dobrym kodzie
mov ax,3513h ; wez adres przerwania Int 13h,
int 21h ; zeby mozna je bylo przetrace'owac,
mov CallFarSeg,es ; / trzeba je emulowac poprzez
mov CallFarOfs,bx ; / pushf/call dword ptr Ofs:Seg
mov TraceMode,OFF ; flaga potrzebna tracerowi
mov ax,3501h ; pobierz adres obslugi
int 21h ; przerwania krokowego Int 1
mov of1,bx ;
mov se1,es ; i ustaw nowa procedure jego
; - obslugi, sprawdzajaca, czy
mov dx,offset Tracer_13 ; / funkcja zostala juz wykonana
mov ax,2501h ; / przez BIOS
int 21h ; /
pushf ; wlacz tryb krokowy
pop ax ; procesora
or ah,1 ;
push ax ; /
popf ; /
mov dl,80h ; parametr funkcji 08/int 13h = HD0
mov ah,08h ; numer funkcji BIOS
pushf ; czesc emulacji Int 13
mov TraceMode,ON ; wlacz flage tracera
Call dword ptr cs:IntAsFarCall
; emuluj int 13
mov TraceMode,OFF ; wylacz flage tracera
pushf ; wylacz tryb krokowy
pop ax ; procesora
and ah,0FEH ;
push ax ; /
popf ; /
lds dx,dword ptr cs:of1 ; przywroc stary adres przerwania
mov ax,2501h ; / krokowego Int 1
int 21h ; /
pop si ;
pop dx ;
pop cx ; przywroc zmieniane rejestry
pop bx ; /
pop ax ; /
pop es ; /
pop ds ; /
ret ; powrot z procedury
Tracing13 endp
Tracer_13 proc far
push bp ; zachowaj zmieniany rejestr
mov bp,sp ; BP wskazuje na stos
; [bp+00] BP
; [bp+02] IP
; [bp+04] CS
; [bp+06] FLAGS
push ax ; zachowaj zmieniany rejestr
cmp cs:TraceMode,ON ; czy wlaczony tracer ?
jne Tracer_13Exit ; jesli nie, to wyskocz z procedury
mov ax,[bp+04] ; AX=CS image
cmp ax,cs:ShowSeg ; czy segment kodu ten sam
je OldSeg13 ; tak=wyskocz procedury
; nie=zachowaj nowy adres seg:ofs
mov cs:ShowSeg,ax ; AX=CS image
mov ax,[bp+02] ; AX=IP image
mov cs:ShowOfs,ax
OldSeg13:
cmp cx,cs:MagicNum1 ;
jne Tracer_13Exit ; czy funkcja sie juz wykonala ?
cmp dx,cs:MagicNum2 ; / nie=wyskocz z procedury
jne Tracer_13Exit ; /
mov cs:TraceMode,OFF ; tak=wylacz tracer, bo adres
; znaleziony
Tracer_13Exit: ; koniec przerwania Int 1
pop ax ; przywroc zmieniany rejestr
or byte ptr [bp+7],1 ; [bp+06] FLAGS , ustaw
; bit TF dla nastepnego rozkazu
; wykonywanego po IRET
pop bp ; przywroc zmieniany rejestr
iret ; powrot z przerwania Int 1
Tracer_13 endp
GetOriginal21 proc near
push si ; zachowaj zmieniany rejestr
lea si,TeGet21 ; pokaz info o przerwaniu 21h
Call Print ; /
Call LookUpTable21 ; wez adres 21h
; tablica stalych adresow
Call ShowAddr ; pokaz adres 21h
Call Recursive21 ; wez adres 21h
; metoda tunelingu rekursywnego
Call ShowAddr ; pokaz adres 21h
Call Tracing21 ; wez adres 21h
; metoda tracingu (tryb krokowy)
Call ShowAddr ; pokaz adres 21h
pop si ; przywroc zmieniany rejeetr
ret ; powrot z procedury
GetOriginal21 endp
LookUpTable21 proc near
push es ;
push ax ; zachowaj zmieniane rejestry
push bx ; /
push si ; /
lea si,TeLookUpTable21 ; wyswietl info o metodzie
Call Print ; /
xor ax,ax ; zeruj zmienne pomocnicze
mov ShowSeg,ax ; /
mov ShowOfs,ax ; /
mov ShowError, offset TeLookUpTableFailDOSVer
; ewentualny komunikat o bledzie
mov ah,30h ; wez wersje DOS
int 21h ; /
xchg al,ah ; ax=wersja DOS, ah=major,al=minor
mov bx,109Eh ; ofset dla DOS 5.0 - 6.22
cmp ax,0500h ; wersja musi byc wieksza od 5.00
jb LookUpTable21_Exit ; mniejsza=tuneling nie zadziala
cmp ax,0622h ; dla wersji wiekszej od 6.22
jbe DOSVerOk21 ; jest inny ofset
mov bx,0FB2h ; ofset dla DOS >6.22 (np. 7.0)
DOSVerOk21: ; ofset ustawiony
push bx ; zachowaj go na stosie
mov ah,52h ; pobierz do ES:BX adres struktury
int 21h ; / LL (lista list)
pop bx ; przywroc ze stosu ofset do skoku
mov ShowError, offset TeLookUpTableFailBadOfs
; ewentualny komunikat o bledzie
; czy pod ES;BX jest sekwencja
; 90 lub EB NOP JMP $+3
; 90 lub 03 NOP /
; E8 xx xx CALL NEAR [IP+xxxx]
; 2E FF 2E yyyy JMP FAR CS:[yyyy] ?
cmp word ptr es:[bx],9090h
je FirstCodeOK21 ; skocz, gdy sa 2 NOPy
cmp word ptr es:[bx],03EBh
jne LookUpTable21_Exit ; skocz, gdy JMP $+3
FirstCodeOK21:
cmp byte ptr es:[bx+2],0E8h ;
jne LookUpTable21_Exit ; skocz, gdy nie ma CALL xxxx
cmp word ptr es:[bx+5],0FF2Eh
jne LookUpTable21_Exit ; skocz, gdy nie ma czesci rozkazu jmp far
cmp byte ptr es:[bx+7],02Eh ;
jne LookUpTable21_Exit ; skocz, gdy nie ma czesci rozkazu jmp far
mov bx,word ptr es:[bx+8] ; pobierz [yyyy]=adres oryginalnej procedury
les bx,dword ptr es:[bx] ; /
mov ShowSeg,es ; przepisz segment i offset
mov ShowOfs,bx ; potrzebne do wyswietlenia adresu
LookUpTable21_Exit: ; skacz tu, gdy jakis blad
pop si
pop bx ;
pop ax ; - przywroc zmieniane rejeetry
pop es ; /
ret ; powrot z procedury
LookUpTable21 endp
Recursive21 proc near
push es ;
push ds ;
push ax ; zachowaj zmieniane rejestry
push bx ; /
push si ; /
push di ; /
lea si,TeRecursive21 ; wyswietl info o metodzie
Call Print ; /
mov ShowError, offset TeRecursive21Fail
; ewentualny komunikat o bledzie
xor ax,ax ; zeruj zmienne pomocnicze
mov ShowSeg,ax ; /
mov ShowOfs,ax ; /
mov ah,52h ; pobierz do ES:BX adres struktury
int 21h ; / LL (lista list)
mov bx,es
xor ax,ax ; ustaw adres DS:SI na adres
mov ds,ax ; przerwania 21h wskazywanego
mov si,21h*4 ; przez tablice przerwa±
xchg ax,di ; DI=licznik sprawdzanych bajtow=0
Adres32:
lds si,ds:[si] ; pobierz adres
or bx,bx ; czy koniec szukania ?
jz WSegmencieDOS ; TAK - powrot DS:SI=adres
mov ax,ds ; czy jest to segment DOS ?
cmp ax,bx ; /
jne NastepnyBajt ; TAK - znaleziony adres
xor bx,bx ; BX=0 oznacza koniec szukania
NastepnyBajt:
lodsw ; wez 2 bajty bedace czescia
; aktualnej procedury
dec si ; sprawdzamy co bajt
cmp al,9Ah ; czy jest to CALL FAR PTR ?
je Adres32 ; TAK - wez kolejny adres
cmp al,0EAh ; czy jest to JMP FAR PTR ?
je Adres32 ; TAK - wez kolejny adres
cmp ax,0FF2Eh ; czy jest to JMP FAR CS:DWORD ?
jne NieJMP_DWORD ;
cmp byte ptr [si+1],al ; czy dalsza czesc rozkazu JMP FAR CS:DWORD ?
jne NieJMP_DWORD ;
mov si,ds:[si+2] ; pobierz ofset do danych dla skoku
jmp short Adres32 ; TAK - wez kolejny adres
NieJMP_DWORD:
inc DI ; licznik sprawdzanych bajtow
and DI,4095 ; jezeli sprawdzono juz > 4095 bajtow,
je Recursive21_Exit ; to koncz, bo tuneling nie dziala
jmp NastepnyBajt ; wez kolejny bajt
WSegmencieDOS:
; adres zostal znaleziony (jest w DS:SI)
mov cs:ShowSeg,ds ; przepisz segment i offset
mov cs:ShowOfs,si ; potrzebne do wyswietlenia adresu
Recursive21_Exit: ; skacz tu, gdy jakis blad
pop di ;
pop si ;
pop bx ; przywroc zmieniane rejeetry
pop ax ; /
pop ds ; /
pop es ; /
ret ; powrot z procedury
Recursive21 endp
Tracing21 proc near ; procedura popbiera oryginalny
; adres Int 13h wykorzystujac
; metode tracingu
push ds ;
push es ;
push ax ; zachowaj zmieniane rejestry
push bx ; /
push cx ; /
push dx ; /
push si ; /
mov ShowError, offset TeTracingFail
; ewentualny komunikat o bledzie
lea si,TeTracing21 ; wyswietl info o metodzie
Call Print ; /
xor ax,ax ; zeruj zmienne pomocnicze
mov ShowSeg,ax ; /
mov ShowOfs,ax ; /
mov ah,62h ; pobierz info o aktualnym PSP
int 21h ; i zachowaj na pozniej te wartosc
mov MagicNum1,bx ; / (rejestr BX) bedzie ona
; / potrzebna, zeby sprawdzic, czy
; / tracer jest juz w dobrym kodzie
mov ax,3521h
int 21h ; wez adres przerwania Int 21h,
mov CallFarSeg,es ; zeby mozna je bylo przetrace'ow
mov CallFarOfs,bx ; / trzeba je emulowac poprzez
; / pushf/call dword ptr Ofs:Seg
mov TraceMode,OFF ; flaga potrzebna dla tracera
mov ax,3501h ; pobierz adres obslugi
int 21h ; przerwania krokowego Int 1
mov of1,bx ;
mov se1,es ; i zmien je na nowa procedure
; - obslugi, sprawdzajaca czy
mov dx,offset Tracer_21 ; / funkcja zostala juz wykonana
mov ax,2501h ; / przez DOS
int 21h ; /
pushf ; wlacz tryb krokowy
pop ax ; procesora
or ah,1 ;
push ax ; /
popf ; /
mov ah,62h ; numer funkcji DOS
pushf ; czesc emulacji Int 21
mov TraceMode,ON ; wlacz flage tracera
Call dword ptr cs:IntAsFarCall ; emuluj int 21
mov TraceMode,OFF ; wylacz flage tracera
pushf ; wylacz tryb krokowy
pop ax ; procesora
and ah,0FEH ;
push ax ; /
popf ; /
; przywroc stary adres przerwania
lds dx,dword ptr cs:of1 ; / krokowego Int 1
mov ax,2501h ; /
int 21h
pop si ;
pop dx ;
pop cx ; przywroc zmieniane rejestry
pop bx ; /
pop ax ; /
pop es ; /
pop ds ; /
ret ; powrot z procedury
Tracing21 endp
Tracer_21 proc far
push bp ; zachowaj zmieniany rejestr
mov bp,sp ; BP wskazuje na stos
; [bp+00] BP
; [bp+02] IP
; [bp+04] CS
; [bp+06] FLAGS
push ax ; zachowaj zmieniany rejestr
cmp cs:TraceMode,ON ; czy wlaczony tracer ?
jne Tracer_21Exit ; jesli nie, to wyskocz z procedury
mov ax,[bp+04] ; AX=CS instrukcji
cmp ax,cs:ShowSeg ; czy segment kodu ten sam
je OldSeg21 ; tak=wyskocz procedury
mov cs:ShowSeg,ax ; nie=zachowaj nowy adres seg:ofs
mov ax,[bp+02] ; AX=CS instrukcji
mov cs:ShowOfs,ax ; AX=IP instrukcji
OldSeg21:
cmp bx,cs:MagicNum1 ;
jne Tracer_21Exit ; czy funkcja juz sie wykonala ?
; / nie=wyskocz z procedury
mov cs:TraceMode,OFF ; / tak=wylacz tracer, bo adres
; / znaleziony
Tracer_21Exit: ; koniec przerwania Int 1
pop ax ; przywroc zmieniany rejestr
or byte ptr [bp+7],1 ; [bp+06] FLAGS, ustaw
; bit TF dla nastepnego rozkazu
; wykonywanego po IRET
pop bp ; przywroc zmieniany rejestr
iret ; powrot z przerwania Int 1
Tracer_21 endp
GetOriginal2F proc near
push si ; zachowaj zmieniany rejestr
lea si,TeGet2F ; pokaz info o przerwaniu 2Fh
Call Print ; /
Call LookUpTable2F ; wez adres 2Fh
; tablica stalych adresow
Call ShowAddr ; pokaz adres 21h
pop si ; przywroc zmieniany rejestr
ret ; powrot z procedury
GetOriginal2F endp
LookUpTable2F proc near
push es ;
push ax ; zachowaj zmieniane rejestry
push bx ; /
push si ; /
lea si,TeLookUpTable2F ; wyswietl info o metodzie
Call Print ; /
xor ax,ax ; zeruj zmienne pomocnicze
mov ShowSeg,ax ; /
mov ShowOfs,ax ; /
mov ShowError, offset TeLookUpTableFailDOSVer
; ewentualny komunikat o bledzie
mov ah,30h ; wez wersje DOS
int 21h ; /
xchg al,ah ; ax=wersja DOS, ah=major,al=minor
mov bx,10C6h ; ofset dla DOS 5.0 - 6.22
cmp ax,0500h ; wersja musi byc wieksza od 5.00
jb LookUpTable2F_Exit ; mniejsza=tuneling nie zadziala
cmp ax,0622h ; dla wersji wiekszej od 6.22
jbe DOSVerOk2F ; jest inny ofset
mov bx,0FDAh ; ofset dla DOS >6.22 (np. 7.0)
DOSVerOk2F: ; ofset ustawiony
push bx ; zachowaj go na stosie
mov ah,52h ; pobierz do ES:BX adres struktury
int 21h ; / LL (lista list)
pop bx ; przywroc ze stosu ofset do skoku
mov ShowError, offset TeLookUpTableFailBadOfs
; ewentualny komunikat o bledzie
; czy pod ES;BX jest sekwencja
; 90 lub EB NOP JMP $+3
; 90 lub 03 NOP /
; E8 xx xx CALL NEAR [IP+xxxx]
; 2E FF 2E yyyy JMP FAR CS:[yyyy] ?
cmp word ptr es:[bx],9090h
je FirstCodeOK2F ; skocz, gdy sa 2-a NOPy
cmp word ptr es:[bx],03EBh
jne LookUpTable2F_Exit ; skocz, gdy JMP $+3
FirstCodeOK2F:
cmp byte ptr es:[bx+2],0E8h ;
jne LookUpTable2F_Exit ; skocz, gdy nie ma CALL xxxx
cmp word ptr es:[bx+5],0FF2Eh
jne LookUpTable2F_Exit ; skocz, gdy nie ma czesci rozkazu jmp far
cmp byte ptr es:[bx+7],02Eh ;
jne LookUpTable2F_Exit ; skocz, gdy nie ma czesci rozkazu jmp far
mov bx,word ptr es:[bx+8] ; pobierz [yyyy]=adres oryginalnej procedury
les bx,dword ptr es:[bx] ; /
mov ShowSeg,es ; przepisz segment i ofset
mov ShowOfs,bx ; potrzebne do wyswietlenia adresu
LookUpTable2F_Exit: ; skacz tu, gdy jakis blad
pop si
pop bx ;
pop ax ; - przywroc zmieniane rejestry
pop es ; /
ret ; powrot z procedury
LookUpTable2F endp
ShowAddr proc near ; wyswietl adres w postaci
; seg:ofs heksalnie na podstawie
; zawartosci zmiennych
; ShowSeg i ShowOfs
push ax ; zachowaj zmieniany rejestr
push si ; /
mov si,ShowError ; wez adres komunikatu o ewentualnym
; / bledzie
mov ax,ShowSeg ; czy seg i ofs sa wyzerowane,
or ax,ShowOfs ; tzn czy nie znaleziono adresu ?
jz ShowAddrError ; tak=nie znaleziono adresu
mov ax,ShowSeg ; wyswietl segment
Call PrintHexDW ; /
mov al,':' ; wyswietl dwukropek
Call PrintChar ; /
mov ax,ShowOfs ; wyswietl ofset
Call PrintHexDW ; /
lea si,TeCRLF ; wyswietl CR,LF,
ShowAddrError: ; - czyli przejdz do nastepnego wiersza
Call Print ; / lub komunikat o bledzie
pop si ;
pop ax ; / przywroc zmieniany rejestr
ret ; powrot z procedury
ShowAddr endp
PrintHexDW proc near ; procedura wyswietla heksalnie
; liczbe zawarta w AX
push ax ; zachowaj zmieniane rejestry
push bx ; /
lea bx,HexChars ; bx wskazuje na tablice konwersji
; liczb heksadecymalnych 0..F
Call PrintHex ; wyswietl liczbe w AX
pop bx ; przywroc zmieniane rejestry
pop ax ; /
ret ; powrot z procedury
PrintHexDW endp
PrintHex proc near
push ax ; zachowaj mlodsza czesc adresu
mov al,ah ; AL=starsza czesc adresu
Call PrintHexDB ; wyswietl starsza czesc adresu
pop ax ; przywroc mlodsza czesc adresu
PrintHexDB: ; wyswietl czesc adresu z al
mov ah,al ; zachowaj na chwile te czesc
shr al,1 ; wyswietl starsza czesc bajtu
shr al,1 ; al przesuniete o 4 w prawo
shr al,1 ;
shr al,1 ; /
xlat byte ptr cs:[bx] ; / al=[bx+al]
Call PrintChar ; / wyswietl znak w AL
mov al,ah ; wyswietl mlodsza czesc bajtu
and al,15 ; al zamaskowane z 00001111b
xlat byte ptr cs:[bx] ; / al=[bx+al]
Call PrintChar ; / wyswietl znak w AL
ret ; powrot z procedury
PrintHex endp
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,'TUNEL v1.0, Autor : Adam Blaszczyk 1997',NUL
TeGet13 db CR,LF,'Adres oryginalnej procedury 13h : '
db CR,LF,NUL
TeGet21 db CR,LF,'Adres oryginalnej procedury 21h : '
db CR,LF,NUL
TeGet2F db CR,LF,'Adres oryginalnej procedury 2Fh : '
TeCRLF db CR,LF,NUL
TeTrik2F13 db ' _ trik Int 2Fh/13h := ',NUL
TeTracing13 db ' _ tracing 13h := ',NUL
TeLookUpTable21 db ' _ tablica stalych adresow 21h := ',NUL
TeRecursive21 db ' _ tuneling rekursywny 21h := ',NUL
TeTracing21 db ' _ tracing 21h := ',NUL
TeLookUpTable2F db ' _ tablica stalych adresow 2Fh := ',NUL
TeLookUpTableFailBadOfs db 'Blad : Zla kombinacja kodu',CR,LF,NUL
TeLookUpTableFailDOSVer db 'Blad : Wersja DOS musi byc >5.0',CR,LF,NUL
TeTracingFail db 'Blad : Tracing nie dziala',CR,LF,NUL
TeRecursive21Fail db 'Blad : Tuneling rekursywny nie dziala',CR,LF,NUL
HexChars db '0123456789ABCDEF'
ShowSeg dw ? ; zmienne pomocnicze do zachowywania
ShowOfs dw ? ; znalezionego adresu
ShowError dw ? ; zmienna dla ewentualnych bledow
of1 dw ? ; zmienne potrzebne do zachowywania
se1 dw ? ; adresu Int 1
IntAsFarCall label dword ; adres dalekiej procedury sluzacej do
CallFarOfs dw ? ; emulacji instrukcji INT
CallFarSeg dw ?
TraceMode db ? ; flaga ON=wlaczony/OFF= wlaczony tracer
MagicNum1 dw ? ; zmienne pomocnicze do przechowywania
MagicNum2 dw ? ; wartosci potrzebnych do sprawdzenia czy
; jestesmy juz we wlasciwym kodzie DOS/BIOS
PROG ends ; koniec segmentu kodu i danych
end CodeStart ; koniec programu, pierwsza instrukcja
; pod etykieta CodeStart
6.5. Wykorzystanie trybu chronionego
Tryb chroniony nie jest zbyt często wykorzystywany przez wirusy, jednak kilka z nich używa go do przejmowania przerwań. Po zainstalowaniu (co wiąże się z przejściem do trybu chronionego) każde odwołanie do jakiegokolwiek przerwania będzie kierowane najpierw do wirusa, a dopiero ten przekaże je do oszukiwanego systemu poprzez chwilowe przejście (ang. redirection) do trybu rzeczywistego (lub trybu V86). Ponadto, aby utrudnić wykrycie wirusa w pamięci, można po instalacji przenieść jego kod do pamięci powyżej 1MB.
W przypadku systemu Windows do przejmowania przerwań można wykorzystać fakt, iż udostępnia on programom usługi specyfikacji DPMI (ang. DOS Protected Mode Interface).
Do przejmowania przerwań służą funkcje:
> 0200h - odczytanie wektora przerwań trybu rzeczywistego;
> 0201h - zapisanie wektora przerwań trybu rzeczywistego;
> 0202h - odczytanie adresu procedury obsługi wyjątku;
> 0203h - ustawienie adresu procedury obsługi wyjątku;
> 0204h - odczytanie wektora przerwań trybu wirtualnego;
> 0205h - zapisanie wektora przerwań trybu wirtualnego;
Powyższe funkcje są dostępne w trybie chronionym za pośrednictwem przerwania 31h. Przed ich użyciem należy sprawdzić, czy DPMI jest dostępne, za pomocą funkcji (1687/2F). Dokładniejsze informacje na temat specyfikacji DPMI oraz trybu chronionego zawarte są w pozycjach [l] i [6] ze spisu na końcu książki.
6.6. Włączanie się jako program obsługi urządzenia
Jednym z wirusów stosujących tę metodę jest wymieniany już wirus DIR-2. Zamienia on oryginalną procedurę obsługi dysków poprzez manipulację na strukturach DPB, co zostało dokładniej omówione przy okazji omawiania wirusów zarażających JAP
Politica de confidentialitate | Termeni si conditii de utilizare |
Vizualizari: 1019
Importanta:
Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved