hacktricks/src/reversing/common-api-used-in-malware.md

12 KiB
Raw Blame History

Загальні API, що використовуються в шкідливому ПЗ

{{#include ../banners/hacktricks-training.md}}

Загальні

Мережа

Сирі сокети WinAPI сокети
socket() WSAStratup()
bind() bind()
listen() listen()
accept() accept()
connect() connect()
read()/recv() recv()
write() send()
shutdown() WSACleanup()

Постійність

Реєстр Файл Служба
RegCreateKeyEx() GetTempPath() OpenSCManager
RegOpenKeyEx() CopyFile() CreateService()
RegSetValueEx() CreateFile() StartServiceCtrlDispatcher()
RegDeleteKeyEx() WriteFile()
RegGetValue() ReadFile()

Шифрування

Назва
WinCrypt
CryptAcquireContext()
CryptGenKey()
CryptDeriveKey()
CryptDecrypt()
CryptReleaseContext()

Анти-аналіз/VM

Назва функції Інструкції асемблера
IsDebuggerPresent() CPUID()
GetSystemInfo() IN()
GlobalMemoryStatusEx()
GetVersion()
CreateToolhelp32Snapshot [Перевірка, чи запущено процес]
CreateFileW/A [Перевірка, чи існує файл]

Схованість

Назва
VirtualAlloc Виділення пам'яті (пакувальники)
VirtualProtect Зміна дозволів пам'яті (пакувальник надає дозвіл на виконання секції)
ReadProcessMemory Ін'єкція в зовнішні процеси
WriteProcessMemoryA/W Ін'єкція в зовнішні процеси
NtWriteVirtualMemory
CreateRemoteThread Ін'єкція DLL/процесу...
NtUnmapViewOfSection
QueueUserAPC
CreateProcessInternalA/W

Виконання

Назва функції
CreateProcessA/W
ShellExecute
WinExec
ResumeThread
NtResumeThread

Різне

  • GetAsyncKeyState() -- Логування клавіш
  • SetWindowsHookEx -- Логування клавіш
  • GetForeGroundWindow -- Отримати назву активного вікна (або вебсайту з браузера)
  • LoadLibrary() -- Імпорт бібліотеки
  • GetProcAddress() -- Імпорт бібліотеки
  • CreateToolhelp32Snapshot() -- Список запущених процесів
  • GetDC() -- Скриншот
  • BitBlt() -- Скриншот
  • InternetOpen(), InternetOpenUrl(), InternetReadFile(), InternetWriteFile() -- Доступ до Інтернету
  • FindResource(), LoadResource(), LockResource() -- Доступ до ресурсів виконуваного файлу

Техніки шкідливого ПЗ

Ін'єкція DLL

Виконати довільну DLL всередині іншого процесу

  1. Знайти процес для ін'єкції шкідливої DLL: CreateToolhelp32Snapshot, Process32First, Process32Next
  2. Відкрити процес: GetModuleHandle, GetProcAddress, OpenProcess
  3. Записати шлях до DLL всередині процесу: VirtualAllocEx, WriteProcessMemory
  4. Створити потік у процесі, який завантажить шкідливу DLL: CreateRemoteThread, LoadLibrary

Інші функції для використання: NTCreateThreadEx, RtlCreateUserThread

Відображувана ін'єкція DLL

Завантажити шкідливу DLL без виклику звичайних API Windows.
DLL відображається всередині процесу, вона вирішить адреси імпорту, виправить переміщення та викличе функцію DllMain.

Захоплення потоку

Знайти потік з процесу та змусити його завантажити шкідливу DLL

  1. Знайти цільовий потік: CreateToolhelp32Snapshot, Thread32First, Thread32Next
  2. Відкрити потік: OpenThread
  3. Призупинити потік: SuspendThread
  4. Записати шлях до шкідливої DLL всередині процесу жертви: VirtualAllocEx, WriteProcessMemory
  5. Відновити потік, що завантажує бібліотеку: ResumeThread

Ін'єкція PE

Ін'єкція Portable Execution: Виконуваний файл буде записаний у пам'яті процесу жертви і буде виконуватися звідти.

Порожнє процесу (також відоме як RunPE)

Process Hollowing є одним з улюблених трюків обходу захисту / виконання, що використовуються шкідливим ПЗ для Windows. Ідея полягає в тому, щоб запустити легітимний процес у призупиненому стані, видалити (порожнє) його оригінальне зображення з пам'яті та скопіювати довільний PE на його місце. Коли первинний потік нарешті відновлюється, шкідливий вхідний пункт виконується під виглядом довіреного бінарного файлу (часто підписаного Microsoft).

Типовий робочий процес:

  1. Запустити доброзичливий хост (наприклад, RegAsm.exe, rundll32.exe, msbuild.exe) призупиненим, щоб жодні інструкції ще не виконувалися.
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. Прочитати шкідливий вантаж у пам'ять і розібрати його PE заголовки, щоб отримати SizeOfImage, секції та новий EntryPoint.
  2. NtUnmapViewOfSection / ZwUnmapViewOfSection зняти відображення оригінальної бази зображення призупиненого процесу.
  3. VirtualAllocEx зарезервувати RWX пам'ять SizeOfImage всередині віддаленого процесу.
  4. WriteProcessMemory спочатку скопіювати Headers, а потім пройтися по секціях, копіюючи їх сирі дані.
  5. SetThreadContext виправити значення EAX/RAX (RCX на x64) або Rip у структурі контексту, щоб EIP вказував на EntryPoint вантажу.
  6. ResumeThread потік продовжує виконання, виконуючи код, наданий атакуючим.

Мінімальний доказ концепції (x86) скелет:

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 крадій (holographies.exe) не скидається на диск; він існує лише всередині порожнього процесу, що ускладнює статичне виявлення.
  • Чутливі рядки (regex, шляхи, облікові дані Telegram) RC4-зашифровані для кожного рядка і розшифровуються лише під час виконання, що ще більше ускладнює сканування пам'яті.

Ідеї для виявлення:

  • Сповіщати про процеси CREATE_SUSPENDED, які ніколи не створюють GUI/консольні вікна перед тим, як область пам'яті буде виділена як RWX (рідко для доброчинного коду).
  • Шукати послідовність викликів NtUnmapViewOfSection ➜ VirtualAllocEx ➜ WriteProcessMemory в різних процесах.

Хукінг

  • SSDT (System Service Descriptor Table) вказує на функції ядра (ntoskrnl.exe) або драйвера GUI (win32k.sys), щоб користувацькі процеси могли викликати ці функції.
  • Руткіт може змінювати ці вказівники на адреси, які він контролює.
  • IRP (I/O Request Packets) передають частини даних з одного компонента в інший. Практично все в ядрі використовує IRP, і кожен об'єкт пристрою має свою власну таблицю функцій, яку можна підключити: DKOM (Direct Kernel Object Manipulation).
  • IAT (Import Address Table) корисний для вирішення залежностей. Можливо підключити цю таблицю, щоб перехопити код, який буде викликаний.
  • EAT (Export Address Table) Хуки. Ці хуки можна робити з userland. Мета полягає в тому, щоб підключити експортовані функції DLL.
  • Inline Hooks: Цей тип важко досягти. Це передбачає модифікацію коду самих функцій. Можливо, шляхом вставлення стрибка на початку цього.

Посилання

{{#include ../banners/hacktricks-training.md}}