12 KiB
일반 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 /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
- 악성 DLL을 주입할 프로세스를 찾음: CreateToolhelp32Snapshot, Process32First, Process32Next
- 프로세스를 엶: GetModuleHandle, GetProcAddress, OpenProcess
- 프로세스 내부에 DLL 경로를 씀: VirtualAllocEx, WriteProcessMemory
- 악성 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
- 대상 스레드 찾기: CreateToolhelp32Snapshot, Thread32First, Thread32Next
- 스레드 열기: OpenThread
- 스레드 일시중지: SuspendThread
- 희생자 프로세스 내부에 악성 DLL 경로 기록: VirtualAllocEx, WriteProcessMemory
- 라이브러리를 로드하면서 스레드 재개: 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 서명됨)의 위장 하에 실행된다.
전형적인 작업 흐름:
- 무해한 호스트(예:
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);
- 악성 페이로드를 메모리로 읽어 PE 헤더를 파싱하여
SizeOfImage
, 섹션들 및 새로운EntryPoint
를 얻음. - NtUnmapViewOfSection / ZwUnmapViewOfSection – suspended된 프로세스의 원래 이미지 베이스를 언맵.
- VirtualAllocEx – 원격 프로세스 내부에
SizeOfImage
크기의 RWX 메모리를 예약. - WriteProcessMemory – 먼저
Headers
를 복사한 다음 섹션들을 순회하며 raw 데이터를 복사. - SetThreadContext – 컨텍스트 구조의
EAX/RAX
(x64
에서는RCX
) 또는Rip
값을 패치하여EIP
가 페이로드의EntryPoint
를 가리키도록 함. - 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
- Unit42 – New Infection Chain and ConfuserEx-Based Obfuscation for DarkCloud Stealer
- Check Point Research – Under the Pure Curtain: From RAT to Builder to Coder
{{#include ../banners/hacktricks-training.md}}