crystal-palace. tradecraft link PIC y evasion de EDRs

2026-06-25 research

Introducción

Crystal Palace es un enlazador y un lenguaje de especificación especializado en la construcción y transformación de código independiente de posición. Su propósito no es sustituir al compilador ni convertir automáticamente cualquier programa en un artefacto indetectable. Su objetivo es proporcionar una cadena de construcción con la que separar capacidades, componentes de carga y técnicas de instrumentación, y después combinarlos de manera explícita mediante archivos .spec.

La documentación oficial lo presenta como una herramienta orientada al desarrollo de capacidades de postexplotación y a la investigación de técnicas de evasión. También deja claro que el proyecto busca que los componentes sean independientes del caso de uso, interoperables y reutilizables. Esta separación entre capacidad y tradecraft es la idea central de Tradecraft Garden.

Este artículo estudia Crystal Palace desde una perspectiva arquitectónica y crítica. No es un tutorial de evasión ni una promesa de indetectabilidad. El objetivo es explicar:

  • qué problema intenta resolver;
  • qué significa que sea un enlazador y no un compilador;
  • cómo organiza PIC, PICO, recursos, bibliotecas y archivos .spec;
  • qué hacen realmente sus transformaciones;
  • cómo funcionan attach, redirect, addhook, preserve, magic, ised y rule;
  • qué puede afirmarse de una integración con C2 como Mythic y Xenon;
  • qué límites técnicos y metodológicos deben tenerse presentes.

La fuente principal es la documentación oficial de Crystal Palace, consultada en agosto de 2026:

Como referencias complementarias se utilizan el repositorio oficial de Xenon, el proyecto Crystal-Kit-Xenon y el artículo técnico de Lorenzo Meacci sobre una implementación concreta basada en Crystal Palace.

Ámbito ético: las técnicas y herramientas mencionadas deben estudiarse únicamente en laboratorios propios o entornos donde exista autorización expresa. Ninguna característica de Crystal Palace garantiza evasión frente a productos de seguridad ni sustituye una metodología de prueba responsable.


imagen echa con Gemini 3.1pro nanobana

Fuera de tecnicismos el elefante en la habitacion, esto lleva redactado un tiempo y en mi mente. Al final, es lo que más utilizo para la evasión de EDR y lo que aprendí a usar en el CRTL de Zero-Point Security.

bastante gente me preguntó si iba a hablar sobre Crystal Palace para la evasión de EDRs como Elastic o CrowdStrike. Esto también a raíz de una de mis anteriores explicaciones que trataba sobre Stardust.

Y yo les decía: "Quiero, pero no tengo dónde hacerlo que no sea un Cobalt Strike, y yo no tengo Cobalt Strike"

El problema radica en lo siguiente: no hay C2 open source que se lleven excesivamente bien con Crystal Palace.

Sliver, cómo no, siempre fastidiando con Go. Y eso que lo conseguí aplicar gracias a este proyecto, pero era tan inconsistente que simplemente no vale la pena gastar tiempo en él: https://github.com/licitrasimone/CrystalSliver (de hecho, yo pasé un vídeo en el Discord de Zero-Point usándolo y no iba mal con mis configs, pero cuando profundizas te das cuenta de todo).

AdaptixC2. Esto no sé cómo describirlo. Es raro; simplemente me parece raro en algunos sentidos. La implementación de Crystal Palace en este caso se llama StealthPalace (https://github.com/MaorSabag/Adaptix-StealthPalace) y el creador es majísimo, muy buen tío. Pero tiene un problema: no tiene post-ex. Se lo comenté al creador y me dijo que eso está hecho, pero que no sabe si liberarlo. Y yo dije: «¿De qué me sirve colarme si después no puedo hacer nada?». Me puse a investigar para hacerme mi propia post-ex y ahí vi lo raro que era el C2.

Y después vino Mythic a mi vida. Yo ya lo había usado con anterioridad (como hace 2 años jajaj), pero la interfaz es muy rara, al igual que el tema de los agentes. Sin embargo, hablando con its-a-feature (https://github.com/its-a-feature), creador de Mythic, me comentó la existencia de Xenon (https://github.com/MythicAgents/Xenon) (https://github.com/nickswink/Crystal-Kit-Xenon) y me presentó a su creador. Hablando con él, me comentó que, aunque Xenon no está acabado al 100%, sí que cubre todas mis necesidades. Y pues llevo cosa de casi un mes testeándolo y analizándolo todo.

Los resultados han sido magníficos: cubre casi al 100% mis necesidades (he notado unas pequeñas cosas en la post-ex, pero tienen solución) y procedí a probarlo contra mi Elastic 9.4.2. Para ello, también me lancé a hacer un loader bastante potente en Rust, hecho a medida para el .bin de Mythic con Crystal Palace (esto me da para otra entrada de blog, así que no entraré en detalles, pero es para que tengáis el contexto). ¿El resultado? Ni una sola detección, incluso ejecutando varias cosas. Os comparto las capturas que pasé por el Discord de Zero-Point Security; más adelante, a lo mejor, añado un vídeo de demostración. :).

1.1 Qué es el código independiente de posición

El código independiente de posición, o PIC por sus siglas en inglés, es código que puede ejecutarse correctamente aunque su dirección de carga cambie. En el modelo descrito por Crystal Palace, el resultado suele ser un bloque de código y datos que puede colocarse en memoria y comenzar su ejecución desde una posición acordada, sin depender del cargador PE normal de Windows.

Un ejecutable o una DLL convencional reciben numerosos servicios del compilador, del enlazador y del cargador del sistema operativo. Entre ellos se encuentran:

  • la disposición final de secciones;
  • la resolución de símbolos;
  • la aplicación de relocalizaciones;
  • la construcción y resolución de la tabla de importaciones;
  • el acceso a cadenas y datos globales;
  • la preparación de metadatos necesarios para la ejecución.

Cuando se extrae únicamente la sección de código de un objeto o de una imagen ya enlazada, esos servicios dejan de estar disponibles. El código puede conservar referencias a datos situados en otras secciones, a símbolos aún no resueltos o a funciones que normalmente se localizarían mediante la IAT. Por eso escribir PIC en C exige disciplina y conocimiento del resultado generado por el compilador.

No debe simplificarse el problema diciendo que toda referencia relativa a RIP depende del ImageBase. El problema real es el contrato entre código, datos, relocalizaciones y disposición de secciones. Si se separa .text del resto del artefacto o se cambia su diseño sin volver a resolver esas relaciones, las referencias pueden dejar de ser válidas.

1.2 El enfoque manual

El enfoque clásico consiste en compilar C a un objeto COFF, examinar sus relocalizaciones y eliminar o adaptar todo aquello que no sea compatible con el formato PIC elegido. Según el compilador, las opciones y el código fuente, suelen requerir atención:

  • literales almacenados fuera de .text;
  • variables globales y estáticas;
  • importaciones de API;
  • referencias a funciones auxiliares del runtime;
  • tablas de salto generadas por algunas construcciones de C;
  • metadatos de excepciones y desenrollado de pila;
  • supuestos de alineación y convención de llamada.

La regla informal de colocar una función como go() al principio aparece en muchos diseños porque el ejecutor necesita saber dónde comienza la ejecución. Sin embargo, no es una propiedad universal de todo PIC. Es un contrato concreto entre un artefacto y quien lo carga. Crystal Palace ofrece mecanismos como +gofirst para imponer ese contrato cuando el proyecto lo necesita.

1.3 Qué aporta Crystal Palace

Crystal Palace trabaja después del compilador. Recibe objetos COFF compatibles, los analiza y aplica las operaciones declaradas en un archivo .spec. Puede combinar código, relacionar símbolos, incorporar recursos, generar determinadas formas de PIC o PICO y transformar el resultado.

Esto recupera parte de la ergonomía que se pierde al escribir PIC de forma manual. El desarrollador puede trabajar con cadenas, determinados datos globales, referencias a API mediante la convención DFR, bibliotecas compatibles y módulos separados. La herramienta se encarga de integrar esos elementos dentro del modelo de salida solicitado.

No obstante, esta capacidad tiene límites importantes. La documentación oficial indica que Crystal Palace espera principalmente objetos COFF compilados desde C con MinGW-w64, recomienda especialmente -O0 y -O1, y advierte que algunas características de C no están soportadas. También especifica que no se realizan adaptaciones generales para otros lenguajes y compiladores.

Por tanto, sería incorrecto afirmar que cualquier objeto COFF generado por MSVC, Clang, Go, Rust o cualquier otro compilador puede transformarse automáticamente. Algunos objetos externos pueden funcionar si respetan las convenciones admitidas, pero la compatibilidad debe probarse de manera específica.


2.1 Responsabilidades del compilador y del enlazador

El compilador transforma el código fuente en objetos que contienen instrucciones, datos, símbolos y relocalizaciones. El enlazador combina esos objetos y construye una salida que cumple un contrato determinado.

Un enlazador convencional para Windows suele producir un EXE o una DLL conforme al formato PE. Crystal Palace persigue otro resultado: componer y transformar objetos para producir código que pueda utilizarse como PIC, PICO, COFF enlazado u otro artefacto definido por su especificación.

Esta diferencia explica por qué Crystal Palace puede actuar sobre elementos que ya existen en los objetos:

  • símbolos de funciones y datos;
  • referencias entre módulos;
  • relocalizaciones;
  • secciones de código y datos;
  • puntos donde pueden aplicarse redirecciones;
  • patrones de instrucciones sobre los que puede operar ised;
  • metadatos generados durante el proceso de enlace.

Crystal Palace no comprende la intención semántica completa del programa y no puede reparar cualquier construcción arbitraria. Opera sobre las estructuras y patrones que su modelo reconoce.

2.2 Cadena de construcción

Una cadena de construcción típica puede representarse así:

  1. El código C se compila mediante MinGW-w64 a objetos COFF.
  2. Un archivo .spec carga los objetos necesarios.
  3. La especificación decide qué elementos se fusionan, transforman o mantienen separados.
  4. Se configuran servicios como la resolución dinámica de funciones.
  5. Se incorporan bibliotecas y recursos compatibles.
  6. Se aplican redirecciones, hooks y transformaciones declaradas.
  7. Se genera la salida solicitada.

No existe una especificación predeterminada que sea correcta para todos los proyectos. El archivo .spec describe explícitamente cómo debe construirse cada artefacto.

2.3 Requisitos documentados

La documentación oficial enumera como base:

  • OpenJDK 11 o posterior;
  • MinGW-w64;
  • un entorno Linux, incluido WSL como opción recomendada;
  • objetos COFF producidos desde C mediante MinGW para los casos soportados.

Esto no convierte a Crystal Palace en un enlazador universal. Su entorno de C restringido puede entenderse como un ensamblador de alto nivel: se pierde parte de la comodidad y compatibilidad de una cadena nativa tradicional, pero se obtiene control sobre la estructura y el contenido del artefacto.


3.1 La convención PICO

PICO es una convención de Crystal Palace para encapsular código independiente de posición en un formato diseñado para ser cargado, enlazado o reutilizado dentro de otros componentes compatibles. La documentación lo describe como una convención común para código, COFF preparado para carga y bibliotecas que pueden funcionar en distintos contextos.

Un PICO no debe presentarse simplemente como “cualquier COFF”. Debe cumplir las convenciones que Crystal Palace define sobre símbolos, servicios, datos y forma de ejecución.

3.2 Composición modular

Uno de los objetivos del proyecto es separar:

  • capacidad, que representa la función principal de un componente;
  • carga, que prepara y transfiere la ejecución;
  • servicios, como resolución de API o acceso a datos;
  • instrumentación, que modifica o envuelve determinados comportamientos;
  • recursos, que se enlazan junto al código;
  • transformaciones, que cambian la representación final.

Esta separación permite probar y reemplazar módulos de forma independiente, siempre que mantengan el contrato esperado. No significa que todos los componentes sean intercambiables sin trabajo. Sus interfaces, símbolos, convenciones y supuestos deben coincidir.

3.3 Sub-PICOs y regiones independientes

Una especificación puede invocar otra mediante run y enlazar el resultado como recurso o componente. Este patrón permite construir sub-PICOs independientes y resolver funciones exportadas mediante los mecanismos previstos por la herramienta.

Si dos PICOs se cargan en regiones distintas, no debe suponerse que comparten automáticamente sus variables globales. La comunicación debe realizarse mediante funciones exportadas, estructuras compartidas o datos entregados expresamente durante la inicialización.

Esta separación es útil para el diseño modular, pero también añade posibles errores:

  • inicialización en orden incorrecto;
  • símbolos exportados ausentes;
  • estructuras incompatibles;
  • recursos enlazados con tamaños equivocados;
  • referencias a memoria liberada;
  • diferencias entre versiones de bibliotecas.

4.1 Función de la especificación

El archivo .spec es el guion de enlace de Crystal Palace. Describe qué objetos y recursos participan en la construcción y qué operaciones deben aplicarse. No debe entenderse como un simple archivo de configuración. Es una parte ejecutable de la arquitectura de construcción.

Entre sus responsabilidades se encuentran:

  • cargar objetos y bibliotecas;
  • establecer el tipo de salida;
  • fusionar módulos;
  • definir recursos;
  • configurar la resolución dinámica de funciones;
  • redirigir referencias;
  • registrar hooks;
  • aplicar transformaciones;
  • exportar el resultado.

La sintaxis exacta puede cambiar entre versiones. Siempre debe consultarse la documentación que corresponda a la distribución instalada.

4.2 load, merge y mergelib

load introduce un objeto en el estado de construcción. merge combina un objeto cargado con el objetivo actual. mergelib incorpora elementos de una biblioteca compatible.

Estas directivas favorecen la composición, pero no eliminan las reglas de compatibilidad. Una biblioteca no puede considerarse utilizable solo porque esté comprimida en un archivo o contenga objetos COFF. Debe respetar el modelo de símbolos, compilador y código que Crystal Palace admite.

4.3 make pic y +gofirst

make pic solicita una transformación orientada a código independiente de posición. Las opciones asociadas cambian aspectos de la salida. +gofirst, por ejemplo, sitúa la función go() al comienzo cuando el proyecto adopta ese contrato.

Esto no significa que go() sea un requisito universal de Windows ni de todo código PIC. Es una convención útil entre el blob y el componente que transferirá la ejecución.

4.4 DFR

DFR, o Dynamic Function Resolution, permite expresar referencias a funciones mediante la convención MODULE$Function y resolverlas sin depender de una IAT convencional.

Crystal Palace prepara las referencias y su integración, pero el proyecto debe proporcionar los servicios de resolución requeridos por la especificación. El comportamiento final depende del resolver y de cómo se haya compuesto el programa.

No debe afirmarse que DFR oculta automáticamente todas las cadenas o que evita por sí solo la observación de API. Reduce o cambia determinados artefactos estáticos, pero la llamada sigue teniendo efectos observables durante la ejecución.

Crystal Palace puede incorporar recursos junto al código y hacerlos accesibles mediante símbolos enlazados. Un flujo puede cargar un recurso, aplicarle una transformación, anteponer su longitud y vincularlo con un nombre.

preplen antepone una longitud de cuatro bytes al recurso que se enlaza. Esta convención permite que el código recupere tanto la dirección como el tamaño, siempre que interprete correctamente el formato.

También pueden aplicarse operaciones de enmascaramiento o cifrado proporcionadas por la herramienta. Esto no implica que el recurso sea criptográficamente seguro en todos los sentidos. Si el código contiene la información necesaria para recuperar el contenido, un analista con acceso al artefacto y al proceso también puede estudiar ese procedimiento.

4.6 attach, redirect, addhook y preserve

Estas funciones suelen confundirse, por lo que conviene separarlas conceptualmente.

attach

attach permite envolver o intervenir referencias a una función dentro de los objetos que Crystal Palace está transformando. El wrapper puede sustituir el comportamiento o decidir cómo acceder al objetivo original según el contrato definido por la herramienta.

No debe describirse únicamente como una sustitución textual de direcciones. Es una operación de enlace consciente de símbolos y del modelo de llamadas de Crystal Palace.

redirect

redirect cambia el destino de referencias determinadas. A diferencia de un wrapper que puede conservar acceso al objetivo, una redirección expresa que la referencia debe apuntar al nuevo símbolo conforme a las reglas de la especificación.

addhook

addhook registra información que puede ser consultada mediante __resolve_hook. Su uso típico consiste en permitir que un componente de resolución devuelva una función alternativa para un nombre o hash registrado.

Registrar un hook no modifica mágicamente todas las importaciones de una DLL. El cargador o el código encargado de resolverlas debe integrar __resolve_hook en su flujo. Si no lo hace, el registro no tendrá el efecto esperado.

preserve

preserve limita la aplicación de determinados wrappers o redirecciones dentro de un contexto concreto. Resulta útil para evitar ciclos, conservar una llamada original durante la inicialización o excluir una función de una transformación global.

Un uso incorrecto puede producir recursión, comportamientos inesperados o fallos difíciles de depurar. La necesidad concreta de preserve depende de la arquitectura del proyecto y no debe generalizarse desde una única implementación.


5.1 Qué pueden conseguir

Crystal Palace incluye transformaciones orientadas a modificar la representación binaria del programa. Su utilidad principal es aumentar la variabilidad, romper secuencias rígidas y estudiar qué partes de un artefacto permanecen invariantes.

Estas transformaciones pueden dificultar firmas basadas en bytes exactos. No garantizan que el binario sea único en todos sus fragmentos, que todas las reglas YARA dejen de coincidir ni que desaparezcan indicadores estructurales o de comportamiento.

5.2 +mutate

+mutate transforma determinadas constantes y construcciones compatibles mediante operaciones equivalentes. Los valores configurados con magic pueden utilizarse para descomponer una constante en una secuencia que reconstruye el valor durante la ejecución.

Por ejemplo, conceptualmente una asignación directa puede representarse como una combinación aritmética equivalente. La documentación no describe una tabla general incrustada que el loader consulte para recuperar cada constante. La reconstrucción se deriva de las instrucciones generadas.

+mutate no debe definirse como la opción que reorganiza bloques, cambia arbitrariamente registros y sustituye cualquier instrucción. Esas funciones corresponden a otras transformaciones.

5.3 magic

magic controla los valores disponibles para determinadas mutaciones. Su objetivo es influir en la representación de constantes y patrones compatibles.

No es una técnica criptográfica y no protege el significado del programa frente a análisis. Un desensamblador o un análisis simbólico puede reconstruir operaciones equivalentes.

5.4 +regdance

+regdance modifica asignaciones de registros no volátiles cuando la transformación puede realizarse de forma segura. Esto puede cambiar los bytes producidos sin alterar la semántica prevista.

La transformación no puede aplicarse de manera ilimitada. Debe respetar la convención de llamada, los registros con propósito especial y las dependencias que el análisis haya identificado.

5.5 +blockparty, +shatter y +disco

Estas opciones afectan a la disposición del código:

  • +blockparty reorganiza bloques básicos dentro de funciones compatibles;
  • +shatter realiza una reorganización más amplia del flujo y de los bloques a escala del programa;
  • +disco modifica el orden de funciones en la salida.

El comportamiento exacto y las restricciones deben verificarse en la documentación de la versión usada. No es correcto describir +shatter como una simple inserción de “bytes basura”. Una inserción arbitraria rompería instrucciones y destinos de salto.

5.6 ised

ised permite realizar modificaciones quirúrgicas sobre instrucciones o patrones reconocidos por el desensamblador interno de Crystal Palace. Puede insertar, reemplazar, eliminar o dividir determinadas formas, según las operaciones admitidas y sus opciones de seguridad.

Su valor está en abordar patrones localizados que permanecen estables. Antes de escribir una regla ised, es necesario trabajar con la representación de instrucciones que la propia herramienta reconoce. Una forma textual aproximada puede no coincidir con el patrón interno.

Las instrucciones modificadas mediante ised pueden excluirse de la generación automática de reglas YARA de Crystal Palace. Esto no significa que una herramienta YARA externa o un producto de seguridad sea incapaz de detectarlas.

5.7 Coste de las transformaciones

Las transformaciones pueden aumentar el tamaño, introducir más saltos, complicar la depuración y ampliar el número de combinaciones que deben probarse. No existe un porcentaje universal de sobrecarga válido para todos los proyectos.

El impacto depende de:

  • número y tamaño de funciones;
  • cantidad de constantes transformables;
  • opciones activadas;
  • uso de bibliotecas;
  • cantidad de recursos;
  • nivel de optimización;
  • versión de Crystal Palace.

Por tanto, cifras como “20-90 %” o “15-30 %” solo deberían publicarse si proceden de un conjunto de pruebas reproducible y claramente documentado.


6. Generación de reglas YARA y partes invariantes

6.1 Qué hace rule

La directiva rule configura la generación de reglas YARA para representar partes invariantes del programa. Los parámetros definen aspectos como el número de firmas, el acuerdo mínimo y las longitudes consideradas. La opción de línea de comandos correspondiente genera el archivo de reglas.

Esta función sirve para localizar secuencias que permanecen suficientemente estables en un conjunto o salida y que podrían convertirse en firmas. Es una herramienta de evaluación y retroalimentación.

6.2 Qué no hace rule

No debe afirmarse que rule:

  • escanea automáticamente todas las reglas conocidas de un EDR;
  • garantiza que una build sea indetectable;
  • falla siempre que quede cualquier patrón detectable;
  • demuestra que las firmas estáticas son imposibles;
  • sustituye a una batería externa de pruebas.

La generación de una regla contra partes invariantes solo cubre el modelo y los parámetros utilizados por Crystal Palace. Un defensor puede crear reglas con otras condiciones, combinar indicadores o detectar el comportamiento en ejecución.

6.3 Uso metodológico correcto

Un flujo riguroso de evaluación puede incluir:

  1. construir varias muestras de un mismo proyecto;
  2. conservar opciones, versiones y hashes;
  3. generar reglas sobre invariantes;
  4. estudiar qué componentes producen coincidencias;
  5. corregir o diversificar únicamente los patrones justificados;
  6. repetir la prueba;
  7. validar con herramientas defensivas independientes;
  8. registrar falsos positivos y estabilidad entre versiones.

El resultado debe presentarse como evidencia limitada al conjunto probado, no como una garantía universal.


7. Relación con visibilidad de EDR

7.1 Superficies habituales de observación

Un producto EDR puede combinar múltiples fuentes:

  • análisis de archivos y contenido;
  • reputación y procedencia;
  • memoria ejecutable y permisos;
  • creación de procesos e hilos;
  • carga de imágenes;
  • llamadas y telemetría de API;
  • pila de llamadas;
  • ETW y telemetría de kernel;
  • comportamiento de red;
  • correlación temporal entre eventos.

Crystal Palace actúa principalmente durante la construcción y composición del artefacto. No controla por sí mismo todas estas superficies.

7.2 Análisis estático

Eliminar un formato PE convencional, resolver funciones de otra manera y variar instrucciones puede reducir algunos indicadores estáticos. Sin embargo, también pueden aparecer otros:

  • entropía inusual;
  • stubs de resolución repetitivos;
  • constantes o hashes conocidos;
  • estructuras de recursos;
  • patrones de desenmascaramiento;
  • relaciones entre bloques;
  • similitud semántica entre muestras.

La frase “la detección estática se vuelve inabordable” no es sostenible. Una formulación correcta es que la variabilidad por compilación puede dificultar determinadas firmas rígidas, mientras otras técnicas de clasificación y análisis siguen siendo aplicables.

7.3 Memoria y comportamiento

Crystal Palace no decide automáticamente:

  • dónde se asigna la memoria;
  • qué permisos recibe;
  • si existe respaldo de archivo;
  • cómo se resuelven importaciones;
  • cómo se transfiere la ejecución;
  • qué hace el software una vez iniciado.

Esas decisiones pertenecen al componente de carga y a la capacidad ejecutada. Un cargador defectuoso continúa siendo defectuoso aunque se haya construido con Crystal Palace.

7.4 Hooks y pila de llamadas

attach y addhook permiten instrumentar llamadas dentro del modelo de enlace y resolución del proyecto. Esa capacidad puede utilizarse para pruebas defensivas, observabilidad, compatibilidad o investigación de pilas de llamadas.

No obstante, una pila aparentemente coherente no elimina la telemetría del kernel, los parámetros observados, el contexto del hilo, las transiciones de memoria ni los efectos posteriores. Los productos modernos correlacionan distintas señales.

7.5 ETW y kernel

Crystal Palace es una herramienta de userland y de tiempo de construcción. No elimina callbacks de kernel ni controla universalmente ETW-TI u otras fuentes de telemetría protegidas. Cualquier afirmación de que “aborda la mayoría de los vectores” debe especificar qué implementación se evaluó y qué telemetría permanecía activa.


8.1 Agnóstico no significa compatible automáticamente

Crystal Palace no impone un contrato específico de Cobalt Strike, Mythic u otro C2. Esa independencia permite adaptarlo a distintos proyectos, pero obliga a entender el formato real de cada capacidad.

La documentación de Tradecraft Garden señala una serie de supuestos usados por sus cargadores de demostración, como una DLL estándar con DllMain, y advierte que una capacidad de C2 puede no respetarlos. La compatibilidad con un C2 concreto no es un objetivo automático de los ejemplos.

Para integrar una capacidad deben documentarse al menos:

  • formato de entrada;
  • arquitectura;
  • convención de entrada;
  • argumentos de inicialización;
  • requisitos de TLS;
  • modelo de hilos;
  • importaciones;
  • ciclo de vida y finalización;
  • comunicación con el framework;
  • postexplotación y recuperación de salida.

8.2 Xenon

Xenon es un agente de Windows para Mythic escrito en C. Su repositorio oficial indica que se encuentra en una fase temprana, que la configuración predeterminada no se considera segura desde el punto de vista OPSEC y que puede contener problemas de memoria. También enumera soporte para UDRL basados en Crystal Palace y compatibilidad con kits de inyección de proceso.

Estas advertencias son importantes. No debe presentarse Xenon como una plataforma terminada o capaz de evadir EDR por defecto. La propia documentación del proyecto rechaza esa afirmación.

La compatibilidad puede cambiar con rapidez. En agosto de 2026, el repositorio público muestra la versión 0.0.6 como estado reciente, pero cualquier artículo debe fijar un commit o una versión concreta para que sus resultados sean reproducibles.

8.3 Crystal-Kit-Xenon

Crystal-Kit-Xenon es un fork de Crystal Kit adaptado para Xenon. El repositorio lo describe como una modificación de compatibilidad y contiene componentes separados para el loader y el loader de postexplotación.

Su existencia demuestra que la integración es posible, no que toda configuración funcione de la misma forma. Cambios recientes, como la adaptación a SleepEx, muestran que el contrato del agente puede evolucionar y obligar a actualizar hooks y servicios.

8.4 Cómo presentar pruebas propias

Si un autor afirma haber probado una combinación contra un EDR, la metodología debería incluir:

  • versión y commit de Crystal Palace;
  • versión y commit del agente;
  • versión del sistema operativo;
  • producto EDR y versión;
  • políticas y módulos activos;
  • conectividad del laboratorio;
  • configuración de compilación;
  • hashes de las muestras;
  • acciones ejecutadas;
  • duración de la observación;
  • alertas, eventos y logs revisados.

“Cero detecciones” solo significa que no se observaron alertas bajo esas condiciones. No demuestra invisibilidad general ni resultados equivalentes en otra política, versión o entorno.


9. Comparación prudente con otros enfoques

9.1 Stardust

Stardust y Crystal Palace abordan el desarrollo PIC desde modelos distintos. Stardust proporciona convenciones y una cadena de enlace para desarrollar implantes PIC con una disciplina explícita sobre símbolos y secciones. Crystal Palace opera como enlazador y transformador sobre objetos compatibles y enfatiza la composición mediante .spec.

No hay un ganador universal. La elección depende de si se desea controlar directamente el diseño de un implante, reutilizar módulos compatibles, transformar objetos existentes o componer servicios de enlace.

9.2 RDI y sRDI

Reflective DLL Injection coloca la lógica de carga reflectiva dentro o junto a una DLL y permite prepararla sin recurrir al cargador convencional. sRDI convierte o acompaña una DLL con un stub de shellcode que realiza la carga.

No todas las implementaciones de RDI o sRDI son equivalentes. Deben distinguirse:

  • loader integrado en la DLL;
  • stub antepuesto;
  • lógica completa de carga externa;
  • modificaciones específicas de un framework;
  • decisiones de memoria y transferencia de ejecución.

Las implementaciones públicas ampliamente reutilizadas pueden presentar patrones conocidos, pero no es correcto afirmar sin evidencia que “todos los EDR” detectan cualquier variante.

9.3 Donut

Donut empaqueta distintos tipos de capacidades en una forma ejecutable como shellcode. No debe mezclarse con sRDI como si ambos tuvieran el mismo punto de entrada, formato interno o tratamiento de cadenas y globales.

La comparación útil debe hacerse por criterios observables:

  • tipos de entrada;
  • formato de salida;
  • necesidad de runtime;
  • forma de carga;
  • compatibilidad;
  • superficie estática;
  • mantenimiento;
  • posibilidades de transformación;
  • requisitos operativos.

9.4 RDI tradicional

RDI sigue siendo un punto de referencia histórico y una técnica útil para aprendizaje y laboratorio. Las implementaciones predeterminadas o públicas pueden ser ampliamente conocidas. Eso no autoriza a convertir una tendencia en una afirmación absoluta sobre todos los productos y contextos.


10. Límites de Crystal Palace

10.1 No es un bypass de EDR

Crystal Palace proporciona herramientas de enlace, composición, hooks y transformación. No decide automáticamente una estrategia de evasión segura ni garantiza resultados frente a un producto.

La detección puede producirse por:

  • comportamiento del agente;
  • infraestructura o tráfico de red;
  • credenciales y acciones realizadas;
  • telemetría de kernel;
  • memoria;
  • contenido estable;
  • errores de implementación;
  • herramientas de postexplotación;
  • correlación con otras señales.

10.2 Compatibilidad limitada

El soporte documentado se centra en C y MinGW-w64, con restricciones sobre características del lenguaje y niveles de optimización. Las bibliotecas y objetos externos deben probarse.

10.3 Complejidad del .spec

Un archivo .spec puede contener dependencias sutiles. Entre los fallos posibles se encuentran:

  • orden incorrecto de operaciones;
  • hooks recursivos;
  • símbolos ausentes;
  • uso de recursos con formato incorrecto;
  • funciones exportadas incompatibles;
  • exclusiones preserve incompletas;
  • transformaciones que no coinciden con la forma desensamblada;
  • diferencias entre versiones.

10.4 Transformaciones heurísticas

Las transformaciones no constituyen una prueba formal de diversidad. Algunas secuencias pueden permanecer estables y el comportamiento general no cambia. Un conjunto amplio de muestras puede permitir identificar invariantes nuevos.

10.5 Depuración y pruebas

Trabajar sobre objetos transformados puede complicar la depuración fuente, la reproducción de errores y el análisis de fallos. Una metodología madura necesita pruebas unitarias de módulos, artefactos de demostración inocuos, análisis estático propio y validación de cada combinación de opciones.


11. Lecciones prácticas para investigación responsable

11.1 Fijar versiones

Todo resultado debe asociarse a una versión o commit. La documentación, los comandos y los proyectos comunitarios evolucionan. Una afirmación correcta hoy puede quedar obsoleta tras un cambio de formato o de API.

11.2 Separar hechos, inferencias y experiencia

Un artículo técnico debería indicar claramente:

  • Documentado: aparece en la documentación oficial.
  • Observado: se reprodujo en un laboratorio descrito.
  • Inferido: se dedujo del comportamiento o del código.
  • Hipótesis: todavía requiere validación.

Esta clasificación evita que una experiencia particular se convierta en una supuesta propiedad universal de la herramienta.

11.3 Medir la variabilidad

En lugar de afirmar que cada build es única, pueden medirse:

  • hashes completos;
  • similitud por función;
  • bloques compartidos;
  • cadenas invariantes;
  • reglas YARA generadas;
  • cambios de tamaño;
  • variación entre semillas y opciones.

La conclusión debe ceñirse a la muestra analizada.

11.4 Usar demostraciones inocuas

Tradecraft Garden utiliza ejemplos independientes del caso de uso, como una DLL o un PICO de demostración. Este modelo permite estudiar enlace, hooks, recursos y transformaciones sin desplegar una capacidad de intrusión real.

11.5 No confundir ausencia de alerta con ausencia de telemetría

Un EDR puede registrar eventos sin generar una alerta visible. También puede retener telemetría para correlación posterior. Las pruebas deben revisar eventos y sensores, no solo la consola de alertas.


12. Conclusiones

Crystal Palace propone un modelo de ingeniería valioso: separar capacidad, servicios y técnicas de instrumentación, y recombinarlos mediante un enlazador especializado. Su lenguaje .spec permite expresar cómo deben cargarse objetos, fusionarse bibliotecas, incorporarse recursos, resolverse funciones, aplicarse hooks y transformarse el resultado.

Su mayor aportación no es una supuesta indetectabilidad. Es la posibilidad de tratar el código independiente de posición y los componentes asociados como elementos componibles, evaluables y reemplazables. Esto puede reducir el acoplamiento de proyectos monolíticos y facilitar el estudio de qué partes de una construcción producen patrones estables.

Las transformaciones como +mutate, +regdance, +blockparty, +shatter, +disco e ised pueden aumentar la variabilidad y romper algunas firmas rígidas. magic participa en determinadas transformaciones de constantes. rule ayuda a generar reglas YARA sobre partes invariantes. Ninguno de estos mecanismos demuestra que las firmas sean imposibles ni que una build sea indetectable.

De la misma forma, attach, redirect, addhook y preserve ofrecen control sobre referencias y hooks, pero su efecto depende de la arquitectura concreta y de que el cargador integre correctamente los servicios necesarios. Crystal Palace no controla por sí solo la memoria, la telemetría de kernel, el comportamiento del agente ni la red.

La integración con Xenon confirma que Crystal Palace puede adaptarse a C2 reales. Al mismo tiempo, el repositorio oficial de Xenon advierte que el proyecto se encuentra en una fase temprana y no realiza afirmaciones de evasión. Los resultados deben publicarse con versiones, configuración y metodología reproducible.

La conclusión más precisa es la siguiente:

Crystal Palace es un enlazador especializado que facilita la construcción modular, la instrumentación y la transformación de código compatible. Puede mejorar la ergonomía del desarrollo PIC y proporcionar herramientas útiles para estudiar variabilidad e invariantes, pero no convierte automáticamente cualquier COFF en PIC, no garantiza evasión y no sustituye las pruebas técnicas ni la disciplina operativa.


Las versiones publicadas el 29 de junio y el 16 de julio de 2026 amplían Crystal Palace en tres direcciones: consolidación de la interfaz de uso, mayor control sobre la transferencia de ejecución y las excepciones, y mejores mecanismos para reutilizar y configurar archivos .spec. Estas novedades no cambian la conclusión principal del artículo: Crystal Palace sigue siendo un enlazador y transformador especializado, no una garantía de evasión. Sin embargo, sí completan de forma importante su modelo de desarrollo modular.

13.1 Nueva interfaz unificada cpl

La versión del 29 de junio de 2026 reemplazó los comandos independientes anteriores, como coffparse, disassemble, link, linkserve y piclink, por un único punto de entrada con el formato cpl [verbo] [argumentos]. La correspondencia publicada incluye cpl coffparse, cpl disassemble, cpl link, cpl server y cpl build. También se incorporó un procedimiento formal de instalación mediante ./install y un sistema opcional de autocompletado para Bash. Fuente: Cruising Forward with the Tradecraft Garden.

Este cambio es principalmente operativo, pero tiene consecuencias importantes para la documentación y la reproducibilidad. Los artículos y scripts antiguos que utilicen piclink, linkserve u otros ejecutables separados deben actualizarse. En un proyecto que pretenda ser reproducible conviene registrar tanto la versión de Crystal Palace como la sintaxis correspondiente, porque una orden válida en una distribución anterior puede haber sido sustituida por su equivalente bajo cpl.

13.2 __transfer: transferencia mediante llamada de cola

La misma versión introdujo __transfer, un intrinsic de enlace exclusivo de x64 que se expande como una llamada de cola. Su contrato documentado espera una función de destino void sin argumentos. En lugar de crear una llamada convencional que deba regresar al llamante directo, la transformación desmonta el frame del llamante y transfiere la ejecución al destino. Cuando el destino termina, retorna al llamante del llamante.

Desde el punto de vista arquitectónico, __transfer proporciona una primitiva más simple para los casos en que un componente de preparación ya ha terminado su trabajo y no necesita recuperar el control. También puede evitar que ese componente permanezca como frame intermedio en la pila. No obstante, no debe confundirse con una solución universal de manipulación de pila: se limita a x64, impone un contrato de función específico y no fabrica por sí mismo una cadena completa de frames sintéticos. Tampoco sustituye la necesidad de metadatos de desenrollado válidos cuando el código o sus excepciones los requieren.

13.3 Nuevos contratos de hashing para DFR

La resolución dinámica de funciones dejó de estar limitada a los contratos ror13 y strings. La versión de junio añadió djb2, fnv1a y sdbm como contratos alternativos de hashing para DFR.

Esta ampliación reduce el acoplamiento a un único algoritmo y permite que distintos servicios de resolución utilicen el contrato que corresponda a su diseño. Sin embargo, cambiar de algoritmo no equivale por sí solo a ocultar el comportamiento ni a evitar detecciones. El resolver, sus patrones de recorrido, las llamadas resultantes y los efectos de la API continúan siendo observables. La elección del hash debe entenderse como una decisión de interoperabilidad y representación, no como una garantía de seguridad.

13.4 Cambios de migración relevantes

La publicación de junio señala varios cambios que pueden afectar a proyectos existentes:

  • Las referencias a los comandos antiguos deben migrarse a sus equivalentes bajo cpl.
  • Los proyectos que utilicen bofprep.spec pueden necesitar importar explícitamente LoadLibraryA, GetProcAddress y BeaconOutput.
  • findFunctionByHash de LibTCG pasó a utilizar GetProcAddress al detectar exportaciones reenviadas.
  • La combinación de __resolve_hook, hooks sobre GetProcAddress y determinadas llamadas de depuración puede activar comprobaciones de seguridad del enlazador.
  • En ese escenario concreto, puede ser necesario excluir el hook dentro de findFunctionByHash mediante preserve, siguiendo la recomendación y la sintaxis de la versión instalada.

Estos cambios son un buen ejemplo de por qué preserve no debe copiarse como una receta universal. Su necesidad aparece por una interacción concreta entre el resolver, una función reenviada, un hook y el sistema de diagnóstico. El proyecto debe justificar cada exclusión según su propio grafo de llamadas.

13.5 Metadatos de desenrollado y control de excepciones

Antes de la publicación de julio, Crystal Palace ya había añadido generación de metadatos de desenrollado de pila. El objetivo es permitir que el sistema operativo pueda recorrer pilas de código PIC, PICO o COFF cuando esos metadatos se registran correctamente, por ejemplo mediante la infraestructura de tablas de funciones de Windows.

La versión del 16 de julio de 2026 amplió este modelo con handlers de excepción específicos del lenguaje, o LSH. La nueva directiva tiene la forma:

catch "function" "lsh_handler"

Con ella se asocia un handler a una función concreta dentro de los metadatos generados. Durante una excepción, Windows consulta la información de desenrollado de los frames y puede invocar el LSH correspondiente. El handler recibe estructuras relacionadas con la excepción, el frame, el contexto y el despachador, y devuelve un valor EXCEPTION_DISPOSITION.

La distinción con VEH es esencial. Un vectored exception handler recibe la primera oportunidad de intervenir antes del recorrido normal de la pila. Un LSH está asociado a la información de excepción de un frame y se consulta durante el proceso de desenrollado. Sus valores de retorno tampoco son intercambiables. Por tanto, migrar de VEH a LSH no consiste únicamente en cambiar el nombre de una función.

Para que este mecanismo funcione, los metadatos de desenrollado del código deben estar registrados y ser coherentes con las funciones ejecutadas. catch no repara automáticamente una pila incorrecta ni convierte cualquier bloque de código en un participante válido del sistema de excepciones de Windows.

13.6 Intrinsics definidos por el usuario

La versión de julio también introdujo intrinsics definidos por el usuario. La sintaxis general publicada es:

intrinsic "__foo" $VAR

Durante una pasada de reescritura, una llamada a __foo se sustituye por el contenido del pack asociado. Esto permite representar ciertos valores o secuencias como una llamada simbólica en el código fuente y decidir su forma final desde la especificación.

Un caso de uso razonable es proporcionar configuración en tiempo de enlace. Por ejemplo, un pack puede generar una instrucción que devuelva un valor configurado por la build. Este mecanismo mejora la separación entre código y configuración y evita crear una API de runtime para datos que pueden fijarse al construir el artefacto.

Su límite es igualmente importante: un intrinsic definido por el usuario es una sustitución de enlace, no una función normal. El código insertado debe respetar la convención de llamada, los registros vivos, el tamaño esperado y las restricciones de seguridad de la transformación. Una sustitución incorrecta puede cambiar la semántica o corromper el estado de ejecución.

13.7 before, after y callnear

Crystal Palace ya permitía ejecutar acciones antes o después de determinados comandos de una especificación. Las versiones recientes ampliaron la precisión de estos hooks para considerar el comando, el tipo de exportación y el nombre del archivo.

El nuevo callnear resuelve inmediatamente el archivo de destino en relación con la especificación que contiene la llamada. Esto evita ambigüedades cuando una config.spec instala un hook que después debe ejecutar un bloque de comandos local. Sin callnear, una ruta relativa podía terminar interpretándose respecto al archivo interceptado y no respecto a la configuración que definió el hook.

Esta mejora resulta especialmente útil para configuraciones reutilizables. Una config.spec puede inyectar comportamiento alrededor de pasos de construcción sin obligar al proyecto principal a duplicar varias directivas before o after. Aun así, este poder debe documentarse con cuidado: una configuración puede modificar la construcción desde fuera del archivo principal, lo que dificulta entender el resultado si no se conserva el conjunto completo de especificaciones.

13.8 Qué significan estas novedades en conjunto

13. Actualizaciones recientes de Crystal Palace: junio y julio de 2026

Las actualizaciones de junio y julio de 2026 muestran que Crystal Palace está evolucionando desde una colección de operaciones de enlace hacia una plataforma más coherente para construir, configurar e instrumentar componentes compatibles.

Las mejoras pueden agruparse así:

  1. Usabilidad y mantenimiento: la interfaz cpl y el instalador reducen la fragmentación de comandos.
  2. Control de flujo: __transfer ofrece una transferencia final de ejecución mediante llamada de cola en x64.
  3. Interoperabilidad: los nuevos contratos DFR permiten resolvers basados en distintos algoritmos.
  4. Correcta integración con Windows: la generación de unwind metadata y los LSH acercan el código transformado al modelo de excepciones y recorrido de pila del sistema operativo.
  5. Configuración en tiempo de enlace: los intrinsics definidos por el usuario permiten sustituir llamadas simbólicas por secuencias generadas.
  6. Composición de especificaciones: callnear y los hooks before y after facilitan configuraciones reutilizables.

Estas características no deberían presentarse como nuevas “técnicas mágicas de evasión”. Su valor principal está en mejorar los contratos, la modularidad, la integración con el sistema operativo y el control sobre la salida. Como ocurre con el resto de Crystal Palace, la seguridad y la calidad final dependen de que los objetos sean compatibles, los metadatos sean correctos y las especificaciones se prueben de forma sistemática.

Referencias

  1. Raphael Mudge, Crystal Palace Documentation, Tradecraft Garden.\ https://tradecraftgarden.org/docs.html
  2. Raphael Mudge, Crystal Palace: A linker and bin2bin code manipulation tool, Tradecraft Garden.\ https://tradecraftgarden.org/crystalpalace.html
  3. Tradecraft Garden, Community Pavilion, proyectos comunitarios y ejemplos.\ https://tradecraftgarden.org/references.html
  4. MythicAgents, Xenon, repositorio oficial. Consultado en agosto de 2026.\ https://github.com/MythicAgents/Xenon
  5. nickswink, Crystal-Kit-Xenon, fork de Crystal Kit adaptado para Xenon. Consultado en agosto de 2026.\ https://github.com/nickswink/Crystal-Kit-Xenon
  6. Lorenzo Meacci, Bypassing EDR in a Crystal Clear Way, 15 de marzo de 2026.\ https://lorenzomeacci.com/bypassing-edr-in-a-crystal-clear-way
  7. Cracked5pider, Stardust, repositorio del proyecto.\ https://github.com/Cracked5pider/Stardust
  8. Stephen Fewer, Reflective DLL Injection, proyecto y publicaciones originales.\ https://github.com/stephenfewer/ReflectiveDLLInjection
  9. TheWover, Donut, repositorio oficial.\ https://github.com/TheWover/donut
  10. Raphael Mudge, Cruising Forward with the Tradecraft Garden, 29 de junio de 2026.\ https://aff-wg.org/2026/06/29/cruising-forward-with-the-tradecraft-garden/
  11. Raphael Mudge, LSH delish, 16 de julio de 2026.\ https://aff-wg.org/2026/07/16/lsh-delish/

← back to blog