Hlavné menuPřihlášeníHledat |
Odpovědět na komentář
Čtvrtek, 24.07.2008 15:43
Konečně vyšel čas a s ním je tu i nový proof-of-concept, který jsem se rozhodl napsat po určitém výroku ohledně HijackThis a Combofix, který zněl nějak podobně: "co nevidí HJT, uvidí Combofix". Oba dva programy jsou relativně hojně využívané a jejich logy jsou směrodatné v detekci a léčení nákazy v systému na nemálo fórech týkajících se bezpečnosti. UPOZORNĚNÍ: NÁSLEDUJÍCÍ DOKUMENT JE URČEN POUZE PRO STUDIJNÍ ÚČELY. ZA JAKÉKOLIV ZNEUŽITÍ TOHOTO DOKUMENTU A JEHO SOUČÁSTÍ, VČETNĚ ZDROJOVÝCH KÓDU NENESE AUTOR ŽÁDNOU ZODPOVĚDNOST. ČLÁNEK NESMÍ BÝT KOPÍROVÁN BEZ POVOLENÍ AUTORA. WARNING: FOLLOWING DOCUMENT IS INTENDED FOR STUDY PURPOSES ONLY. AUTHOR HAS NO RESPONSIBILITY FOR ANY ABUSE OF THIS DOCUMENT OR ITS PARTS INCLUDING SOURCE CODE. IT IS NOT ALLOWED TO COPY THIS DOCUMENT WITHOUT AUTHORS PERSMISSION. if you do not agree, please close your eyes and try to close your browser ;) V tomto článku popíši jak vytvořit program, který se bude spouštět po startu a bude běžet libovolně dlouho. Nebude vidět v Hijackthis jako proces, jako položka po spuštění, ačkoliv se bude jednat o normální exe soubor. Stejně tak nebude vidět v jediné sekci Combofixu (upozornění pro "stálé" uživatele Combofixu: sekcí snapshot se zde zabívat nebudu, ta je založena na předchozím scanu Combofixu). Celý tento proof of concept je založen pouze na chybách, resp. velmi naivních předpokladech užitých v těchto dvou aplikacích - nejedná se tedy o žádný rootkit, ať už ring3 nebo ring0 - těmi se budeme zabývat velice podrobně jindy. Testováno na Windows 2000, Windows XP 32 bit. Exploitujeme HijackThisInformační hodnota logu aplikace Hijackthis je založena na dvou sekcích. Výpis aktuálně běžících procesů a položek po spuštění + nějaké další informace. Prvním úkol tedy bude odstranit náš proces ze seznamu běžících procesů z logu a druhý úkol bude odstranit naši položku po spuštění. Hijackthis - ProcesHJT hojně využívá standardních high level API pro práci s procesy, CreateToolhelp32Snapshot, Process32First a Process32Next. V seznamu procesů je zobrazena celá cesta spustitelného souboru, kterou si obstará voláním funkce z psapi.dll, konkrétně GetModuleFileNameExA. GetModuleFileNameEx funguje velice jednoduše, pomocí NtQueryInformationProcess zjistí, kde se nachazí PEB a z něj pak pomocí ReadProcessMemory prochází pole spojáků načtených modulů. Nutno připomenout, že struktura PEB je přepisovatelná a není problém cokoliv, včetně členů onoho spojáku s načtenými moduly, změnit, přepsat a přetvořit k obrazu svému. PEB -> (ptr PEB +0x00c Ldr) PEB_LDR_DATA PEB_LDR_DATA: Všechny tři seznamy, tedy InLoadOrder, InMemoryOrder, InInitializationOrder jsou struktury typu LIST_ENTRY, tzn. blink & flink na struktury LDR_DATA_TABLE_ENTRY. Tato struktura obsahuje členy, jako UNICODE_STRING FullDllName,UNICODE_STRING BaseDllName a PVOID DllBase. GetModuleFileNameEx prochází spojáky v InLoadOrder, takže stačí změnit záznam pouze tam. Jelikož je exe soubor načítán PE loaderem jako první, je ve spojáku InLoadOrder uveden vždy jako první. ;:: HIDE PROCESS :::::::::::::::::::::::::::::::::::::
assume fs: nothing push fs: [30h] pop edi ;edi = ptr to PEB mov edi, dword ptr [edi+0Ch] ;ptr to LDR Funkce ReDoPath přepíše původní cestu a vytvoří cestu novou - v našem příkladě použijeme například cestu shodnout s programem svchost.exe. Výsledek je tedy takový, že GetModuleFileNameEx vrátí cestu k svchost.exe. Hijackthis - StartupDalším úkolem je spouštění po startu a skrytí této činnosti před Hijackthis. Hijackthis hlídá snad všechny klíče a adresáře pro automatické spouštění, ale obsahuje pro nás velmi dobře využitelnou "chybičku". Výpis služeb je hnán přes filtr, který má za úkol vyfiltrovat služby Microsoftu a to velice nešťastným způsobem - pomocí funkce InStr a uvedeného výrobce souboru. V praxi to vypadá tak, že pokud je v uvedeném výrobci souboru obsažen řetězec "Microsoft" (tedy např. i "NotAMicrosoftCorp"), je splněna podmínka pro filtraci a služba nebude do logu vypsána. Tato část je snad nejjednodušší, stačí přidat adekvátní resource, nebo upravit informace v IDE. Hijackthis - shrnutíV této chvíli máme program, který se spouští po startu, v logu Hijackthis není vidět. Projevuje se jako další z svchostů, resp. jakéhokoliv jiného programu, který si vybereme (nutně to nemusí být ani platná cesta). Exploitujeme ComboFixPůvodně jsem chtěl použít k popisu mých pocítů z Combofixu i citoslovce, ale raději půjdeme hned k věci. Combofix ohrožuje naši neviditelnost pomocí několika kontrol, nemůžeme si dovolit, aby o nás byla v logu jakákoliv zmíňka . První hrozbou je výpis souborů vytvořených za posledních x dní. Další hrozbou je výpis položek po spuštění, včetně výpisu všech služeb, na jejíž bázi náš program běží a konečně poslední hrozba - kontrola nově vytvořených služeb. Combofix - výpis souborůJako snad vše v tomto dokumentu je i způsob obejití této kontroly triviální. Prostě a jednoduše si všechny časy (poslední úpravy, čas vytvoření, atd.) nakopírujeme z některého systémového soubor, např. kernel32.dll a tyto informace pak nastavit našemu souboru. Vše zvládneme pomocí API z kernel32.dll (CreateFile, GetFileTime a SetFileTime). Combofix netestuje logičnost TimeDateStamp v NT Headeru (jak by mohl mít soubor, který byl kompilován v roce 2008 nastavený datum posledních úprav na rok 2004?! :)), čímž nám ulehčuje práci asi o 12 řádků kódu. Combofix - výpis služebCombofix, resp. část určená za výpis služeb tyto služby prohání přes svůj whitelist, který je založen pouze na jménech služeb. Whitelist, tedy seznam všech jmen služeb, které nebudou do logu vloženy jsou uloženy v nešifrovaném textovém souboru (žádné hashe, žádné katalogy, žádné digitální podpisy a nic, co by nás jakkoliv mohlo označit za podvodníky). Tento soubor si stačí vypůjčit a v našem kousku se pokoušet vytvářet novou službu tak dlouho, dokud nenarazíme na nějakou volnou. V přkladu jsem zvolil stálé jméno. Combofix - výpis nových služebBez dalšího studování Combofixu jsem se vrhl do psaní funkce na změnu času vytvoření klíče v registru. Po nezdaru jsem si všiml, že Windows po přidání nové služby po prvním restartu přidávají do klíče Services\enum\root\LEGACY_jméno_služby hodnotu se jménem "*NewlyCreated*" a tu Combofix kontroluje. Po startu naší apliakce je tedy nutno tuto hodnotu smazat. Tato hodnota je však v klíči, ke kterému nemá uživatel zapisovací práva, ale ty si přidělíme sami, takže žádný strach. Shrnutí detekcePokud provedeme všechny zmíněné kroky, máme program, který se spouští po startu, v Hijackthis se projeví jen jako další z běžících svchostů a v Combofixu se neprojeví vůbec. Proof Of ConceptNyní si popíšeme chování tohoto kousku. Máme několik stavů, první stav je, kdy uživatel dostane do rukou náš soubor - ten je potřeba nainstalovat - tedy zavést službu, změnit datumy, atd. Další stav je, kdy je program spuštěn jako služba. Jako služba máme život trochu obtížnější, hlavně práci s okny, user interface, atp. Z tohoto a mnoha dalších důvodů jsem se rozhodl, že bude vhodné spustit sám sebe znovu s parametrem pod tokenem uživatele a službu ukončit. Třetí stav, kdy je program spuštěn s parametrem je stav konečný, nejedná se ani o instalaci ani o službu... Je čas se skrýt a zobrazit uživateli, že jsme stále zde. # Zjistíme, kde se aktuálně nacházíme, pokud se nenacházíme v system32, jde o první spuštění, tedy o instalaci: 1) Instalace # Nejsme spuštěni s parametrem "go"? 3) Jsme v konečném akčním stavu Zdrojový kódInstalace ;-- PATH CHECK -------------------------------------------
invoke GetSystemDirectory, addr dbPath, sizeof dbPath invoke lstrcat, addr dbPath, addr szMY_NAME invoke GetModuleFileName, 0, addr dbBuffer, sizeof dbBuffer ; 2. modify file times invoke GetModuleFileName, eax, ecx, sizeof dbBuffer ;- set creation date, ... - ; 3. create service ; 4. run new file Služba / akce? ;-- TO BE A SERVICE OR NOT TO BE A SERVICE... -------------
Invoke GetCommandLine mov esi, EAX Invoke lstrlen, esi Add esi, EAX .IF word ptr[esi-2] != "og" lea esi, tSTE assume esi: ptr SERVICE_TABLE_ENTRY invoke RtlZeroMemory, esi, sizeof SERVICE_TABLE_ENTRY * 2 mov [esi].lpServiceName, offset szSVC_NAME mov [esi].lpServiceProc, offset ServiceMain Invoke StartServiceCtrlDispatcher, esi assume esi: nothing Invoke ExitProcess, 0 .ENDIF Jsme služba ServiceMain proc uses esi edi argA:DWORD, argB:DWORD
local hProc: HANDLE local hToken: HANDLE local hDupToken: HANDLE ;-- SERVICE STUFF ---------------------------------------- lea esi, tServiceStatus mov [esi].dwCurrentState, SERVICE_RUNNING ;-- RELOAD US TO NORMAL PROC. & STOP -------------------- invoke GetModuleFileName, 0, addr dbBuffer, sizeof dbBuffer Invoke CloseHandle, hDupToken mov tServiceStatus.dwCurrentState, SERVICE_STOP_PENDING Nejsme služba - schovat! ;-- NOT A SERVICE =)) LETS HIDE! --------------------------
invoke SetNamedSecurityInfo, addr szSVC_CFX, 4, DACL_SECURITY_INFORMATION, 0, 0, 0, 0 .IF !EAX lea esi, szSVC_CFX Add esi, 8 invoke RegOpenKey, HKEY_LOCAL_MACHINE, esi, addr hKey ;:: INIT ::::::::::::::::::::::::::::::::::::: mov sNEW_NAMEA.dwLength, ax push 1 ;:: HIDE PROCESS ::::::::::::::::::::::::::::::::::::: mov edi, dword ptr [edi+0Ch] ;ptr to LDR invoke MessageBox, 0, addr szRUNNING, addr szCAPTION,MB_ICONQUESTION or MB_SERVICE_NOTIFICATION DownloadBinárka k otestování: Kompletní zdrojový kód v MASMu je stažitelný zde: Odpovědět |
OdkazyOdkazy |