How it's made: Virusy #4

11.06.2007 10:13 | blackhole_ventYl

Po mensej pauze sposobenej najma mojou lenivostou prichadza dalsi diel o virusoch a nimi pouzivanych technikach. Tentokrat sa zameriam na infekciu u suborovych virusov, teda infekciu COM a EXE suborov. Infekcia suborov je zakladnym reprodukcnym mechanizmom suborovych virov, vzhladom k tomu, ze jedine v spustitelnych suboroch aplikacii ma virus stabilnu a predvidatelnu sancu byt spusteny, infikuju sa prave tieto zaveditelne programy.

Odjakziva sa v MS-DOSe (teda presnejsie cca od verzie 2.0) pouzivali 2 formaty spustitelnych programov reprezentovane priponami COM a EXE. Format COM bol prebrany z operacneho systemu CP/M, bol teda primitivnejsi a mal striktnejsie obmedzenia. Format EXE pribudol v systeme MS-DOS, aby umoznil pisanie programov, ktore dokazu plne vyuzit platformu systemu bez nutnosti obchadzat ho.

Format COM bol charakteristicky tym, ze obsahoval len jediny programovy modul, umoznoval ulozit maximalne 65280 bytov kodu a dat, ktore od seba neboli separovane. Kedze system CP/M bol navrhnuty k behu na 8bitovych pocitacoch von Neumannovskej architektury, ktore nepoznali segmentaciu, vsetok kod v tychto programoch vyuzival relativne skoky za pomoci bazoveho registra, preto vzdy pri spusteni COM programu v MS-DOSe plati: CS=DS=ES=SS. Vykonatelny kod programu zacina na adrese 0x100. Pred touto adresou sa nachadza tzv. program segment prefix, co je 256 bytov dlha struktura obsahujuca niektore informacie o beziacom programe a volne miesto na ulozenie buffrov. Do program segment prefixu sa casto ukladal aj zasobnik, ktory COM aplikacie nemali specialne vyhradeny. Tento format bol v MS-DOSe zachovany pre spatnu kompatibilitu a svoje vyuzitie nasiel najma pri tvoreni ovladacov zariadeni a rezidentnych programov, pretoze zbavit sa zbytocneho balastu z COM aplikacie je jednoduchsie, nez osekat v pamati beziacu EXE aplikaciu. COM subor okrem vlastneho kodu a dat programu neobsahuje ziadnu hlavicku, signaturu, ani dalsie nalezitosti. Kod sa vykonaval vzdy od zaciatku.

Format EXE je mierne komplikovanejsi a viac odraza skutocnu platformu x86 (teda presnejsie skor odraza jedinu moznost programovat realne aplikacie na procesore 8086). Umoznuje definovat zasobnik aj vstupne miesto programu, umoznuje od seba oddelit kod a data a umoznuje zostavit program z viacerych modulov. Taktiez zohladnuje segmentaciu, takze program moze byt pisany tak, ze pracuje viacmenej v linearnom adresnom priestore zacinajucom od nuly a operacny system potom pomocou relokacnej tabulky moze adresovanie v programe zmenit tak, aby vyhovovalo skutocnosti. Nejedna sa vsak o dynamicke linkovanie programu, iba o viac-menej relokovatelny kod. Kod predpoklada, ze zacina pracovat v segmente s cislom 0 (co je prakticky nerealizovatelne - prvy cely kilobyte operacnej pamate procesora 8086 zabera tabulka vektorov preruseni), operacny system nasledne pri ulozeni programu do pamati k vsetkym segmentovym adresam pripocita pociatocnu adresu segmentu programu v pamati, aby program dokazal korektne pracovat. Format EXE nasiel uplatnenie vsade tam, kde bolo treba komplikovanejsi kod, alebo viac dat. Format EXE obsahuje na zaciatku hlavicku dynamickej dlzky a relokacnu tabulku, ktora obsahuje adresy hodnot, ktore je nutne skorigovat, pretoze obsahuju hodnoty relativne k segmentu 0 podla vyssie popisaneho postupu.

Vzhladom k tomu, ze subory COM a EXE maju odlisny format aj sa odlisne chovaju, musi sa infekcia tychto suborov vykonavat odlisne. Infekcia suboru EXE je podstatne zlozitejsia, ako infekcia suboru COM. V tejto casti neuvediem ziadne ukazky kodu, pretoze by jednak boli neumerne dlhe a jednak by nemali zmysel, vacsina infekcnej rutiny je divoka matematika s pointermi a file I/O.

Pri infekcii suboru COM je virus limitovany tym, ze COM subor je vzdy spusteny od prveho bytu (a nepriamo je limitovany aj dlzkou COM suboru), teda virus nema moznost posunut entrypoint priamo na svoje telo. Predtym samozrejme virus musi svoje telo do programu dostat. To mozno vykonat viacerymi sposobmi, v zavislosti na tom, nakolko nenapadny si virus zela byt.

Najcastejsou metodou je forma tzv. predlzujuceho virusu, ktory svoje telo pripoji na koniec COM suboru, pricom musi kontrolovat to, ci sa nesnazi infikovat prilis velky subor (kvoli limitu 65280 bytov). Vo virusovom tele obsahuje vyhradene miesto dost velke na ulozenie prvych niekolko bytov povodneho programu, ktore si tam pri infekcii nakopiruje a prve bajty programu nahradi instrukciou skoku na telo virusu. Tento postup virusu zabezpeci, ze ihned po spusteni programu bude riadenie odovzdane virusu, ktory vykona virusovu akciu (rezidentna instalacia, kontrola zavirenia, zavirenie dalsich suborov, atd.), nasledne z vyhradeneho miesta vo svojom tele nakopiruje na zaciatok programu odlozene byty a vykona skok na zaciatok programu, kde sa vsak teraz uz nachadza jeho legitimny kod, cize dalsi skok do tela virusu sa nevykona. Predlzujuce virusy nie su voci svojmu nositelovi destruktivne a v pripade, ze je znamy infekcny algoritmus, je mozne program odvirit. Nevyhodou pre virus je to, ze program napadnuty virusom bude mat vacsiu velkost.

Ina kategoria virusov su prepisujuce virusy, ktore obchadzaju problem so zvacsenim nositela tym, ze prepisu jeho povodny kod svojim, ale aj napriek tomu zachovaju prvych par instrukcii a po vykonani virovych akcii vykonaju skok na telo programu. Takyto program je nenavratne poskodeny a za predpokladu, ze nedoslo k prepisu datovej oblasti, sa stane nefunkcnym, co vsak virusu nevadi, pretoze v dobe, ked uzivatel zisti nefunkcnost programu, bude uz virus aktivny v pamati, alebo zaviri dalsie programy. Programy infikovane prepisujucimi virusmi nemozno odvirovat a su nenavratne znicene.

Specialnou kategoriou virusov stojacich na pomedzi medzi virusmi prepisujucimi a predlzujucimi su tzv. medzerove virusy. Subory COM (ale aj EXE) casto obsahuju prazdne casti, napriklad vyhradene buffre, alebo ine prazdne retazce v datovej obslasti, ktore ak su dostatocne velke, moze virus vyuzit na ulozenie svojho tela. Telo virusu nemusi byt nutne ulozene v jednom kuse, ale v pripade, ze je prazdnych oblasti v subore viac, virus sa moze rozporcovat a svojim telom tieto oblasti vyplnit. V takom pripade vsak bude musiet pred samotnym spustenim virusu tento casti svojho tela poskladat dokopy niekde mimo telo vykonavaneho programu a az tak bude moct spustit virove akcie. Vyhodou medzerovych virusov je, ze napadnuty program nezmeni svoju dlzku, nevyhodou vsak je, ze nie kazdy program je vhodny k infekcii takymto virusom. Jednym z casto sa vyskytujucich programov obsahujucich medzeru dost velku na ulozenie virusu je napriklad COMMAND.COM, ktory bol k tejto cinnosti casto zneuzivany. Program infikovany medzerovym virusom je mozne odvirit, ale je to podstatne komplikovanejsie, nez pri viruse predlzujucom, pretoze je potrebne dost presne poznat mechanizmus oznacenia miest, kam virus rozlozil svoje telo.

Rozdiel pri infekcii programu COM a EXE spociva v tom, ze v pripade infekcie suboru COM nie je nutne upravovat ziadne hlavicky, zatial co v pripade suboru EXE je nutne prepocitat niektore udaje v hlavicke. Format EXE je stavany viacmenej tak, ze umoznuje v spustitelnom subore spolu s vykonatelnym kodom distribuovat aj vsemozny nevykonatelny a pre beh samotneho programu absolutne nepotrebny bordel. Dosahuje sa toho tak, ze v hlavicke je zapisane, kde vykonatelny kod aplikacie zacina a aky je dlhy. Dlzka kodu aplikacie vsak nie je zapisana priamo v bytoch, ale vo forme poctu blokov a vyuzitia posledneho bloku. Kod programu bol "rozdeleny" do blokov pevnej velkosti a zarovnany na cele bloky vzdy smerom nahor. Toto cislo bolo uvedene v hlavicke EXE suboru ako prve, druhe cislo urcovalo, o kolko bol posledny blok zarovnany (kolko bytov z posledneho bloku patri k programu). Kedze kod programu je v pamati suvisly (EXE nepodporovalo dynamicke linkovanie), tieto 2 cisla dostatocne popisuju obraz programu v pamati. Virus preto musi dlzku programu po infekcii prepocitat a zapisat do hlavicky. Hlavicka EXE suboru dalej obsahuje checksum area, co je 16bitova hodnota, ktora funguje ako checksum programu. Teoria je asi taka, ze ak sa cela binarka programu zoXORoruje word po worde, vysledok ma byt 0. K tomu sluzi prave hodnota checksum wordu. Problemom je, ze vacsina linkerov necha tuto hodnotu na 0, pretoze MS-DOS tento field pri spustani programu nekontroluje. Virus preto nemusi checksum prepocitavat a nehrozi mu odhalenie. Virus vsak musi akceptovat to, ze za koncom obrazu spustitelneho kodu programu sa moze nachadzat nieco dalsie, co virus nesmie prepisat, ani zahodit, inac by program mohol znefunkcnit.

Vysledkom infekcie spustitelneho programu je to, ze kopia tela virusu sa stane sucastou kodu nositela a je vykonana este pred spustenim samotneho kodu programu. To dava virusu moznost vykonat virusovu akciu skor, nez sa spusti program, pretoze vstupne miesto v programe je jedine miesto programu, ktoreho vykonanie je zarucene za vsetkych okolnosti (za predpokladu, ze sa podari dostat program do stavu spustitelneho).

Pri infekcii programu vsak sofistikovanejsie virusy nemaju za ciel jedine infikovat program a tak si zabezpecit svoju aktivaciu, ale obvykle sa snazia aj co najviac skomplikovat odvirenie programu. Prepisujuce virusy to riesia tym, ze program nenavratne znicia, cim ale sposobia jeho nefunkcnost a odsudia svojho hostitela na zmazanie. S predlzujucimi virusmi to je v pripade jednoduchej infekcie relativne jednoduche. Staci poznat dlzku virusoveho tela a adresu miesta vyhradeneho pre ulozenie uvodnych instrukcii programu, instrukcie z vyhradeneho miesta nakopirovat na zaciatok (v pripade, ze sa jedna o COM subor, alebo o EXE infektor, ktory nemeni entrypoint, ale prepisuje kod programu) a virusove telo z konca programu odstrihnut.

Vychytavkove virusy sa pokusaju vsemozne zabranit odvireniu programu, rezidentne stealth virusy sa napriklad snazia zamaskovat fakt, ze program je zavireny, preto sa vesaju na obsluhu otvorenia suboru (nie spustenia binarky) a v pripade, ze sa otvara subor obsahujuci zavireny program, tak pred tym, ako sa telo suboru predhodi programu, sa on the fly odviri, aby nebolo vidno, ze je zavireny. To vsak nespada do sekcie infekcia.

Znemoznit, alebo aspon skomplikovat odvirenie je mozne uz pri samotnej infekcii, napriklad napodobnenim techniky medzeroveho virusu. Ten svoje telo moze (musi) fragmentovat, aby sa voslo do medzier v programe. Virusu vsak nic nebrani, aby svoje telo rozlozil aj v pripade, ze sa jedna o obycajny prepisujuci virus. Virus telo naseka podla lubovole a jeho kusky rozhodi po kode programu (napriklad si miesta vybera podla nejakej peknej, dostatocne rychlo rastucej a primerane perverznej funkcie). V takom pripade ale virus musi davat pozor na to, aby neporusil polozky v relokacnej tabulke, preto musi vsetky relokacne polozky s adresou za miestom vlozenia kusu kodu posunut o dlzku vkladaneho kodu smerom k vyssim adresam (to je okrem ineho dovod, preco virus umiestnuje svoje telo na koniec kodu). Ak nie je relokacna tabulka prazdna, virus sa jej zmene nemoze vyhnut, pretoze pocitanie relokacnych poloziek sa deje este pred spustenim programu.

Taketo rozsekanie virusu kladie na virus poziadavku svoje telo pred spustenim zlozit, kod povodneho programu nasledne zlepit vybranim zvyskov virusu a pre antivirus znamena prekazku, pretoze nestaci jednoducho odseknut potrebny pocet bytov z konca obrazu binarky, ale musi presne vediet zistit, ako, kam a ake velke kusy svojho kodu virus v programe rozhodil a pri ich vysekavani musi takisto upravovat relokacnu tabulku programu.

V nasledujucom pokracovani sa zamerima na obecne stealth techniky rezidentnych virusov, ako na urovni BIOSu, tak na urovni MS-DOSu, popis toho, co to vlastne stealth presne znamena a tym bude ukonceny popis "nezaujimavych" casti virusov. V dalsich pokracovaniach sa pokusim zameriat na vychytavkove vlastnosti, ako kryptovirusy, pravy a nepravy polymorfizmus a ine exoticke veci, ktore sa pocas rokov vyvoja vo virusoch nasli.