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
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.
Ogólne
Sieci
Raw Sockets | WinAPI 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
Registry | File | Service |
---|---|---|
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 Name | Assembly 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/regionuGetSystemDefaultLangID
/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 /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 | |
---|---|
VirtualAlloc | Alokowanie pamięci (packery) |
VirtualProtect | Zmiana uprawnień pamięci (packer nadający sekcji uprawnienia do wykonania) |
ReadProcessMemory | Injection do zewnętrznych procesów |
WriteProcessMemoryA/W | Injection do zewnętrznych procesów |
NtWriteVirtualMemory | |
CreateRemoteThread | DLL/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
- Zlokalizuj proces, do którego wstrzykniesz złośliwy DLL: CreateToolhelp32Snapshot, Process32First, Process32Next
- Otwórz proces: GetModuleHandle, GetProcAddress, OpenProcess
- Zapisz ścieżkę do DLL-a wewnątrz procesu: VirtualAllocEx, WriteProcessMemory
- 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
- Znajdź docelowy wątek: CreateToolhelp32Snapshot, Thread32First, Thread32Next
- Otwórz wątek: OpenThread
- Zawieś wątek: SuspendThread
- Zapisz ścieżkę do złośliwego DLL-a wewnątrz procesu ofiary: VirtualAllocEx, WriteProcessMemory
- 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:
- Stwórz hosta (np.
RegAsm.exe
,rundll32.exe
,msbuild.exe
) w stanie suspended, tak aby nie wykonały się żadne instrukcje.
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);
- Wczytaj złośliwy payload do pamięci i sparsuj jego nagłówki PE, aby uzyskać
SizeOfImage
, sekcje i nowyEntryPoint
. - NtUnmapViewOfSection / ZwUnmapViewOfSection – odmapuj oryginalny base image zawieszonego procesu.
- VirtualAllocEx – zarezerwuj pamięć RWX o rozmiarze
SizeOfImage
wewnątrz procesu zdalnego. - WriteProcessMemory – skopiuj najpierw
Headers
, następnie iteruj po sekcjach kopiując ich surowe dane. - SetThreadContext – wprowadź poprawkę wartości
EAX/RAX
(RCX
na x64) lubRip
w strukturze kontekstu tak, abyEIP
wskazywał naEntryPoint
payloadu. - ResumeThread – wątek kontynuuje, wykonując kod dostarczony przez atakującego.
Minimalny proof-of-concept (x86) skeleton:
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
- Unit42 – New Infection Chain and ConfuserEx-Based Obfuscation for DarkCloud Stealer
- Check Point Research – Under the Pure Curtain: From RAT to Builder to Coder
- Unit 42 – PhantomVAI Loader Delivers a Range of Infostealers
- MITRE ATT&CK – Trusted Developer Utilities Proxy Execution: MSBuild (T1127.001)
- VMDetector – virtualization checks (open-source)
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
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.