Evasion de EDR para Investigacion: Direct Syscalls Explicados sin Romantizar
Como funcionan los direct syscalls en estudio defensivo controlado, por que siguen siendo detectables, y que deberia mirar un blue team antes de comprar la proxima caja negra.
Los direct syscalls se volvieron meme en canales de YouTube y hilos de Twitter, pero la mayoria de la investigacion publicada ni se acerca a lo que un EDR moderno (CrowdStrike Falcon 7.x, SentinelOne Singularity, Microsoft Defender for Endpoint con ETW-TI kernel) realmente observa. En Basilisk OffSec estudiamos la tecnica en laboratorio aislado, con Windows 11 23H2 sin internet, snapshots VMware versionados y cero intencion de empaquetar esto como servicio. El objetivo es claro: entender el camino NTDLL -> SSN -> syscall -> kernel para escribir mejores detecciones, no vender bypass. Si lo que buscas es apilar IOC y fingir red team profesional, mejor cierra la pestana.
Repasando lo basico sin condescendencia: cada funcion documentada en ntdll.dll (NtAllocateVirtualMemory, NtCreateThreadEx, NtProtectVirtualMemory) lleva un System Service Number (SSN) que cambia con cada build de Windows. El EDR tipicamente instala un hook inline JMP en los primeros bytes de esos stubs en user-mode, asi que cuando tu loader llama VirtualAlloc el control pasa por la DLL inyectada antes de tocar el kernel. Direct syscall significa replicar el stub dentro de tu binario - mov r10, rcx; mov eax, SSN; syscall; ret - saltandose el hook por completo. Funciona, pero como veremos es una victoria barata contra telemetria user-mode y nada contra telemetria kernel. Para contexto vale releer Bypass de AMSI y ETW para Investigacion Defensiva: Lo que los Blue Teams Deben Saber, la logica es similar.
Para reproducir en casa uso SysWhispers3 (fork mantenido por klezVirus) generando stubs MASM para un proyecto C++ compilado con MSVC 19.38. El SSN se resuelve en runtime via Hell's Gate o Halo's Gate, recorriendo la EAT de la ntdll mapeada desde disco, no la version en memoria que puede estar adulterada. En tres horas de banco logre un POC que asigna RW, escribe shellcode benigno (calc.exe puro, sin nada extra), llama NtProtectVirtualMemory a RX y dispara NtCreateThreadEx. Sysmon 15 con la config de SwiftOnSecurity registra creacion de hilo, pero ProcessAccess queda limpio. Parece victoria hasta que activas Defender en EDR block mode y el alerta sale del kernel via Threat Intelligence ETW, no de user-mode.
Aqui esta el punto que nadie quiere decir en escenario: Microsoft-Windows-Threat-Intelligence emite eventos de NtAllocateVirtualMemory, NtProtectVirtualMemory con RWX, NtMapViewOfSection y NtCreateThreadEx independientemente del hook user-mode. Te saltaste la NTDLL, perfecto, pero el kernel vio llegar el syscall con un return stack apuntando al .text de tu binario en vez de a ntdll.dll - justo lo que la deteccion de call stack anomaly persigue. Elastic Security tiene regla publica desde 2023, y la gente de Threat Hunting con Sigma y Elastic: Del Indicador a la Regla de Deteccion ya la consume por defecto. Indirect syscalls (saltar de regreso dentro de la ntdll y hacer syscall ahi) mitigan ese stack pero generan otros artefactos que YARA-X identifica.
En proyectos autorizados discutimos este trade-off con el cliente antes de ejecutar, y esto conecta directo con Red Team 101: Diferencia entre Pentest y Operaciones Adversariales Reales: la emulacion de adversario tiene alcance, reglas de enganche y ventana definida. Del lado defensivo el ejercicio es mas rico - correr el POC, capturar el ETW-TI con SilkETW o krabsetw, y escribir una regla Sigma que cubra la heuristica sin disparar falso positivo en el instalador de Teams. Suelo combinar esto con hardening segun Hardening de Windows 11 para Estaciones de Trabajo de Alto Riesgo y revisar movimiento cruzado como en Movimiento Lateral en Lab: SMB, WMI y WinRM con Foco en Deteccion, porque el syscall directo aislado rara vez es la historia completa de un incidente real.
Algunas preguntas que recibo y respondo rapido: no, no publicamos loader listo; no, unhooking via copia fresca de NTDLL desde disco no es magia - Defender mapea eso desde 2022 con memory image integrity; y no, ChatGPT escribiendo tu shellcode en Nim no te vuelve invisible, solo te da entropia rara en el .text que el clasificador ML del EDR adora. Para quien empieza en serio el lado ofensivo, recomiendo base solida en Pentest de Active Directory: Kerberoasting Paso a Paso en Lab GOAD e Construyendo Infra de C2 con Sliver en Lab Aislado para Estudio Defensivo antes de meterte a syscalls, porque sin entender que viene despues de la ejecucion solo te quedas admirando tu reflejo en Process Hacker.
Takeaway practico: si eres defensor, habilita el provider Microsoft-Windows-Threat-Intelligence (requiere PPL en el servicio EDR), ingestalo en tu SIEM y construye tres reglas - call stack no originado en ntdll, NtProtectVirtualMemory cambiando RW a RX en region private, y NtCreateThreadEx cross-process con start address en heap. Eso atrapa el 80% de los POCs publicos sin costo de licenciamiento extra. Si eres investigador, documenta, aisla, no distribuyas binarios compilados y recuerda que la frontera entre estudio y delito es el consentimiento escrito del dueno del activo - tema que OPSEC para Investigadores de Seguridad: Modelo de Amenaza Personal cubre con detalle.