Toda técnica de evasión tiene fecha de caducidad
La evasión no es un producto. Pero emular significa vivir en memoria: un teardown de las técnicas y el punto exacto donde cada una se rompe.
La evasión no es una capacidad que se compre ni una técnica que se aprenda una vez. Es un bien perecedero con una fecha de caducidad que nadie anuncia, y toda la disciplina consiste en saber más o menos cuándo se pasó la tuya. La emulación de adversarios exige operar en memoria contra un endpoint defendido, lo que significa entender los loaders. No exige fingir que algo de eso dura.
Esta nota va de dónde se rompen las técnicas. Esa es la mitad más útil para los dos lados del ejercicio: un operador que sabe dónde falla un método deja de apoyarse en él antes de que le deje en evidencia, y un defensor que sabe lo mismo sabe qué instrumentar.
Aquí todo es un intercambio
Un loader tiene un solo trabajo: poner código a correr en memoria sin que el artefacto llegue a resultar interesante para lo que está mirando. Cada técnica que avanza hacia ese objetivo lo paga en otro sitio, y el pago es siempre en la misma moneda: un comportamiento más raro que el que sustituyó.
Esa es la forma del campo entero. No te estás volviendo invisible. Estás eligiendo cuál de tus propiedades observables tiene menos papeletas de ser la que está bajo observación. La rareza es el riesgo, y las técnicas que suenan más impresionantes suelen ser las más raras.
Propiedades estáticas: resueltas, y no es donde está la pelea
Esquivar firmas es la parte que todo el mundo aprende primero y la que menos importa. Los bytes de un fichero se cambian con facilidad, así que una defensa apoyada en los bytes de un fichero se derrota con facilidad, y todos los implicados lo saben desde hace quince años. La detección moderna casi ni mira ahí.
Lo que la sustituyó no son «mejores firmas» sino un desplazamiento de dónde ocurre la evaluación. El contenido se inspecciona en el punto en que cobra sentido y no en el punto en que aterriza en disco, que es para lo que existen interfaces como AMSI. Un script ilegible en disco se vuelve legible en el momento en que el runtime tiene que interpretarlo, y ahí es donde está la comprobación.
La consecuencia es que la ofuscación por sí sola no te compra nada contra un endpoint moderno, mientras te cuesta el perfil de entropía de un fichero normal. Un binario empaquetado con secciones de entropía alta y una tabla de importaciones casi vacía no está evadiendo nada: está anunciando que merece la pena examinarlo. La técnica que iba a esconderte te ha convertido en el fichero menos corriente del directorio.
La detección por comportamiento es el rival de verdad
Una vez la inspección de contenido deja de ser el factor limitante, la pelea se mueve a lo que hace el proceso, y ahí es donde vive el modo de fallo de cada técnica.
Inyección en procesos. Escribir en otro proceso y ejecutar allí es el movimiento más antiguo de la categoría, y su problema es que la secuencia no tiene explicación benigna a escala. Ese conjunto de APIs concreto lleva una década siendo objeto de instrumentación dedicada. Cada variante desarrollada desde entonces, escribir en un objeto de sección en vez de reservar memoria, secuestrar un hilo en vez de crearlo, encolar trabajo en un hilo existente, mueve el mismo comportamiento a una interfaz un poco menos vigilada. Eso funciona exactamente hasta que la interfaz se vigila, y la tendencia va en una sola dirección. Modo de fallo: la operación entre procesos es en sí misma la señal, y la señal no depende de qué función la ejecutó.
Memoria ejecutable sin respaldo. El código que corre desde una región sin fichero detrás es anómalo de una forma que sale barata de escanear. Un defensor puede enumerar cada región ejecutable de cada proceso y preguntar cuáles se corresponden con una imagen mapeada en disco. La respuesta es corta y los falsos positivos son un conjunto conocido y enumerable: algunos runtimes generan código legítimamente, y esa lista se puede establecer como línea base una vez. Modo de fallo: un escaneo periódico de memoria te encuentra sin haber tenido que verte llegar.
Llamadas al sistema directas. Saltarse una función monitorizada en modo usuario invocando la interfaz del kernel directamente elimina un punto de observación y crea otro distinto. Un proceso que emite llamadas al sistema desde una región que no es la biblioteca del sistema es ya inusual, y a la telemetría del lado del kernel que recibe un EDR moderno le da igual qué ruta de modo usuario vino antes. Modo de fallo: evadiste el hook y conservaste el evento.
Living off the land. Usar utilidades del sistema firmadas y esperadas para hacer el trabajo evita introducir código ajeno, lo que es genuinamente el enfoque más duradero de la lista. Su límite es aritmético. El conjunto de esas utilidades es finito, está catalogado en público y las invocaciones inusuales de cada una están cada vez más establecidas como línea base. Modo de fallo: la técnica es duradera, pero el binario concreto que elegiste está en una lista, y el patrón de argumentos también.
Toda técnica de evasión funciona hasta el momento exacto en que la usa suficiente gente. La publicación es la cuenta atrás, y rara vez eres tú quien puso el reloj en marcha.
Qué sigue funcionando de verdad
La fiabilidad en este terreno no viene de la novedad. Viene de parecerse al entorno.
Un proceso que corre desde una ubicación plausible, está firmado, lanza los hijos que lanza su homólogo real, habla con hosts con los que la organización ya habla y hace su trabajo a un ritmo que encaja con el tráfico de alrededor es difícil de aislar. No porque ninguna técnica concreta haya derrotado un control, sino porque ninguna propiedad suya por separado es rara. Eso es un problema de investigación sobre el entorno objetivo, no un problema de programación, y ahí es donde debería ir el tiempo.
El corolario es el útil para los defensores: la restricción que tiene un intruso es el conocimiento de qué es normal en tu entorno, y todo lo que hagas para que lo normal sea más difícil de caracterizar desde dentro vale más que otro producto. Rutas de build consistentes, una lista corta y aplicada de software firmado, salida de tráfico a través de un proxy que registre y puestos de trabajo que se parezcan entre sí son todas cosas aburridas y todas encarecen el mimetizarse.
La versión de esta nota para el defensor
Si te llevas una sola cosa de la sección anterior, llévate el orden. Están aproximadamente en orden descendente de valor por unidad de esfuerzo:
- Escanea la memoria de los procesos en busca de regiones ejecutables sin fichero detrás, de forma programada. Caza una clase amplia de técnicas de golpe y no requiere haber observado la llegada.
- Alerta sobre operaciones de memoria entre procesos por linaje, no por API. La función concreta cambiará; la relación padre-hijo es más estable.
- Establece una línea base de qué procesos de tu entorno generan memoria ejecutable legítimamente. La lista es más corta de lo esperado y todo lo que quede fuera es una pregunta que merece hacerse.
- Vigila las llamadas al sistema que se originen fuera de las bibliotecas del sistema. Es una señal estrecha y con muy poco ruido.
- Restringe y registra la salida de tráfico. Un loader que no puede llegar a su infraestructura es un fichero inerte.
Por qué esto está escrito siquiera
Las técnicas de arriba están documentadas en público, se enseñan en cursos comerciales y están implementadas en herramientas abiertas que cualquier defensor puede lanzar contra su propio entorno esta misma tarde. Nada de esto le acorta a nadie el camino hacia nada.
Lo que merece la pena decir con claridad es la economía. La investigación de evasión de un operador se degrada continuamente y necesita reinversión constante para seguir vigente. El trabajo estructural de un defensor, conocer el entorno, restringir qué es normal, instrumentar comportamiento en lugar de contenido, se revaloriza. El lado que tiene que correr para quedarse en el sitio no es el que la gente supone.
// ¿te ha servido esta nota?