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

12 KiB
Raw Blame History

일반 API (Common API used in 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

많은 로더는 TCP 스트림을 SslStream으로 감싸고 서버의 leaf certificate를 임베디드 복사본에 대해 고정합니다 (certificate pinning). 봇 정보/작업은 압축됩니다(예: GZip). 응답 크기가 임계값(약 1 MB)을 초과하면, 데이터는 크기 기반 휴리스틱을 회피하고 역직렬화 중 메모리 스파이크를 줄이기 위해 작은 청크(예: 16 KB 세그먼트)로 분할됩니다.

영속성 (Persistence)

레지스트리 (Registry) 파일 (File) 서비스 (Service)
RegCreateKeyEx() GetTempPath() OpenSCManager
RegOpenKeyEx() CopyFile() CreateService()
RegSetValueEx() CreateFile() StartServiceCtrlDispatcher()
RegDeleteKeyEx() WriteFile()
RegGetValue() ReadFile()

암호화 (Encryption)

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

안티-분석/VM (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]

에뮬레이터 API 지문화 및 슬립 회피 (Emulator API fingerprinting & sleep evasion)

Malware는 종종 Defender의 virtualised exports(예: Malware Protection Emulator에서 관찰되는)를 검색하여 샌드박스 에뮬레이터를 지문화합니다. 프로세스에서 이러한 심볼이 존재하면(대소문자 구분 없는 스캔) 실행을 1030분 지연시키고 재확인하여 분석 시간을 소모시킵니다.

카나리로 사용되는 API 이름 예시:

  • 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 /c timeout /t %RANDOM_IN_[600,1800]% > nul

인자 게이트키핑

  • 운영자들은 페이로드 실행 전에 무해해 보이는 CLI 스위치의 존재를 요구하는 경우가 있다(예: Chromium 자식 프로세스를 흉내내기 위한 /i:--type=renderer). 스위치가 없으면 loader가 즉시 종료되어 단순한 sandbox 실행을 방해한다.

Stealth

이름
VirtualAlloc 메모리 할당 (packers)
VirtualProtect 메모리 권한 변경 (section에 실행 권한을 부여하는 packer)
ReadProcessMemory 외부 프로세스에 대한 주입
WriteProcessMemoryA/W 외부 프로세스에 대한 주입
NtWriteVirtualMemory
CreateRemoteThread DLL/Process injection...
NtUnmapViewOfSection
QueueUserAPC
CreateProcessInternalA/W

Execution

함수 이름
CreateProcessA/W
ShellExecute
WinExec
ResumeThread
NtResumeThread

Miscellaneous

  • GetAsyncKeyState() -- 키로깅
  • SetWindowsHookEx -- 키로깅
  • GetForeGroundWindow -- 실행 중인 창 이름 가져오기 (또는 브라우저의 웹사이트)
  • LoadLibrary() -- 라이브러리 로드
  • GetProcAddress() -- 함수 주소 조회
  • CreateToolhelp32Snapshot() -- 실행 중인 프로세스 나열
  • GetDC() -- 화면 캡처
  • BitBlt() -- 화면 캡처
  • InternetOpen(), InternetOpenUrl(), InternetReadFile(), InternetWriteFile() -- 인터넷 접근
  • FindResource(), LoadResource(), LockResource() -- 실행 파일의 리소스 접근

Malware Techniques

DLL Injection

Execute an arbitrary DLL inside another process

  1. 악성 DLL을 주입할 프로세스를 찾음: CreateToolhelp32Snapshot, Process32First, Process32Next
  2. 프로세스를 엶: GetModuleHandle, GetProcAddress, OpenProcess
  3. 프로세스 내부에 DLL 경로를 씀: VirtualAllocEx, WriteProcessMemory
  4. 악성 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. 대상 스레드 찾기: CreateToolhelp32Snapshot, Thread32First, Thread32Next
  2. 스레드 열기: OpenThread
  3. 스레드 일시중지: SuspendThread
  4. 희생자 프로세스 내부에 악성 DLL 경로 기록: VirtualAllocEx, WriteProcessMemory
  5. 라이브러리를 로드하면서 스레드 재개: 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은 Windows 악성코드가 사용하는 대표적인 defence-evasion / execution 트릭 중 하나이다. 아이디어는 정상적인 프로세스를 suspended 상태로 실행한 뒤, 메모리에서 원래 이미지를 제거(hollow)하고 그 자리에 임의의 PE를 복사하는 것이다. 기본 스레드가 재개되면 악성 엔트리 포인트가 신뢰된 바이너리(종종 Microsoft 서명됨)의 위장 하에 실행된다.

전형적인 작업 흐름:

  1. 무해한 호스트(예: RegAsm.exe, rundll32.exe, msbuild.exe)를 아무 명령도 실행되지 않도록 suspended 상태로 생성.
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 suspended된 프로세스의 원래 이미지 베이스를 언맵.
  3. VirtualAllocEx 원격 프로세스 내부에 SizeOfImage 크기의 RWX 메모리를 예약.
  4. WriteProcessMemory 먼저 Headers를 복사한 다음 섹션들을 순회하며 raw 데이터를 복사.
  5. SetThreadContext 컨텍스트 구조의 EAX/RAX (x64에서는 RCX) 또는 Rip 값을 패치하여 EIP가 페이로드의 EntryPoint를 가리키도록 함.
  6. ResumeThread 스레드가 계속 실행되어 공격자가 제공한 코드를 실행함.

최소 PoC (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 (part of the .NET Framework)를 호스트로 선택 — 서명된 바이너리로 눈에 띄기 어려움.
  • 복호화된 VB6 stealer (holographies.exe)는 디스크에 드롭되지 않음; hollowed 프로세스 내부에서만 존재하여 정적 탐지를 어렵게 함.
  • 민감한 문자열(regexes, paths, Telegram credentials)은 문자열별로 RC4-encrypted 되어 런타임에만 복호화되므로 메모리 스캔이 더 복잡해짐.

탐지 아이디어:

  • 메모리 영역이 RWX로 할당되기 전까지 GUI/콘솔 윈도우를 전혀 생성하지 않는 CREATE_SUSPENDED 프로세스에 대해 경보를 생성(정상 코드에서는 드문 동작).
  • 서로 다른 프로세스에서 NtUnmapViewOfSection ➜ VirtualAllocEx ➜ WriteProcessMemory 호출 시퀀스를 탐지.

Hooking

  • The SSDT (System Service Descriptor Table)는 커널 함수(ntoskrnl.exe) 또는 GUI 드라이버(win32k.sys)를 가리켜 사용자 프로세스가 해당 함수를 호출할 수 있게 합니다.
  • A rootkit은 이러한 포인터를 공격자가 제어하는 주소로 수정할 수 있습니다.
  • The IRP (I/O Request Packets)는 한 구성요소에서 다른 구성요소로 데이터를 전달합니다. 커널의 거의 모든 것은 IRP를 사용하며 각 디바이스 오브젝트는 훅될 수 있는 자체 함수 테이블을 가집니다: DKOM (Direct Kernel Object Manipulation)
  • The IAT (Import Address Table)는 종속성을 해결하는 데 유용합니다. 이 테이블을 훅하여 호출될 코드를 가로챌 수 있습니다.
  • EAT (Export Address Table) Hooks. 이러한 훅은 userland에서 수행할 수 있습니다. 목표는 DLL이 내보내는 함수를 훅하는 것입니다.
  • Inline Hooks: 이 유형은 달성하기 어렵습니다. 함수 코드 자체를 수정하는 것을 포함합니다. 예를 들어 함수 시작 부분에 점프를 삽입하는 방식이 있을 수 있습니다.

References

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