Wspólne API używane w Malware

Reading time: 8 minutes

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

Ogólne

Sieci

Raw SocketsWinAPI Sockets
socket()WSAStratup()
bind()bind()
listen()listen()
accept()accept()
connect()connect()
read()/recv()recv()
write()send()
shutdown()WSACleanup()

TLS pinning and chunked transport

Wiele loaderów owija swój strumień TCP w SslStream i pin'uje certyfikat końcowy serwera względem osadzonej kopii (certificate pinning). Informacje/zadania bota są kompresowane (np. GZip). Gdy odpowiedzi przekraczają pewien próg (~1 MB), dane są fragmentowane na małe kawałki (np. segmenty po 16 KB), aby uniknąć heurystyk opartych na rozmiarze i zmniejszyć skoki pamięci podczas deserializacji.

Utrwalanie

RegistryFileService
RegCreateKeyEx()GetTempPath()OpenSCManager
RegOpenKeyEx()CopyFile()CreateService()
RegSetValueEx()CreateFile()StartServiceCtrlDispatcher()
RegDeleteKeyEx()WriteFile()
RegGetValue()ReadFile()

Szyfrowanie

Name
WinCrypt
CryptAcquireContext()
CryptGenKey()
CryptDeriveKey()
CryptDecrypt()
CryptReleaseContext()

Anti-Analysis/VM

Function NameAssembly Instructions
IsDebuggerPresent()CPUID()
GetSystemInfo()IN()
GlobalMemoryStatusEx()
GetVersion()
CreateToolhelp32Snapshot [Check if a process is running]
CreateFileW/A [Check if a file exist]

Kontrola wykonania oparta na locale/układzie klawiatury

Wiele stealersów/loaderów przerywa działanie przy określonych lokalizacjach, aby unikać badaczy i spełnić ograniczenia operatorów zagrożeń. Typowe sprawdzenia:

  • GetKeyboardLayout do enumeracji zainstalowanych układów (per-thread/user)
  • GetLocaleInfoA/W do ustalenia kodów kraju/regionu
  • GetSystemDefaultLangID / GetUserDefaultLangID

Jeśli którykolwiek pasuje do zablokowanej listy (często kraje CIS), loader kończy działanie natychmiast przed pojawieniem się sieciowych IOCów lub injection.

Obrona/polowanie

  • Zaznacz procesy, które wczesnie wywołują wiele API związanych z locale/układem klawiatury, a następnie kończą działanie bez widocznej aktywności.
  • Koreluj z checkami anty-VM (napisy BIOS, urządzenia PnP, model dysku, usługi) reuse’owanymi z projektów open-source (np. VMDetector), by wykryć gated execution.

Emulator API fingerprinting & sleep evasion

Malware często fingerprintuje emulatory sandboxów, szukając w procesie eksportów związanych z Defenderem (obserwowane w Malware Protection Emulator). Jeśli którykolwiek z tych symboli jest obecny (skanowanie bez uwzględniania wielkości liter), wykonanie jest opóźniane o 10–30 minut i sprawdzane ponownie, co marnuje czas analizy.

Przykłady nazw API używanych jako canary:

  • MpVmp32Entry, MpVmp32FastEnter, MpCallPreEntryPointCode, MpCallPostEntryPointCode, MpFinalize, MpReportEvent*, MpSwitchToNextThread*
  • rodzina VFS_*: VFS_Open, VFS_Read, VFS_MapViewOfFile, VFS_UnmapViewOfFile, VFS_FindFirstFile/FindNextFile, VFS_CopyFile, VFS_DeleteFile, VFS_MoveFile
  • ThrdMgr_*: ThrdMgr_GetCurrentThreadHandle, ThrdMgr_SaveTEB, ThrdMgr_SwitchThreads

Typical delay primitive (user-land):

cmd
cmd /c timeout /t %RANDOM_IN_[600,1800]% > nul

Weryfikacja argumentów

  • Operatorzy czasami wymagają obecności niewinnie wyglądającego przełącznika CLI przed uruchomieniem payloadu (np. /i:--type=renderer aby naśladować procesy potomne Chromium). Jeśli przełącznik jest nieobecny, loader wychodzi natychmiast, utrudniając proste uruchomienie w sandboxie.

Ukrywanie

Name
VirtualAllocAlokowanie pamięci (packery)
VirtualProtectZmiana uprawnień pamięci (packer nadający sekcji uprawnienia do wykonania)
ReadProcessMemoryInjection do zewnętrznych procesów
WriteProcessMemoryA/WInjection do zewnętrznych procesów
NtWriteVirtualMemory
CreateRemoteThreadDLL/Process injection...
NtUnmapViewOfSection
QueueUserAPC
CreateProcessInternalA/W

Wykonanie

Function Name
CreateProcessA/W
ShellExecute
WinExec
ResumeThread
NtResumeThread

Różne

  • GetAsyncKeyState() -- Key logging
  • SetWindowsHookEx -- Key logging
  • GetForeGroundWindow -- Pobierz nazwę aktywnego okna (lub stronę z przeglądarki)
  • LoadLibrary() -- Import biblioteki
  • GetProcAddress() -- Import biblioteki
  • CreateToolhelp32Snapshot() -- Lista uruchomionych procesów
  • GetDC() -- Zrzut ekranu
  • BitBlt() -- Zrzut ekranu
  • InternetOpen(), InternetOpenUrl(), InternetReadFile(), InternetWriteFile() -- Dostęp do Internetu
  • FindResource(), LoadResource(), LockResource() -- Dostęp do zasobów pliku wykonywalnego

Malware Techniques

DLL Injection

Execute an arbitrary DLL inside another process

  1. Zlokalizuj proces, do którego wstrzykniesz złośliwy DLL: CreateToolhelp32Snapshot, Process32First, Process32Next
  2. Otwórz proces: GetModuleHandle, GetProcAddress, OpenProcess
  3. Zapisz ścieżkę do DLL-a wewnątrz procesu: VirtualAllocEx, WriteProcessMemory
  4. Utwórz w procesie wątek, który załaduje złośliwy DLL: CreateRemoteThread, LoadLibrary

Inne funkcje do użycia: NTCreateThreadEx, RtlCreateUserThread

Reflective DLL Injection

Load a malicious DLL without calling normal Windows API calls.
The DLL is mapped inside a process, it will resolve the import addresses, fix the relocations and call the DllMain function.

Thread Hijacking

Find a thread from a process and make it load a malicious DLL

  1. Znajdź docelowy wątek: CreateToolhelp32Snapshot, Thread32First, Thread32Next
  2. Otwórz wątek: OpenThread
  3. Zawieś wątek: SuspendThread
  4. Zapisz ścieżkę do złośliwego DLL-a wewnątrz procesu ofiary: VirtualAllocEx, WriteProcessMemory
  5. Wznów wątek, aby załadował bibliotekę: ResumeThread

PE Injection

Portable Execution Injection: Plik wykonywalny zostanie zapisany w pamięci procesu ofiary i wykonany stamtąd.

Process Hollowing (a.k.a RunPE)

Process Hollowing jest jednym z ulubionych trików z kategorii defence-evasion / execution używanych przez malware dla Windows. Pomysł polega na uruchomieniu legalnego procesu w stanie suspended, usunięciu (wyczyszczeniu) jego oryginalnego obrazu z pamięci i wstawieniu w jego miejsce dowolnego PE. Gdy główny wątek zostanie wznowiony, złośliwy punkt wejścia wykonuje się pod pozorem zaufanego binarium (często podpisanego przez Microsoft).

Typowy przebieg:

  1. Stwórz hosta (np. RegAsm.exe, rundll32.exe, msbuild.exe) w stanie suspended, tak aby nie wykonały się żadne instrukcje.
c
STARTUPINFOA  si = { sizeof(si) };
PROCESS_INFORMATION pi;
CreateProcessA("C:\\Windows\\Microsoft.NET\\Framework32\\v4.0.30319\\RegAsm.exe",
NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi);
  1. Wczytaj złośliwy payload do pamięci i sparsuj jego nagłówki PE, aby uzyskać SizeOfImage, sekcje i nowy EntryPoint.
  2. NtUnmapViewOfSection / ZwUnmapViewOfSection – odmapuj oryginalny base image zawieszonego procesu.
  3. VirtualAllocEx – zarezerwuj pamięć RWX o rozmiarze SizeOfImage wewnątrz procesu zdalnego.
  4. WriteProcessMemory – skopiuj najpierw Headers, następnie iteruj po sekcjach kopiując ich surowe dane.
  5. SetThreadContext – wprowadź poprawkę wartości EAX/RAX (RCX na x64) lub Rip w strukturze kontekstu tak, aby EIP wskazywał na EntryPoint payloadu.
  6. ResumeThread – wątek kontynuuje, wykonując kod dostarczony przez atakującego.

Minimalny proof-of-concept (x86) skeleton:

c
void RunPE(LPCSTR host, LPVOID payload, DWORD payloadSize){
// 1. create suspended process
STARTUPINFOA si = {sizeof(si)}; PROCESS_INFORMATION pi;
CreateProcessA(host, NULL,NULL,NULL,FALSE,CREATE_SUSPENDED,NULL,NULL,&si,&pi);

// 2. read remote PEB to get ImageBaseAddress
CONTEXT ctx; ctx.ContextFlags = CONTEXT_FULL;
GetThreadContext(pi.hThread,&ctx);
PVOID baseAddr;
ReadProcessMemory(pi.hProcess,(PVOID)(ctx.Ebx+8),&baseAddr,4,NULL);

// 3. unmap original image & allocate new region at same base
NtUnmapViewOfSection(pi.hProcess,baseAddr);
PVOID newBase = VirtualAllocEx(pi.hProcess,baseAddr,pHdr->OptionalHeader.SizeOfImage,
MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);
// 4-5. copy headers & sections …
// 6. write new image base into PEB and set Eip
WriteProcessMemory(pi.hProcess,(PVOID)(ctx.Ebx+8),&baseAddr,4,NULL);
ctx.Eax = (DWORD)(newBase) + pHdr->OptionalHeader.AddressOfEntryPoint;
SetThreadContext(pi.hThread,&ctx);
// 7. run!
ResumeThread(pi.hThread);
}

Practical notes observed in the DarkCloud Stealer campaign:

  • The loader picked RegAsm.exe (part of the .NET Framework) as host – a signed binary unlikely to draw attention.
  • The decrypted VB6 stealer (holographies.exe) is not dropped on disk; it only ever exists inside the hollowed process making static detection harder.
  • Sensitive strings (regexes, paths, Telegram credentials) are RC4-encrypted per-string and only decrypted at runtime, further complicating memory scanning.

Detection ideas:

  • Alert on CREATE_SUSPENDED processes that never create GUI/console windows before a memory region is allocated as RWX (rare for benign code).
  • Look for a call sequence NtUnmapViewOfSection ➜ VirtualAllocEx ➜ WriteProcessMemory across different processes.
  • Unusual use of trusted developer utilities as hollowing hosts, especially MSBuild.exe, RegAsm.exe, rundll32.exe, parented by short-lived loaders.
  • Hunt for msbuild.exe spawned from user-writable paths or without corresponding .sln/.proj context then making outbound connections (ATT&CK T1127.001 + T1055.012).

Common host processes and path resolution

  • MSBuild.exe is frequently chosen as a hollowing host to blend with developer tooling. Loaders often search architecture-appropriate locations:
  • C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe
  • C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe
  • C:\Windows\System32\MSBuild.exe
  • C:\Windows\SysWOW64\MSBuild.exe
  • Select the host matching the current payload/OS architecture before calling CreateProcess(..., CREATE_SUSPENDED, ...).

Hooking

  • The SSDT (System Service Descriptor Table) points to kernel functions (ntoskrnl.exe) or GUI driver (win32k.sys) so user processes can call these functions.
  • A rootkit may modify these pointer to addresses that he controls
  • IRP (I/O Request Packets) transmit pieces of data from one component to another. Almost everything in the kernel uses IRPs and each device object has its own function table that can be hooked: DKOM (Direct Kernel Object Manipulation)
  • The IAT (Import Address Table) is useful to resolve dependencies. It's possible to hook this table in order to hijack the code that will be called.
  • EAT (Export Address Table) Hooks. This hooks can be done from userland. The goal is to hook exported functions by DLLs.
  • Inline Hooks: This type are difficult to achieve. This involve modifying the code of the functions itself. Maybe by putting a jump at the beginning of this.

References

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