V tomto miniseriálu se převtělíme do role útočníka. Nebude nás ale zajímat, jak se do cílového počítače nabourat nebo jak v rámci jeho operačního systému získat dostatečná oprávnění. Předpokládáme, že v tomto ohledu útočník již dosáhl úspěchu a jeho další starostí je se na daném stroji udržet. Popíšeme si několik způsobů, jak skrýt různé aspekty své přítomnosti před uživatelem a přidáme ještě pár ošklivých triků. Tento článek pokrývá první třetinu mojí přednášky na konferenci Hakcerfest 2015.
Jako útočníka nás budou zajímat tři oblasti, kde skrývání dává nějaký smysl: registry, souborový systém a síťová komunikace. Pochopení textu by nemělo vyžadovat žádné speciální znalosti; vše potřebné se pokusím v rámci možností vysvětlit, i když třeba v zjednodušené (a ne úplně pravdivé) podobě.
Registry
Registr Windows lze chápat jako úložiště specializované na uchovávání nastavení všeho druhu. Z logického pohledu se jedná o strukturu podobnou souborovému systému; registr tvoří strom sestávající ze dvou druhů objektů:
- Hodnot (registry values) sloužících pro vlastní uchovávání dat. Od souboru se hodnota odlišuje zejména tím, že má pevně definovaný typ dat, která v ní lze ukládat (např. celé číslo či řetězec).
- Klíčů (registry key) plnících roli adresářů. Každý klíč může obsahovat klíče a hodnoty, stejně jako obsah adresáře tvoří další složky a soubory. Klíče tak staví stromovou strukturu registru stejným způsobem jako adresáře u souborového systému.
Na rozdíl od souborového systému je registr specializován na ukládání pouze malých objemů dat. Nedisponuje prostředky, jak například přečíst či změnit pouze část dat určité registrové hodnoty. Vždy pracuje s danou hodnotou jako s celkem. Do jedné hodnoty sice lze uložit i velké množství dat (maximální velikost je omezena na 2 GB), ale práce s nimi bude pomalá a paměťově náročná.
Strom registru je fyzicky uložen v několika souborech na disku a některé jeho části se nacházejí pouze v paměti a při každém startu systému se vytvářejí znovu. Uživatelé registru se o jeho fyzickou strukturu zajímat příliš nemusí, jelikož jej od ní jádro úspěšně odstiňuje.
Pro útočníka patří registr mezi zajímavé oblasti, protože obsahuje velké množství systémových nastavení, případně i nastavení různých nainstalovaných programů. Vhodnou změnou obsahu určitých registrových hodnot lze dosáhnout automatického spuštění programů, donucení aplikací k používání určitých DLL knihoven či načtení ovladače do jádra. Z tohoto důvodu může být pro útočníka zajímavé nejen takové oblasti registru znát, ale i je kontrolovat (například vědět, kdo s nimi právě pracuje). A Windows mu v tomto ohledu vycházejí vstříc.
Data registru jsou ukládána v binární podobě, takže není rozumné je číst či měnit přímo. Pro takové situace existuje program Editor registru (regedit.exe), který dovoluje prohlížet obsah registrového stromu a měnit ho. Informace o významu jednotlivých klíčů a hodnot ale neposkytuje; ty si musí uživatel obstarat sám. Ukázku programu vidíte na obrázku 1. Klíče tvořící stromovou strukturu jsou zobrazeny v levé části okna, pravá slouží k zobrazení seznamu hodnot aktuálně vybraného klíče, jehož celé jméno lze přečíst ve stavovém řádku. O hodnotách se z pravé části dozvíte jméno, typ uložených dat a lidsky čitelné zobrazení těchto dat (konkrétní podoba závisí na typu).

Obrázek 1: Editor registru – základní nástroj pro prohlížení a manipulaci
Filtrování operací
Ovladače mohou požádat systém, aby je upozorňoval, kdykoliv nějaká entita s registrem pracuje. Konkrétně takové upozornění dostávají v následujících situacích:
- těsně před tím, než je daná operace vykonána,
- těsně poté, co je vykonána (nebo pokus o její vykonání skončí nezdarem).
Z tabulky 1 shrnující možnosti, které ovladačům jádro v oblasti sledování registrových aktivit poskytuje, vidíte, že od Windows Vista má útočník nad registrem téměř plnou kontrolu. Nejenže může operace, které se mu nelíbí, blokovat (entita požadující takovou operaci obdrží chybový kód specifikovaný útočníkem) či měnit jejich parametry a výsledky, ale dokonce je možné dosáhnout emulace – ovladač útočníka se o celou operaci postará sám a na samotný registr nepřijde řada.
Tabulka 1: Možnosti ovladačů ohledně manipulace s registrovými operacemi v různých verzích Windows
Verze OS | Monitorování | Blokování | Změna | Emulace |
---|---|---|---|---|
XP SP2/3 | Jen před operací | ANO | NE | NE |
W2k3 | ANO | ANO | NE | NE |
Vista a novější | ANO | ANO | ANO | ANO |
Možnost emulace registrových operací dovoluje útočníkovi nejen efektivně skrývat obsah libovolných klíčů a hodnot před zraky běžících aplikací a ostatních komponent jádra, ale i zpřístupnit obsah, který v registru vůbec neexistuje. Tato schopnost, spolu s faktem, že útočník u každé detekované registrové operace ví, která aplikace se o ni pokouší, dovoluje provádění ošklivostí různého druhu.
Pokud váš překvapuje, že jsme nikde nevedl, jak se výše popisované rozhraní pro filtrování operací nad registrem nazývá, vězte, že bych vám jeho jméno rád prozradil. Bohužel jsem v dokumentaci na nic takového nenarazil. Proto je nejlepší se na něj odkazovat buď přes název funkce sloužící k registraci za účelem filtrování operací (CmRegisterCallback
či CmRegisterCallbackEx
), nebo označovat ovladače toto rozhraní používající slovním spojením registry filter driver
.
RegHider
RegHider je názornou ukázkou toho, co útočník může změnami v chování registru dokázat. Jedná se o ovladač, který svému okolí poskytuje následující služby:
- Skrývání registrových klíčů. Zadané klíče jsou skryty ze seznamu podklíčů jejich rodičů. Navíc, pokud se někdo dotáže na počet potomků určitého klíče, výstupní hodnota je upravena, aby skryté klíče nebyly prozrazeny. Pokud však entita jméno skrytého klíče zná, může k němu volně přistupovat.
- Vymýšlení registrových hodnot. Ovladač dokáže celkem důvěryhodně předstírat, že zadaný registrový klíč obsahuje hodnotu určitého jména, typu a daty, i když v registru žádná taková hodnota neexistuje. Navíc tuto hodnotu zobrazuje pouze procesům, jejichž jméno končí zadaným sufixem.
V praktické ukázce vidíte, že chvíli po přihlášení uživatele do 64bitové verze systému Windows 8.1 došlo k samovolnému spuštění Příkazového řádku. K samovolnému spuštění došlo proto, že aplikace Příkazového řádku byla uvedena v hodnotě s názvem Pseudo v klíči
HKEY_CURRENT_USERSOFTWAREMicrosoftWindowsCurrentVersionRun
Průzkumník Windows v rámci své inicializace tento klíč prohlíží a pokusí se spustit každý program, který v některé z jeho hodnot nalezne. Daný klíč patří mezi ty velmi známé a často užívané i pro samovolné spouštění škodlivých programů. Ovladač RegHider
v tomto ohledu zavádí novinku v podobě snížení viditelnosti hodnoty Pseudo
– vidí ji totiž pouze Průzkumník Windows, pouze pro něho je také určena.
Problém zobrazování určitého obsahu (nejen registru) pouze určitým aplikacím může značně zamotat hlavu nástrojům pro odhalení skrytých či vymyšlených objektů (v dobách své největší slávy se tato skupina nástrojů označovala jako antirootkity). Aby takový nástroj detekoval nesrovnalosti tohoto druhu, musel by je hledat „převlečen“ za entitu, pro kterou jsou zviditelněny (nebo skryty). V ostatních případech nemůže nic najít, protože z jeho pohledu k žádnému skrývání či vymýšlení nedochází.
Útočník může ale zajít ještě dále – může určité aplikace mást skrýváním a vymýšlením obsahu registru pouze v okamžicích, kdy se na něj dotazují. Například na výše uvedený Run klíč se Průzkumník dotazuje pouze při své inicializaci, takže by teoreticky stačilo, kdyby RegHider emuloval hodnotu Pseudo
, pouze dokud ji Průzkumník nepřečte. Ve zbývajícím čase, po který poběží, se již na ní nepodívá, tudíž nemá smysl vytvářet její iluzi.
Dalším zajímavým (a dobře známým) místem, kde by se útočníkovi mohlo hodit obsah registru trochu upravit, je klíč
HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionWindows
a jeho hodnota AppInit_DLLs. Jedná se o řetězcovou hodnotu uvádějící seznam DLL knihoven (jako oddělovač slouží znak čárky “,”). Tyto knihovny se pokusí načíst každá aplikace, která používá systémovou knihovnu user32.dll. Pokud tedy ovladač útočníka do tohoto seznamu “přidá” název své vlastní knihovny, dosáhne jejího načtení (a spuštění) prakticky v každé aplikaci používající grafické uživatelské rozhraní.
Po většinu času však útočník hodnotu AppInit_DLLs nijak emulovat nemusí, protože má význam pouze během inicializace knihovny user32.dll, a to se děje téměř výhradně v rané fázi běhu aplikace. Útočníkovi tedy stačí detekovat, že určitá aplikace právě načetla do paměti user32.dll (to pro ovladač není problém), “přidat” pro ni speciální obsah do hodnoty AppInit_DLLs a emulovat jej tam, dokud si tuto hodnotu aplikace nepřečte. Pak může obsah z hodnoty opět “odebrat”. Navenek (například přes Editor registru) “změna” v obsahu hodnoty nebude viditelná. Tuto operaci zatím RegHider nepodporuje.
Detekce ošklivostí
I když se z dosavadního popisu zdá, že útočník je nepřemožitelný, nemusí tomu být zdaleka tak. Nástroje pro detekci nesrovnalostí mají minimálně tři možnosti, jak postupovat:
- Útok na implementaci útočníka. Pokud má útočník dosáhnout svých cílů (skrytí přítomnosti či jiná změna obsahu registru), nemůže si dovolit žádnou nepozornost. Ač má oproti například skrývání entit souborového systému situaci značně zjednodušenou, i tak lze pouhým použitím funkcí pro práci s registrem získat zajímavé vědomosti a případně implementaci útočníka „prostřelit“ nebo alespoň získat kvalifikované podezření. Mezi nativní registrové operace patří třeba možnost uložení určitého podstromu registru do souboru. Útočník je v takovém případě informován pouze o tom, jaký podstrom se ukládá; musí si sám odvodit, zda se tato operace nějak dotýká jím zmanipulovaného obsahu. Pokud by se snažil o skrývání určitých klíčů, může je těsně před provedením samotného uložení do souboru z registru odstranit a po dokončení operace je tam opět vrátit.
- Offline analýza. Soubor obsahující uložený podstrom registru je možné porovnat s jeho kopií buď na běžícím sytému, nebo i offline (soubor s podstromem lze do registru připojit na jiné místo). Další možnost představuje manuální průzkum podstromu bez využití funkcí rozhraní Windows API. Mezi zajímavé projekty v této oblasti jistě patří knihovna Offline Registry Library či projekt chntpw. Oba disponují vlastním parserem registrových struktur. Nevýhoda offline analýzy spočívá mimo jiné ve faktu, že ne všechny klíče (a hodnoty) se do souboru podstromu ukládají. Při vytváření klíče je možné specifikovat speciální příznak, který instruuje jádro, že daný klíč a jeho hodnoty mohou existovat pouze v paměti.
- Online analýza. Další možnost obránce představuje přímý přístup do datových struktur registru bez použití libovolné úrovně registrových API. Jádro se snaží uchovávat celý registrový strom v paměti, přičemž podstromy původně uložené na disku jsou do paměti nějakým způsobem mapovány (buď přímo, nebo načtením z disku). S dostatečnou znalostí těchto datových struktur a fyzické podoby registru je možné vytvořit vlastní implementaci registrových API a ty používat za účelem detekce nesrovnalostí.