Vectored Overloading PE Injection

Tip

Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Ucz się i ćwicz Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Wsparcie dla HackTricks

Przegląd techniki

Vectored Overloading to Windows PE injection primitive, które łączy klasyczny Module Overloading z Vectored Exception Handlers (VEHs) i hardware breakpoints. Zamiast patchować LoadLibrary lub pisać własny loader, adversary:

  1. Tworzy sekcję SEC_IMAGE opartą na legalnym DLL (np. wmp.dll).
  2. Nadpisuje zmapowany widok w pełni zrelokowanym złośliwym PE, ale utrzymuje obiekt sekcji wskazujący na benign obraz na dysku.
  3. Rejestruje VEH i programuje rejestry debugowania tak, aby każde wywołanie NtOpenSection, NtMapViewOfSection, i opcjonalnie NtClose podnosiło user-mode breakpoint.
  4. Wywołuje LoadLibrary("amsi.dll") (lub dowolny inny benign target). Kiedy Windows loader wywołuje te syscall’e, VEH pomija przejście do jądra i zwraca uchwyty oraz base addresses przygotowanego złośliwego obrazu.

Ponieważ loader nadal uważa, że zmapował żądany DLL, narzędzia patrzące jedynie na pliki backing section widzą wmp.dll, nawet jeśli pamięć zawiera teraz payload adversary. Tymczasem imports/TLS callbacks są nadal rozwiązywane przez prawdziwy loader, co znacząco zmniejsza ilość własnej logiki parsującej PE, którą adversary musi utrzymywać.

Etap 1 – Build the disguised section

  1. Create and map a section for the decoy DLL
NtCreateSection(&DecoySection, SECTION_ALL_ACCESS, NULL,
0, PAGE_READWRITE, SEC_IMAGE, L"\??\C:\\Windows\\System32\\wmp.dll");
NtMapViewOfSection(DecoySection, GetCurrentProcess(), &DecoyView, 0, 0,
NULL, &DecoySize, ViewShare, 0, PAGE_READWRITE);
  1. Skopiuj złośliwy PE do tego widoku sekcja po sekcji, respektując SizeOfRawData/VirtualSize i aktualizując ochrony później (PAGE_EXECUTE_READ, PAGE_READWRITE, itd.).
  2. Zastosuj relocacje i rozwiąż importy dokładnie tak, jak zrobiłby to reflective loader. Ponieważ widok jest już zmapowany jako SEC_IMAGE, wyrównania sekcji i guard pages odpowiadają temu, czego spodziewa się Windows loader.
  3. Normalizuj nagłówek PE:
  • Jeśli payload jest EXE, ustaw IMAGE_FILE_HEADER.Characteristics |= IMAGE_FILE_DLL i wyzeruj entry point, aby powstrzymać LdrpCallTlsInitializers przed skokiem do stubów specyficznych dla EXE.
  • DLL payloady mogą pozostawić nagłówki bez zmian.

W tym momencie proces posiada widok z możliwością RWX, którego backing object to nadal wmp.dll, a jednak bajty w pamięci są kontrolowane przez adversary.

Etap 2 – Hijack the loader with VEHs

  1. Zarejestruj VEH i uzbraj hardware breakpoints: zaprogramuj Dr0 (lub inny rejestr debugowania) adresem ntdll!NtOpenSection i ustaw DR7, tak by każde wykonanie zgłaszało STATUS_SINGLE_STEP. Powtórz później dla NtMapViewOfSection i opcjonalnie NtClose.
  2. Wywołaj ładowanie DLL przez LoadLibrary("amsi.dll"). LdrLoadDll ostatecznie wywoła NtOpenSection, aby uzyskać realny section handle.
  3. VEH hook dla NtOpenSection:
  • Znajdź slot na stosie odpowiadający argumentowi [out] PHANDLE SectionHandle.
  • Zapisz wcześniej utworzony uchwyt DecoySection do tego slotu.
  • Przesuń RIP/EIP do instrukcji ret, aby nigdy nie wywoływać jądra.
  • Ponownie uzbrój hardware breakpoint, aby obserwować NtMapViewOfSection następnie.
  1. VEH hook dla NtMapViewOfSection:
  • Nadpisz [out] PVOID *BaseAddress (i pola rozmiaru/ochrony) adresem już zmapowanego złośliwego widoku.
  • Pomiń ciało syscall tak jak wcześniej.
  1. (Opcjonalne) VEH hook dla NtClose weryfikuje, że fałszywy section handle jest czyszczony, zapobiegając resource leaks i dostarczając ostatecznego sanity check.

Ponieważ syscall’e nigdy nie są wykonywane, kernel callbacks (ETWti, minifilter, itd.) nie obserwują podejrzanych zdarzeń NtOpenSection/NtMapViewOfSection, co drastycznie obniża telemetry. Z perspektywy loadera wszystko zakończyło się sukcesem i amsi.dll znajduje się w pamięci, więc kontynuuje rozwiązywanie importów/TLS względem bajtów adversary.

Etap 3 – Execute the payload

  • EXE payload: Injector po prostu skacze do oryginalnego entry point po wykonaniu relocations. Gdy loader uważa, że wywoła DllMain, custom code zamiast tego wykonuje entry w stylu EXE.
  • DLL payload / Node.js addon: Rozwiąż i wywołaj zamierzony export (Kidkadi udostępnia nazwaną funkcję do JavaScript). Ponieważ moduł jest już zarejestrowany w LdrpModuleBaseAddressIndex, kolejne wyszukiwania widzą go jako benign DLL.

Po połączeniu z Node.js native addon (.node file), całe ciężkie operacje związane z Windows-internals pozostają poza warstwą JavaScript, co pomaga threat actorowi dostarczyć ten sam loader z wieloma różnymi obfuskowanymi Node wrapperami.

Referencje

Tip

Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Ucz się i ćwicz Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Wsparcie dla HackTricks