Chương 12: Các Kỹ Thuật Khởi Chạy Malware Bí Mật (Covert Malware Launching)


Tổng quan

Khi người dùng ngày càng tinh vi hơn (biết dùng Task Manager để xem tiến trình), malware cũng tiến hóa theo — tìm cách ẩn mình vào môi trường Windows bình thường để tránh bị phát hiện.

Covert launching techniques = các kỹ thuật giúp malware khởi chạy mà không bị người dùng hoặc hệ thống bảo mật phát hiện.


1. Launchers (Loader)

Launcher là loại malware chuyên dùng để thiết lập việc thực thi — ngay lập tức hoặc trong tương lai — cho chính nó hoặc một malware khác, một cách bí mật.

Cách hoạt động

  • Launcher thường chứa sẵn malware bên trong nó, phổ biến nhất là nhúng một file .exe hoặc .dll trong resource section của file thực thi.
  • Resource section bình thường chứa: icon, hình ảnh, menu, string — malware lợi dụng vùng này để ẩn payload.
  • Khi launcher chạy → giải nén/giải mã payload từ resource section → khởi chạy payload đó.

Dấu hiệu nhận biết khi phân tích

FindResource      ; tìm resource trong file
LoadResource      ; load resource vào bộ nhớ
SizeofResource    ; lấy kích thước resource

2. Process Injection

Process injection = kỹ thuật tiêm code vào một tiến trình đang chạy, khiến tiến trình đó vô tình thực thi code độc hại.

Mục đích

  • Che giấu hành vi độc hại (code chạy dưới danh nghĩa tiến trình hợp lệ)
  • Bypass host-based firewall và các cơ chế bảo mật theo tiến trình

Hai API nền tảng dùng trong hầu hết mọi kỹ thuật injection

VirtualAllocEx      ; cấp phát vùng nhớ trong tiến trình đích
WriteProcessMemory  ; ghi dữ liệu vào vùng nhớ vừa cấp phát

3. DLL Injection

Nguyên lý

Ép tiến trình nạn nhân tự load một DLL độc hại bằng cách gọi LoadLibrary trong context của tiến trình đó. Khi DLL được load, OS tự động gọi DllMain — hàm chứa toàn bộ code độc hại.

sequenceDiagram participant L as Launcher Malware participant OS as Windows OS participant V as iexplore.exe (Victim) participant D as Malicious DLL L->>OS: CreateToolhelp32Snapshot / Process32Next Note over L: Tìm PID của iexplore.exe L->>OS: OpenProcess(PID) OS-->>L: hProcess (handle) L->>V: VirtualAllocEx → cấp phát vùng nhớ L->>V: WriteProcessMemory → ghi tên DLL vào vùng nhớ L->>OS: GetProcAddress("LoadLibraryA") L->>V: CreateRemoteThread(hProcess, LoadLibraryA, pDLLName) V->>D: LoadLibrary → DllMain() được gọi tự động Note over D,V: DLL chạy trong context của iexplore.exe

Chuỗi API đặc trưng (trademark pattern)

// Bước 1: Lấy handle tiến trình nạn nhân
hVictimProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, victimProcessID);

// Bước 2: Cấp phát vùng nhớ trong tiến trình nạn nhân
pNameInVictimProcess = VirtualAllocEx(hVictimProcess, ..., sizeof(maliciousLibraryName), ...);

// Bước 3: Ghi tên DLL độc hại vào vùng nhớ đó
WriteProcessMemory(hVictimProcess, ..., maliciousLibraryName, sizeof(maliciousLibraryName), ...);

// Bước 4: Lấy địa chỉ của LoadLibrary trong Kernel32.dll
GetModuleHandle("Kernel32.dll");
GetProcAddress(..., "LoadLibraryA");

// Bước 5: Tạo thread trong tiến trình nạn nhân để gọi LoadLibrary
CreateRemoteThread(hVictimProcess, ..., LoadLibraryAddress, pNameInVictimProcess, ...);

4. Direct Injection

So sánh với DLL Injection

Đặc điểmDLL InjectionDirect Injection
PayloadFile DLL riêng biệtCode/shellcode trực tiếp
Linh hoạtThấp hơnCao hơn
Độ phức tạpThấp hơnCao hơn
Yêu cầuDLL có sẵn trên diskCode tự chứa (self-contained)

Chuỗi API đặc trưng

// Thường có 2 lần gọi VirtualAllocEx + WriteProcessMemory:

// Lần 1: Ghi DATA cho remote thread
VirtualAllocEx(hProcess, ..., sizeOfData, ...);
WriteProcessMemory(hProcess, pData, data, sizeOfData, ...);

// Lần 2: Ghi CODE của remote thread
VirtualAllocEx(hProcess, ..., sizeOfCode, ...);
WriteProcessMemory(hProcess, pCode, code, sizeOfCode, ...);

// Chạy thread với code và data vừa inject
CreateRemoteThread(hProcess, ..., pCode, pData, ...);

Khó khăn khi phân tích

  • Code inject phải self-contained: không dùng được .data section bình thường, phải tự gọi LoadLibrary/GetProcAddress để dùng các hàm cần thiết
  • Payload thường là shellcode → cần kỹ năng phân tích shellcode (xem Chương 19)
  • Cần debug và dump buffer ngay trước khi WriteProcessMemory được gọi

5. Process Replacement

Nguyên lý

Thay vì tiêm code vào tiến trình, malware tạo một tiến trình hợp lệ ở trạng thái suspended, rồi xóa toàn bộ code gốcthay bằng code độc hại.

flowchart TD A["CreateProcess('svchost.exe', CREATE_SUSPENDED)"] --> B["Tiến trình svchost.exe được load vào RAM\nnhưng chưa chạy lệnh nào"] B --> C["ZwUnmapViewOfSection\nGiải phóng toàn bộ bộ nhớ của svchost.exe"] C --> D["VirtualAllocEx\nCấp phát vùng nhớ mới theo ImageBase của malware"] D --> E["WriteProcessMemory\nGhi PE header + các section của malware vào"] E --> F["SetThreadContext\nSet EIP/entry point trỏ đến code malware"] F --> G["ResumeThread\nMalware bắt đầu chạy dưới tên svchost.exe"]

Assembly code thực tế

; Tạo tiến trình ở trạng thái suspended
push CREATE_SUSPENDED    ; dwCreationFlags = 0x4
...
call ds:CreateProcessA

; Sau đó thực hiện replacement:
; ZwUnmapViewOfSection  → giải phóng bộ nhớ gốc
; VirtualAllocEx        → cấp phát lại cho malware
; WriteProcessMemory    → ghi malware vào (header + từng section)
; SetThreadContext      → chỉnh entry point
; ResumeThread           tiến trình "svchost.exe" chạy malware

Tại sao nguy hiểm


6. Hook Injection

Windows Hook là gì?

Windows Hook là cơ chế cho phép một ứng dụng chặn và xử lý các message trước khi chúng đến tiến trình đích.

flowchart LR U[User] -->|Events| OS[Windows OS] OS -->|Messages| T[Threads / Application] U2[User] -->|Events| OS2[Windows OS] OS2 -->|Messages| DLL[Malicious DLL Hook] DLL -->|Forwarded/Modified| T2[Threads / Application]

Phân loại hook

LoạiMô tảYêu cầu
Local hookQuan sát/thao túng message trong cùng tiến trìnhHook procedure nằm trong tiến trình
Remote hook (high-level)Quan sát message của tiến trình khácHook procedure phải là exported function trong DLL
Remote hook (low-level)Nhận notification trước cả OSHook procedure nằm trong tiến trình cài hook

Keylogger dùng Hook

WH_KEYBOARD     → high-level hook, chạy trong context tiến trình bị hook
WH_KEYBOARD_LL  → low-level hook, event gửi thẳng về tiến trình cài hook

Cả hai đều có thể:

  • Ghi lại phím gõ vào file
  • Thay đổi phím trước khi chuyển tiếp

API chính: SetWindowsHookEx

SetWindowsHookEx(
    idHook,      // Loại hook: WH_KEYBOARD, WH_CBT, v.v.
    lpfn,        // Con trỏ đến hàm hook
    hMod,        // Handle DLL chứa hàm hook (high-level) hoặc module local (low-level)
    dwThreadId   // Thread ID cụ thể, hoặc 0 = tất cả threads (bắt buộc = 0 với low-level)
);

Assembly code ví dụ

push offset LibFileName   ; "hook.dll"
call LoadLibraryA
; eax = handle của hook.dll

push offset ProcName      ; "MalwareProc"
push eax                  ; hModule = hook.dll
call GetProcAddress
; eax = địa chỉ của MalwareProc

call GetNotepadThreadId   ; hàm tự định nghĩa → lấy thread ID của notepad.exe

push eax                  ; dwThreadId
push hModule              ; hmod
push edi                  ; lpfn = MalwareProc
push WH_CBT               ; idHook (ít dùng → ít bị IPS phát hiện)
call SetWindowsHookExA

Sau khi hook.dll được inject

DllMain của hook.dll chạy → thực thi toàn bộ code độc hại
Gọi ngay LoadLibrary + UnhookWindowsHookEx trong DllMain
→ Đảm bảo message flow không bị ảnh hưởng
→ Hook tự gỡ bỏ sau khi DLL đã được load

7. Detours

Giới thiệu

Detours là thư viện của Microsoft Research (1999), ban đầu dùng để instrument và extend chức năng OS/ứng dụng. Malware tái sử dụng nó để:

  • Modify import table
  • Đính kèm DLL vào file thực thi có sẵn trên disk
  • Thêm function hook vào tiến trình đang chạy

Cách malware dùng Detours

1. Malware chọn một binary hợp lệ (vd: notepad.exe)
2. Sửa PE structure → thêm section mới tên ".detour"
   - Đặt giữa export table và debug symbols
   - Chứa PE header gốc + import address table mới
3. Dùng setdll tool (có trong Detours SDK) để:
   - Sửa PE header → trỏ đến import table mới
   - Import table mới có thêm evil.dll
4. Kết quả: mỗi lần notepad.exe khởi động → evil.dll tự động được load

8. APC Injection

APC là gì?

Asynchronous Procedure Call (APC) = cơ chế cho phép thực thi một hàm trong context của một thread cụ thể, bất đồng bộ.

  • Mỗi thread có một APC queue
  • APC được xử lý khi thread ở alertable state (trạng thái chờ có thể bị ngắt)
  • Các hàm đưa thread vào alertable state: WaitForSingleObjectEx, WaitForMultipleObjectsEx, SleepEx

Hai loại APC

LoạiNguồn gốcDùng bởi
Kernel-mode APCKernel / DriverOS, drivers
User-mode APCApplicationMalware (từ user space hoặc kernel space)

8.1 APC Injection từ User Space

// Bước 1: Tìm tiến trình và thread mục tiêu
CreateToolhelp32Snapshot  Process32First/Next   // tìm tiến trình
Thread32First/Next                               // tìm thread trong tiến trình đó

// Bước 2: Mở handle đến thread
OpenThread(dwDesiredAccess, bInheritHandle, dwThreadId)

// Bước 3: Queue APC vào thread đó
QueueUserAPC(
    pfnAPC,    // Hàm sẽ được gọi (vd: LoadLibraryA)
    hThread,   // Handle của thread mục tiêu
    dwData     // Tham số truyền vào pfnAPC (vd: "dbnet.dll")
)
; Ví dụ thực tế - inject dbnet.dll vào svchost.exe
push [dwThreadId]
push 0
push 10h
call OpenThread             ; Mở handle thread
mov  esi, eax

push "dbnet.dll"            ; dwData = tên DLL cần load
push esi                    ; hThread
push ds:LoadLibraryA        ; pfnAPC
call QueueUserAPC

8.2 APC Injection từ Kernel Space (Rootkit)

Driver/rootkit dùng hai hàm kernel:

KeInitializeApc(
    PKAPC Apc,           // KAPC structure (ESI trong ví dụ)
    PKTHREAD Thread,     // Thread mục tiêu (arg_0)
    ...
    PKNORMAL_ROUTINE NormalRoutine,  // ≠ 0 → user-mode APC
    KPROCESSOR_MODE ApcMode,         // = 1 → user-mode
    PVOID NormalContext              // Tham số cho NormalRoutine
);

KeInsertQueueApc(
    PKAPC Apc,           // KAPC structure đã init
    ...
);
; Rootkit example
push ebx
push 1                   ; ApcMode = 1 → user-mode ← dấu hiệu quan trọng
push [ebp+arg_4]
push ebx
push offset sub_11964    ; NormalRoutine ≠ 0 ← dấu hiệu quan trọng
push 2
push [ebp+arg_0]         ; Thread mục tiêu (svchost.exe thread)
push esi                 ; KAPC structure
call ds:KeInitializeApc

push [ebp+arg_C]
push [ebp+arg_8]
push esi
call edi                 ; KeInsertQueueApc

Tổng kết so sánh các kỹ thuật

flowchart TD A[Covert Launching Techniques] --> B[Thao túng bộ nhớ trực tiếp] A --> C[Thao túng file trên disk] B --> D[DLL Injection\nCreateRemoteThread + LoadLibrary] B --> E[Direct Injection\nInject shellcode trực tiếp] B --> F[Process Replacement\nThay toàn bộ tiến trình] B --> G[Hook Injection\nSetWindowsHookEx] B --> H[APC Injection\nQueueUserAPC / KeInsertQueueApc] C --> I[Detours\nThêm .detour section vào PE]
Kỹ thuậtAPI đặc trưngPayloadMục đích chính
DLL InjectionCreateRemoteThread, VirtualAllocEx, WriteProcessMemoryDLL fileẨn trong tiến trình hợp lệ
Direct InjectionVirtualAllocEx (×2), WriteProcessMemory (×2), CreateRemoteThreadShellcodeKhông cần DLL trên disk
Process ReplacementCreateProcess(SUSPENDED), ZwUnmapViewOfSection, SetThreadContext, ResumeThreadFull PEGiả mạo tiến trình hợp lệ hoàn toàn
Hook InjectionSetWindowsHookExDLLKeylog hoặc load DLL vào tiến trình
Detourssetdll toolDLLPersistence — chạy mỗi khi app khởi động
APC Injection (user)QueueUserAPC, OpenThreadDLL/shellcodeInject không cần tạo thread mới
APC Injection (kernel)KeInitializeApc, KeInsertQueueApcShellcodeRootkit inject vào user space