PENTESTING WINDOWS: SYSTEM CALLS (PART 1)
Bienvenidos al inicio de esta serie avanzada. Hoy exploraremos el uso de System Calls directos en entornos Windows.
Entendiendo la Arquitectura
Para entender por qué los direct syscalls son importantes, primero debemos observar la arquitectura de memoria dividida de Windows.
User Mode vs Kernel Mode
En Windows, las aplicaciones normales se ejecutan en "User Mode" (Ring 3), mientras que el núcleo del sistema y los drivers están en "Kernel Mode" (Ring 0). Cada transición de modo de usuario a núcleo cuesta tiempo, pero es necesaria para realizar operaciones de E/S.
use std::ptr;
// Emulating a simple native API call pattern in Rust
unsafe fn trigger_syscall() {
let mut status: i32 = 0;
// Example of inline ASM for x64 architecture syscall
std::arch::asm!(
"mov r10, rcx",
"mov eax, 0x18", // NtAllocateVirtualMemory syscall ID specific to a Windows build
"syscall",
out("eax") status
);
println!("Status from syscall: {}", status);
}
fn main() {
unsafe { trigger_syscall() };
}Evasión de EDR
El objetivo principal de usar Direct Syscalls desde la perspectiva ofensiva es puentear (bypass) los ganchos o "hooks" colocados por soluciones EDR. Al llamar directamente a la instrucción syscall, evitamos pasar por ntdll.dll, y por lo tanto, no saltan alertas.
Análisis de los Hooks
Los vendors de seguridad alteran la memoria de ntdll.dll inyectando instrucciones `JMP` al inicio de rutinas como NtReadVirtualMemory. Veremos cómo identificarlos manualmente en la siguiente parte.