# Загальні API, що використовуються в Malware {{#include ../banners/hacktricks-training.md}} ## Загальні ### Мережеві | 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 Багато loader-ів обгортають свій TCP-потік у `SslStream` і pinують leaf certificate сервера проти вбудованої копії (certificate pinning). Інформація/завдання бота стискаються (наприклад, GZip). Коли відповіді перевищують поріг (~1 MB), дані фрагментуються на невеликі частини (наприклад, сегменти по 16 KB), щоб уникнути heuristics за розміром та зменшити стрибки використання пам'яті під час десеріалізації. ### Персистентність | Registry | File | Service | | ---------------- | ------------- | ---------------------------- | | RegCreateKeyEx() | GetTempPath() | OpenSCManager | | RegOpenKeyEx() | CopyFile() | CreateService() | | RegSetValueEx() | CreateFile() | StartServiceCtrlDispatcher() | | RegDeleteKeyEx() | WriteFile() | | | RegGetValue() | ReadFile() | | ### Шифрування | Name | | --------------------- | | WinCrypt | | CryptAcquireContext() | | CryptGenKey() | | CryptDeriveKey() | | CryptDecrypt() | | CryptReleaseContext() | ### Анти-аналіз/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] | | ### Emulator API fingerprinting & sleep evasion Malware часто фіксує fingerprinting sandbox-емуляторів, шукаючи Defender’s virtualised exports (помітні в Malware Protection Emulator). Якщо будь-який з цих символів присутній (регістро-нечутливе сканування процесу), виконання відкладають на 10–30 хвилин і перевіряють повторно, щоб марнувати час аналізу. Examples of API names used as canaries: - `MpVmp32Entry`, `MpVmp32FastEnter`, `MpCallPreEntryPointCode`, `MpCallPostEntryPointCode`, `MpFinalize`, `MpReportEvent*`, `MpSwitchToNextThread*` - `VFS_*` family: `VFS_Open`, `VFS_Read`, `VFS_MapViewOfFile`, `VFS_UnmapViewOfFile`, `VFS_FindFirstFile/FindNextFile`, `VFS_CopyFile`, `VFS_DeleteFile`, `VFS_MoveFile` - `ThrdMgr_*`: `ThrdMgr_GetCurrentThreadHandle`, `ThrdMgr_SaveTEB`, `ThrdMgr_SwitchThreads` Типовий примітив затримки (user-land): ```cmd cmd /c timeout /t %RANDOM_IN_[600,1800]% > nul ``` Перевірка аргументів - Іноді оператори вимагають присутності зовнішньо нешкідливого CLI-параметра перед виконанням payload (наприклад, `/i:--type=renderer` щоб імітувати Chromium child processes). Якщо параметр відсутній, loader негайно завершує роботу, ускладнюючи наївне виконання в sandbox. ### Прихованість | Назва | | | ----------------------- | -------------------------------------------------------------------------- | | VirtualAlloc | Виділення пам'яті (packers) | | VirtualProtect | Зміна прав доступу до пам'яті (packer, який дає виконувані права секції) | | ReadProcessMemory | Ін'єкція в зовнішні процеси | | WriteProcessMemoryA/W | Ін'єкція в зовнішні процеси | | NtWriteVirtualMemory | | | CreateRemoteThread | DLL/Process injection... | | NtUnmapViewOfSection | | | QueueUserAPC | | | CreateProcessInternalA/W| | ### Виконання | Назва функції | | --------------- | | CreateProcessA/W| | ShellExecute | | WinExec | | ResumeThread | | NtResumeThread | ### Різне - GetAsyncKeyState() -- Key logging - SetWindowsHookEx -- Key logging - GetForeGroundWindow -- Отримати назву активного вікна (або сайт з браузера) - LoadLibrary() -- Завантаження бібліотеки - GetProcAddress() -- Отримання адреси функції в бібліотеці - CreateToolhelp32Snapshot() -- Перелік запущених процесів - GetDC() -- Знімок екрана - BitBlt() -- Знімок екрана - InternetOpen(), InternetOpenUrl(), InternetReadFile(), InternetWriteFile() -- Доступ до Інтернету - FindResource(), LoadResource(), LockResource() -- Доступ до ресурсів виконуваного файлу ## Техніки Malware ### DLL Injection Execute an arbitrary DLL inside another process 1. Locate the process to inject the malicious DLL: CreateToolhelp32Snapshot, Process32First, Process32Next 2. Open the process: GetModuleHandle, GetProcAddress, OpenProcess 3. Write the path to the DLL inside the process: VirtualAllocEx, WriteProcessMemory 4. Create a thread in the process that will load the malicious DLL: CreateRemoteThread, LoadLibrary Other functions to use: 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. Find a target thread: CreateToolhelp32Snapshot, Thread32First, Thread32Next 2. Open the thread: OpenThread 3. Suspend the thread: SuspendThread 4. Write the path to the malicious DLL inside the victim process: VirtualAllocEx, WriteProcessMemory 5. Resume the thread loading the library: ResumeThread ### PE Injection Portable Execution Injection: The executable will be written in the memory of the victim process and it will be executed from there. ### Process Hollowing (a.k.a **RunPE**) `Process Hollowing` is one of the favourite **defence-evasion / execution** tricks used by Windows malware. The idea is to launch a *legitimate* process in the **suspended** state, remove (hollow) its original image from memory and copy an **arbitrary PE** in its place. When the primary thread is finally resumed the malicious entry-point executes under the guise of a trusted binary (often signed by Microsoft). Typical workflow: 1. Spawn a benign host (e.g. `RegAsm.exe`, `rundll32.exe`, `msbuild.exe`) **suspended** so that no instructions run yet. ```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); ``` 2. Read the malicious payload into memory and parse its PE headers to obtain `SizeOfImage`, sections and the new `EntryPoint`. 3. **NtUnmapViewOfSection** / **ZwUnmapViewOfSection** – unmap the original image base of the suspended process. 4. **VirtualAllocEx** – reserve RWX memory of `SizeOfImage` inside the remote process. 5. **WriteProcessMemory** – copy the `Headers` first, then iterate over sections copying their raw data. 6. **SetThreadContext** – patch the value of `EAX/RAX` (`RCX` on x64) or `Rip` in the context structure so that `EIP` points to the payload’s `EntryPoint`. 7. **ResumeThread** – the thread continues, executing the attacker-supplied code. Minimal 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); } ``` Практичні зауваження, виявлені в кампанії **DarkCloud Stealer**: * Лоадер вибрав `RegAsm.exe` (частина .NET Framework) як хост — підписаний бінарний файл, який навряд чи приверне увагу. * Розшифрований VB6 stealer (`holographies.exe`) *не* скидається на диск; він існує лише всередині hollowed process, що ускладнює static detection. * Чутливі рядки (regexes, paths, Telegram credentials) є **RC4-encrypted** для кожного рядка й дешифруються лише під час виконання, що додатково ускладнює memory scanning. Ідеї для виявлення: * Генерувати алерт для процесів з `CREATE_SUSPENDED`, які не створюють GUI/console вікна до того, як ділянка пам'яті буде відведена як **RWX** (рідко для легітимного коду). * Шукати послідовність викликів `NtUnmapViewOfSection ➜ VirtualAllocEx ➜ WriteProcessMemory` між різними процесами. ## Hooking - The **SSDT** (**System Service Descriptor Table**) вказує на kernel functions (ntoskrnl.exe) або GUI driver (win32k.sys), тому користувацькі процеси можуть викликати ці функції. - A rootkit може змінювати ці вказівники на адреси, які він контролює. - **IRP** (**I/O Request Packets**) передають фрагменти даних між компонентами. Майже все в ядрі використовує IRP, і кожний device object має власну таблицю функцій, яку можна перехопити: DKOM (Direct Kernel Object Manipulation) - The **IAT** (**Import Address Table**) корисна для розв'язання залежностей. Можна hookнути цю таблицю, щоб перехопити код, який буде викликаний. - **EAT** (**Export Address Table**) Hooks. Ці хук-и можна виконувати з **userland**. Мета — hookнути exported functions від DLLs. - **Inline Hooks**: цей тип важко реалізувати. Він передбачає модифікацію коду самих функцій — наприклад шляхом вставки jump на початку функції. ## Посилання - [Unit42 – New Infection Chain and ConfuserEx-Based Obfuscation for DarkCloud Stealer](https://unit42.paloaltonetworks.com/new-darkcloud-stealer-infection-chain/) - [Check Point Research – Under the Pure Curtain: From RAT to Builder to Coder](https://research.checkpoint.com/2025/under-the-pure-curtain-from-rat-to-builder-to-coder/) {{#include ../banners/hacktricks-training.md}}