Rate this post

Praca z nośnikami magnetycznymi z lat 80. i 90. niesie ze sobą specyficzne ryzyko, o którym łatwo zapomnieć w dobie nowoczesnych piaskownic i zaawansowanych systemów uprawnień. Podłączenie stacji dyskietek przez adapter USB, próba odczytu starego dysku twardego IDE czy uruchomienie archiwalnego oprogramowania na fizycznym komputerze retro może natychmiast uaktywnić uśpiony kod złośliwy. Wirusy tamtej ery nie potrzebowały uprawnień administratora, połączenia z siecią ani skomplikowanych podatności zero-day. Wystarczył jeden nieostrożny rozruch z zainfekowanej dyskietki lub uruchomienie pozornie niewinnego pliku wykonywalnego, aby całkowicie przejąć kontrolę nad maszyną, bezpowrotnie nadpisać tablice alokacji plików lub trwale uszkodzić układy scalone na płycie głównej.

Zrozumienie technicznych fundamentów dawnego złośliwego oprogramowania jest kluczem do bezpiecznego zabezpieczania, archiwizowania i badania historycznych zbiorów danych. Niniejszy audyt techniczny szczegółowo opisuje wektory infekcji, mechanizmy rezydentne w pamięci operacyjnej oraz metody niszczenia danych stosowane przez najbardziej destrukcyjne wirusy epoki systemów DOS i wczesnego Windows.

Anatomia zagrożeń epoki DOS – brak ochrony pamięci i architektura trybu rzeczywistego

Środowisko MS-DOS oraz procesory rodziny x86 pracujące w trybie rzeczywistym (Real Mode) projektowano z myślą o prostocie i maksymalnej wydajności jednoużytkownikowej, całkowicie pomijając mechanizmy izolacji procesów. W tej architekturze każda działająca aplikacja miała nieograniczony dostęp do całej przestrzeni adresowej pamięci RAM (standardowo do 1 MB), rejestrów procesora oraz portów wejścia/wyjścia (I/O). Brakowało sprzętowego podziału na uprzywilejowany pierścień jądra (Ring 0) i przestrzeń użytkownika (Ring 3). Każda instrukcja procesora mogła odwołać się bezpośrednio do przestrzeni systemowej, modyfikując struktury danych DOS lub samego BIOS-u.

Tryb rzeczywisty procesorów x86 a bezpośredni dostęp do rejestrów i portów wejścia/wyjścia

W trybie rzeczywistym adresowanie pamięci opierało się na schemacie segment:offset, generującym 20-bitowy adres fizyczny. Oznaczało to, że dowolny program mógł swobodnie odczytywać i modyfikować zawartość pamięci operacyjnej należącej do innych procesów, struktur jądra DOS czy tablic konfiguracyjnych BIOS. Nie istniały mechanizmy stronicowania ani pamięci wirtualnej z prawami dostępu (Read/Write/Execute), które współcześnie blokują wykonywanie kodu w sekcjach danych.

Taki model architektury pozwalał złośliwemu oprogramowaniu na bezpośrednią komunikację z kontrolerami sprzętowymi za pomocą instrukcji IN oraz OUT. Wirus nie musiał prosić systemu operacyjnego o zgodę na wysłanie komend do kontrolera dysków twardych, stacji dyskietek czy układu zegara czasu rzeczywistego (RTC). Wystarczyło załadować odpowiednie parametry do rejestrów procesora i wywołać bezpośredni zapis do rejestrów kontrolera. Twórcy wirusów z łatwością omijali wszelkie prymitywne blokady programowe nakładane przez ówczesne proste nakładki zabezpieczające.

Przechwytywanie wektorów przerwań (INT 13h, INT 21h) przez programy rezydentne (TSR)

Fundamentem działania oprogramowania narzędziowego oraz wirusów w systemie DOS była technika TSR (Terminate and Stay Resident). Program rezydentny po wykonaniu swojej początkowej procedury zwalniał kontrolę do interpretera poleceń, jednak nie usuwał swojego kodu z pamięci RAM. Aby zagwarantować sobie stałe wykonywanie, wirus dokonywał modyfikacji tablicy wektorów przerwań IVT (Interrupt Vector Table), zlokalizowanej na samym początku pamięci fizycznej pod adresem 0000:0000h do 0000:03FFh.

Kluczowymi celami manipulacji były dwa przerwania:

  • INT 13h – niskopoziomowe przerwanie BIOS obsługujące bezpośredni odczyt, zapis i formatowanie sektorów dyskowych z pominięciem systemu plików;
  • INT 21h – główne przerwanie programowe MS-DOS udostępniające funkcje wysokopoziomowe, takie jak otwieranie plików, zmiana katalogów czy uruchamianie programów (funkcja 4Bh - EXEC).

Wirus podmieniał oryginalny wskaźnik przerwania w tablicy IVT na adres własnej procedury infekującej. W momencie, gdy użytkownik lub system wywoływał daną operację dyskową, kontrolę przejmował złośliwy kod. Wirus analizował żądanie, wykonywał infekcję nośnika lub pliku, a następnie przekazywał sterowanie do oryginalnej procedury BIOS/DOS, maskując swoją obecność.

Podstawowym sygnałem ostrzegawczym wskazującym na obecność wirusa TSR w pamięci była zmiana raportowanego rozmiaru pamięci konwencjonalnej. Złośliwy kod musiał zarezerwować dla siebie obszar na szczycie pamięci podstawowej (zazwyczaj tuż poniżej granicy 640 KB), kradnąc od 1 do kilkunastu kilobajtów i odpowiednio modyfikując pole w obszarze danych BIOS (BDA – BIOS Data Area pod adresem 0040:0013h). Punktem kontrolnym dla audytora sprzętu retro jest weryfikacja wyniku polecenia CHKDSK lub MEM /C – każda wartość całkowitej pamięci konwencjonalnej niższa niż 655 360 bajtów (640 KB) przy standardowej konfiguracji płyty głównej musi być traktowana jako anomalia wymagająca natychmiastowej weryfikacji.

Jeśli analiza pamięci wykazuje nieautoryzowane przesunięcie wektora INT 13h poza segmenty należące do BIOS (zazwyczaj F000h) lub jądra DOS, środowisko należy uznać za skompromitowane. W takim stanie nie wolno przeprowadzać żadnych operacji odczytu ani zapisu na cennych nośnikach vintage.

Wirusy sektora rozruchowego – mechanizm działania Stoned, Form i Michelangelo

Wirusy boot sektora (BSV – Boot Sector Viruses) oraz głównego rekordu rozruchowego (MBR) stanowiły dominującą grupę złośliwego oprogramowania przełomu lat 80. i 90. Ich skuteczność wynikała z faktu przejmowania kontroli nad procesorem zanim system operacyjny załadował jakiekolwiek mechanizmy kontrolne czy programy antywirusowe. Podczas procedury startowej BIOS automatycznie odczytywał sektor Cylinder 0, Head 0, Sector 1 pod stały adres pamięci 0000:7C00h i bezwzględnie przekazywał tam sterowanie. Wystarczyło pozostawić zainfekowaną dyskietkę w stacji A: podczas restartu komputera – nawet jeśli nośnik nie był dyskiem systemowym i BIOS zgłaszał błąd braku systemu – kod wirusa zdążył się wykonać i zainstalować w pamięci RAM.

Mechanizm infekcji nośnika przebiegał według powtarzalnego, wysoce zoptymalizowanego schematu:

Wirus odczytywał oryginalny sektor rozruchowy, kopiował go w ukryte, niestandardowe miejsce na dysku (np. na ostatni sektor ścieżki lub za obszar zarezerwowany przez system plików), a w jego pierwotne miejsce wgrywał własny kod rozruchowy. Po restarcie wirus rezerwował pamięć na szczycie RAM, instalował procedurę przechwytującą INT 13h, po czym odczytywał ukryty, oryginalny sektor startowy pod adres 0000:7C00h i skakał do niego, umożliwiając prawidłowy start systemu DOS bez wzbudzania podejrzeń użytkownika.

Poszczególne odmiany różniły się strategią ukrywania i destrukcji:

  • Stoned – jeden z najbardziej rozpowszechnionych wirusów w historii. Na dyskietkach przenosił oryginalny boot sektor do cylindra 0, głowicy 1, sektora 3 (dla formatu 360 KB/1.2 MB), a na dyskach twardych nadpisywał MBR, ukrywając pierwotną zawartość w cylindrze 0, głowicy 0, sektorze 7. Ponieważ sektor ten często pokrywał się z początkiem tablicy alokacji plików (FAT) na niestandardowo partycjonowanych dyskach, wirus nieodwracalnie niszczył strukturę danych, mimo że w założeniu twórcy miał jedynie wyświetlać komunikat „Your PC is now Stoned!”.
  • Form – wirus rezydentny infekujący sektor rozruchowy, który ukrywał oryginalny kod w ostatnim sektorze dyskietki lub partycji DOS. Zawierał moduł uciążliwego ładunku (payload), który aktywował się wyłącznie 18. dnia każdego miesiąca, przechwytując przerwanie klawiatury INT 09h i generując cichy dźwięk kliknięcia w głośniku systemowym (PC Speaker) przy każdym naciśnięciu klawisza.
  • Michelangelo – bezwzględna bomba logiczna oparta na kodzie wirusa Stoned. Wirus analizował datę systemową pobieraną z zegara RTC w trakcie procedury startowej. Jeśli data wskazywała 6 marca (rocznica urodzin Michała Anioła), kod pomijał rozruch systemu i natychmiast uruchamiał procedurę destrukcyjną: pętlę nadpisującą pierwsze 256 cylindrów, 4 głowice nośnika wartościami losowymi lub zerami za pośrednictwem funkcji AH=03h przerwania INT 13h. Efektem było natychmiastowe zniszczenie MBR, tablic FAT oraz katalogu głównego, co uniemożliwiało odzyskanie danych tradycyjnymi metodami.
Sprawdź też ten artykuł:  Współdzielenie plików między starym PC a nowym: SMB, FTP i obraz dysku

Podczas archiwizacji starych nośników magnetycznych kluczową zasadą bezpieczeństwa jest fizyczna blokada zapisu (przesunięcie skrzydełka Write-Protect na dyskietce 3,5″ lub zaklejenie wycięcia w dyskietce 5,25″) przed umieszczeniem jej w napędzie podłączonym do kontrolera. Jeśli konieczne jest wykonanie zrzutu binarnego, należy stosować kontrolery ze sprzętowym trybem Read-Only lub niskopoziomowe urządzenia odczytu strumienia magnetycznego (np. KryoFlux, Greaseweazle), które nie pozwalają systemowi operacyjnemu ani uśpionym procedurom BIOS na przesłanie komendy zapisu do głowicy napędu.

Infekcje plików COM i EXE – techniki dopisywania kodu, maskowania i polimorfizmu

Równolegle z wirusami boot sektora rozwijały się infekatory plików wykonywalnych. Środowisko DOS operowało na dwóch głównych formatach binarnych: prostym formacie .COM oraz bardziej złożonym, relokowalnym formacie .EXE (z nagłówkiem MZ). Różnice w strukturze tych plików determinowały metody wstrzykiwania kodu złośliwego.

Pliki .COM stanowiły płaski zrzut pamięci o maksymalnym rozmiarze 64 KB, ładowany bezpośrednio pod stały offset 0100h w segmencie programu. Najprostsze wirusy dopisywały swoje ciało na samym końcu pliku. Aby przejąć sterowanie, wirus odczytywał pierwsze 3 bajty oryginalnego pliku, zapisywał je w swoim ciele, a na początku programu umieszczał instrukcję bezwarunkowego skoku (JMP – kod maszynowy E9h) wskazującą na offset dopisanego na końcu złośliwego kodu. Po wykonaniu procedury infekującej (np. przeszukaniu bieżącego katalogu funkcjami FindFirst/FindNext przerwania INT 21h), wirus przywracał oryginalne 3 bajty w pamięci pod adresem 0100h i wykonywał skok pod ten adres, oddając kontrolę właściwej aplikacji.

W przypadku plików .EXE operacja wymagała precyzyjnej modyfikacji 28-bajtowego nagłówka MZ. Wirus nie musiał nadpisywać instrukcji w kodzie źródłowym programu – zamiast tego modyfikował pola nagłówka:

W nagłówku MZ zmieniane były wartości Initial CS:IP (wskazujące punkt wejścia programu) w taki sposób, aby procesor rozpoczynał wykonywanie kodu od ciała wirusa dopisanego na końcu ostatniej strony pliku. Równolegle wirus musiał zaktualizować pola rozmiaru pliku (Bytes on last page oraz Pages in file), a także przeliczyć rozmiar pamięci wymaganej przez program (MinAlloc/MaxAlloc), aby zapobiec nadpisaniu własnego kodu przez stos aplikacji. Oryginalne wartości rejestrów CS i IP były zachowywane wewnątrz ciała wirusa i służyły do wykonania skoku dalekiego (Far JMP) po zakończeniu infekcji kolejnych plików.

W odpowiedzi na proste skanery sygnaturowe twórcy wirusów wprowadzili zaawansowane techniki utrudniające analizę:

Wirusy typu Stealth (maskujące) instalowały się rezydentnie w pamięci i monitorowały wywołania przerwania INT 21h. W momencie, gdy program antywirusowy lub polecenie DIR żądało odczytu rozmiaru zainfekowanego pliku (funkcje 11h/12h lub 4Eh/4Fh), wirus w locie odejmował długość swojego kodu od wartości zwracanej w strukturze rekordu katalogowego. Przy próbie bezpośredniego odczytu zainfekowanego sektora przez INT 13h, wirus dynamicznie serwował czysty obraz pliku, ukrywając wprowadzone modyfikacje przed narzędziami diagnostycznymi.

Z kolei polimorfizm uniemożliwiał wykrywanie za pomocą statycznych ciągów bajtów. Wirusy polimorficzne (korzystające z silników takich jak MtE – Mutation Engine stworzony przez Dark Avengera) przy każdej nowej infekcji generowały unikalny moduł deszyfrujący oraz szyfrowały główne ciało wirusa za pomocą zmiennego klucza i zestawu losowych instrukcji (np. kombinacji XOR, ADD, ROR przemieszanych z instrukcjami NOP czy operacjami na nieużywanych rejestrach). Analiza takich próbek na historycznym sprzęcie wymaga stosowania emulatorów procesora z funkcją śledzenia instrukcji krok po kroku (Single-Step Debugging za pomocą flagi pułapki TF w rejestrze znaczników) lub wirtualnych piaskownic symulujących środowisko DOS.

Wirus CIH (Czarnobyl) – skok w Ring 0 i fizyczna

destrukcja komponentów

Wirus CIH, znany powszechnie jako Czarnobyl, zdefiniował na nowo pojęcie złośliwego oprogramowania pod koniec lat 90. Podczas gdy dotychczasowe wirusy DOS operowały w jednolitej przestrzeni adresowej trybu rzeczywistego, CIH zaatakował 32-bitowe środowisko Windows 95 i Windows 98. Był to pierwszy powszechny szkodnik infekujący pliki w formacie PE (Portable Executable) oraz wykorzystujący luki architektoniczne hybrydowych systemów Microsoftu do ucieczki z izolowanego pierścienia użytkownika (Ring 3) bezpośrednio do najbardziej uprzywilejowanego poziomu procesora – Ring 0.

Zamiast dopisywać kod na końcu pliku binarnego, CIH działał jako tzw. cavity infector (wirus szczelinowy). Przeszukiwał on wewnętrzną strukturę nagłówków sekcji PE w poszukiwaniu nieużywanych bloków pamięci (tzw. slack space), powstających w wyniku wyrównywania sekcji do granic stron pamięci (zazwyczaj wielokrotności 4 KB). Wirus dzielił swoje ciało na mniejsze fragmenty i ukrywał je w tych wolnych przestrzeniach wewnątrz istniejącego pliku, modyfikując wskaźniki w nagłówku. W efekcie rozmiar zainfekowanego pliku wykonywalnego nie zwiększał się ani o jeden bajt, co całkowicie paraliżowało proste mechanizmy weryfikacji sum kontrolnych i wielkości plików.

Kluczowym elementem mechanizmu działania CIH było przejęcie pełnej kontroli nad sprzętem. Systemy Windows 9x, mimo pracy procesora w trybie chronionym, nie izolowały dostatecznie tablicy deskryptorów przerwań (IDT – Interrupt Descriptor Table). CIH odczytywał adres bazowy IDT za pomocą nieuprzywilejowanej instrukcji SIDT, a następnie bezpośrednio modyfikował wektor przerwania (zazwyczaj INT 03h lub INT 01h), tworząc własną bramę przerwania (Interrupt Gate). Wywołanie tego przerwania z poziomu aplikacji Ring 3 powodowało natychmiastowe wykonanie złośliwego kodu z uprawnieniami jądra (Ring 0). W tym trybie wirus podpinał się pod podsystem sterowników wirtualnych (VxD) za pośrednictwem menedżera IFSMgr (Installable File System Manager), infekując każdy plik PE otwierany w systemie w czasie rzeczywistym.

Ładunek destrukcyjny wirusa – zaprogramowany na aktywację 26 kwietnia – uderzał w dwóch krytycznych wektorach:

Po pierwsze, wirus omijał standardowe warstwy systemu plików i wysyłał bezpośrednie komendy I/O do kontrolera dysków twardych IDE, zapętlając procedurę zapisu losowych wartości binarnych na pierwszych 2048 sektorach każdego fizycznego napędu. Skutkowało to całkowitym wyzerowaniem MBR, tablicy partycji oraz początkowych struktur FAT32.

Po drugie, CIH przeprowadzał atak na układ Flash ROM BIOS płyty głównej. Wirus wysyłał specyficzne sekwencje bajtów sterujących pod adresy portów I/O mostka południowego (np. chipsetów Intel 430TX, 440LX/BX), co odblokowywało linie zapisu do pamięci nieulotnej. Następnie wirus nadpisywał zawartość kości BIOS śmieciowymi danymi. Po wyłączeniu zasilania komputer stawał się całkowicie martwy – procesor po resecie nie był w stanie pobrać pierwszej instrukcji spod adresu FFFF:0000h, co uniemożliwiało wykonanie procedury POST.

Współczesna obsługa maszyn z epoki Windows 9x wymaga wdrożenia konkretnych procedur chroniących unikalny sprzęt przed skutkami podobnych infekcji. Podstawowym krokiem przed uruchomieniem nieznanego oprogramowania na retro-maszynie jest sprzętowe zabezpieczenie pamięci Flash BIOS. Większość płyt głównych z gniazdami Socket 7, Super Socket 7 oraz Slot 1 posiada fizyczną zworkę opisaną jako Flash ROM Write Protect lub Flash Voltage Select (przełączenie napięcia programowania z 12V/5V na masę). Przestawienie zworki w tryb blokady uniemożliwia nadpisanie układu na poziomie elektrycznym, niezależnie od uprawnień kodu działającego w systemie operacyjnym.

W przypadku konieczności naprawy płyty głównej, w której doszło do uszkodzenia zawartości kości Flash przez wirus lub nieudany proces aktualizacji, standardem diagnostycznym jest użycie zewnętrznego programatora EEPROM (np. układów z rodziny TL866II Plus lub T48) wraz z adapterem DIP32/PLCC32. Zrzut czystego wsadu binarnego pobrany z bazy producenta należy zaprogramować bezpośrednio w pamięci wyjętej z podstawki, co przywraca sprawność platformy bez konieczności ryzykownych metod przekładania układów na działającej płycie (tzw. hot-swap).

Praca z oprogramowaniem i nośnikami z epoki DOS oraz wczesnego Windows wymaga traktowania każdego niezweryfikowanego dysku jako potencjalnego źródła zagrożenia dla spójności danych i integralności komponentów. Ścisła kontrola wektorów przerwań, stosowanie sprzętowych blokad zapisu na nośnikach magnetycznych oraz izolacja procedur Flash BIOS pozwalają na bezpieczną eksplorację i rekonstrukcję środowisk retro bez ryzyka bezpowrotnej utraty historycznych konfiguracji.