Skrývanie vecí na platforme Windows: Súborové systémy 2
Z obrázku 2 v minulém díle seriálu o skrývání věcí na platformě Windows vidíte, že potenciální útočník má širokou možnost výběru místa, kam jeho ovladač zavěsí zařízení, aby mohl provádět souborové a diskové záškodnictví (monitorovat a pozměňovat souborové a diskové operace). Pokud je jeho cílem skrývání, měl by se zavěsit na co možná nejnižší úroveň, protože lze předpokládat, že detektory diskových nesrovnalostí se budou také snažit pracovat co nejblíže k hardware. Taková blízkost s sebou ale, nejen pro útočníka, přináší řadu nevýhod.
Obrázek 2: Zásobníky zařízení zainteresované v souborových operacích
První problém může nastat v případě, že obsah oblasti (svazku, oddílu, disku), kde chce útočník skrývat svoji přítomnost, podléhá softwarovému šifrování realizovanému například pomocí výše zmíněných nástrojů. Pokud se útočník zavěsí níže než zařízení provádějící šifrování a dešifrování dat, jeví se mu obsah jako pseudonáhodná (a tudíž z hlediska významu nesmyslná) posloupnost bajtů. Pokud tedy části, které potřebuje skrýt, detekuje na základě obsahu, musí se k nim dostat jiným způsobem. Obdobná situace samozřejmě platí i pro „hodné hochy“ – z pseudonáhodné posloupnosti se těžko pozná, zda popisuje skrytý soubor, nebo zda se jedná o nepoužívaný blok.
Další problém nízkoúrovňového zavěšení spočívá ve ztrátě kontextu. Na takové úrovni se totiž většina operací na disku jeví jako čtení a zápisy bloků dat. Co ale tyto operace znamenají jako celek, nelze z jejich monitorování jednoduše určit. Jednotlivé požadavky s sebou nenesou žádnou informaci, kterého souboru se týkají, protože takovému údaji nikdo v nízkoúrovňových zásobnících nerozumí.
V neposlední řadě se útočník setká i s problémem rozdílnosti hardware. Flash disky vložené do USB portu se ovládají jinak než ty připojené přes rozhraní IDE či SATA. Běžné aplikace a i ovladače o těchto rozdílech nemusí nic vědět, protože jim stačí komunikovat buď přes souborové operace, nebo přinejhorším s vrcholem zásobníku reprezentujícího obecné diskové zařízení, kde se ještě rozdíly v hardware neprojevují. Je třeba ale také mít na paměti, že i tyto entity mohou využít požadavků určených pro řízení pouze určitého druhu hardware, i když jim ovladače nacházející se na vyšších úrovních nebudou rozumět – požadavky na základě výše řečeného pravidla propadnou až k ovladačům, jež specifičnosti hardware rozumějí. Útočník si tedy například musí být vědom, že operaci čtení je možné provést pomocí obecného požadavku typu IRP_MJ_READ, ale i přes speciální zprávu IOCTL_SCSI_PASS_THROUGH, pokud je daný disk připojen přes rozhraní SCSI, nebo se tváří jako USB Mass Storage, které se v horní polovině nejnižšího zásobníku tváří jako SCSI-kompatibilní.
I když se útočníkovi podaří vyrovnat všemi výše popsanými neduhy, stále nemá vyhráno, i když tentokrát se jedná spíše o můj subjektivní názor než objektivní fakt. Detektoru nesrovnalostí stačí z disku data pouze číst a následně aplikovat parser příslušného souborového systému. Útočník navíc musí obsah, který skrývá, chránit před poškozením. Je-li zavěšen „proklatě nízko“, ovladač souborového systému o jeho skrývaných datech nic neví, a tak se je může pokusit přepsat i zcela neúmyslně (například se rozhodne na daném místě uložit data nového souboru). Útočník tedy musí být na pozoru i v případě, že se jej odhalit nikdo nesnaží. Z této úvahy vyplývá, že napsat detektor nesrovnalostí v souborovém systému je jednodušší než vytvořit záškodnický ovladač, který by jej obalamutil (nebo alespoň působil na stejné úrovni).
Z výše popsaných důvodů pořádně provedené skrývání souborů a složek nevypadá jako příliš lukrativní podnik. Pro útočníka existují i alternativy:
- Filtr souborového systému. Útočník zůstane u skrývání složek a souborů, ale vzdá se nízkoúrovňového filtrování požadavků. Uvažuje tak, že dokud uživatel nepojme podezření, skrývání realizované na základě filtru souborového systému (přítomnost v zásobníku na nejvyšší úrovni) plně postačuje. A pokud uživatel podezření pojme, opatření proti odhalení jsou tak drahá, že se je pro daný projekt nevyplatí realizovat.
- Skrývání jednotlivých bloků. Útočník se také může rozhodnout, že místo do souborů, bude svá tajná data ukládat přímo na disk. Najde si nepoužívanou oblast (například mezeru mezi dvěma oddíly nebo nevyužité místo na konci disku), kam bude svá data přímo ukládat a číst. Jelikož taková oblast nemá pro nikoho kromě útočníka žádnou strukturu, stačí mu příslušně manipulovat s operacemi čtení a zápisu na ni mířícími, a tím zajistit maximální úroveň utajení.
- Skrývání malých struktur. Další možnost pravděpodobně realizovatelnou i při nízkoúrovňovém zavěšení představuje skrývání datových struktur souborového systému, které se nacházejí v rámci jednoho bloku (sektoru, clusteru). V případě souborového systému NTFS se jedná o alternativní datové proudy (alternate data streams) či rozšířené atributy (extended attributes). Definice těchto struktur zabírá pár desítek bajtů v rámci záznamu popisujícího objekt souborového systému, ke kterému jsou přidruženy. Pro útočníka by neměl být velký problém najít soubor či adresář, do kterého pravděpodobně nikdo nebude zapisovat, přidružit k němu některou z těchto struktur a zapsat do ní potřebná data. Navenek však bude záznam o objektu zobrazovat tak, jako by k němu žádná data nepřidružoval.
Rozhodnutí implementovat skrývání v rámci filtru souborového systému sice útočníkovi práci zjednoduší (zejména v případě, že se tento počin rozhodne realizovat prostřednictvím nadstavby, kterou Windows pro tvorbu filtrů souborového systému poskytují, a vytvoří tzv. minifiltr souborového systému – file system minifilter driver), ale ne na úroveň triviality. Měl by například počítat s tím, že k objektům souborového sytému lze získat přístup nejen na základě jména. U některých souborových systémů lze k tomuto účelu využít i interního ID cílového objektu. Na druhou stranu, filtry souborového systému dovolují provádět podobné věci, jako umí ukázkový program RegHider – skrývat a emulovat obsah na základě aplikace, která o něj žádá.
Útočník by se mohl také pokusit realizovat jiné nepěkné kousky. Jednou z možností, která by podle mého názoru stála za prozkoumání, je zmanipulování symbolických odkazů. Aplikace totiž běžně přistupují k souborům přes cesty začínající písmenem svazku (například C:\Windows\Temp). Tato písmena však nejsou reálnými jmény zařízení reprezentujících dané svazky, nýbrž pouze symbolickými odkazy na ně. Pokud by útočník nasměroval tyto odkazy na svá zařízení (ať už přímou modifikací paměti jádra, nebo jejich smazáním a znovuvytvořením), mohl by svést většinu požadavků na souborové operace „na svoje území“ mimo zásobníky zařízení, které se jejich zpracováním standardně zabývají. Útočník by se do těchto zásobníků nemusel vůbec zavěšovat nebo instalovat svůj minifiltr.
Při zavěšování do zásobníku určitého zařízební musí nejen útočník, ale kdokoliv, dávat pozor, zda zařízení na dně zásobníku podporuje Plug&Play. Pokud ano, každý ovladač mající své zařízení v daném zásobníku musí rozumět požadavkům zasílaným správcem Plug&Play a adekvátně na ně reagovat. Mezi adekvátní reakci patří zejména odpojení zařízení ze zásobníku, pokud se dozvíte, že fyzické zařízení zásobníkem reprezentované bylo ze systému odebráno. Podobná, ale daleko jednodušší pravidla platí i v zásobnících souborových systémů.
Závěrem ohledně souborových systémů
Celá tato dvoudílná a poněkud teoretičtější kapitola pojednává o tom, jaké mechanismy jádro Windows uplatňuje při provádění souborových a diskových operací. Stejné koncepty se však používají i u jiných druhů zařízení: klávesnic, myší, paralelních a sériových portů, USB zařízení a najdete určitě i další příklady. Pokud tedy plánujete vytvořit ovladač, který s některými z těchto zařízení nějakým způsobem spolupracuje, měli byste vědět, co to je objekt ovladače, objekt zařízení či zásobník zařízení. Je ale potřeba mít se na pozoru před úskalími, jejichž popis tvoří zřejmě větší část této kapitoly. A to nemusíte vůbec patřit do skupiny ošklivých a efektivních útočníků.