Stardust: Arquitectura de implantes PIC y abstracción de shellcode moderna e integracion con HavocC2
Investigacion echa por: Pedro Antonio Marquina (@Fallenangel666)
Introducción
Stardust es un framework de desarrollo de implantes diseñado para generar código posicionalmente independiente (PIC) puro, eliminando la dependencia de estructuras PE (Portable Executable) en tiempo de ejecución. A diferencia de los cargadores reflectivos tradicionales (RDI), que inyectan una DLL completa y simulan el trabajo del cargador del sistema operativo, Stardust se compila directamente como un blob de shellcode crudo.
Su diseño permite a los desarrolladores escribir implantes en C++ moderno utilizando variables globales, literales de cadena y abstracciones de alto nivel, superando las limitaciones clásicas del desarrollo de PIC. Este artículo analiza la arquitectura técnica de Stardust en profundidad — incluyendo sus mecanismos internos, sus limitaciones no documentadas y las lecciones aprendidas al integrarlo con Havoc C2 en un entorno de laboratorio controlado.
Nota: La versión utilizada en esta investigación es una variante customizada del código base original, con modificaciones para adaptar el loader al formato de shellcode del agente Demon de Havoc y corregir comportamientos específicos del pipeline de construcción. El código original de Stardust está disponible en el repositorio oficial de Cracked5pider.
0. Contexto: Qué es un EDR
Antes de entrar en la arquitectura de Stardust, es necesario entender contra qué se diseña. Un EDR (Endpoint Detection and Response) es una solución de seguridad que se instala como agente en el sistema operativo y monitoriza el comportamiento de los procesos en tiempo real, a diferencia de los antivirus tradicionales que se limitan a comparar firmas estáticas de archivos en disco.
Los EDRs modernos más representativos del mercado son CrowdStrike Falcon y Elastic Security (con su agente Elastic Defend). CrowdStrike opera desde un driver de kernel que intercepta llamadas al sistema, monitoriza la creación de procesos, la carga de DLLs y las operaciones de memoria antes de que ocurran. Elastic Security combina un agente en user-mode con reglas de detección basadas en telemetría ETW (Event Tracing for Windows) y un motor de análisis comportamental que correlaciona eventos en tiempo real.
0.1 Qué monitoriza un EDR en la práctica
Las detecciones más comunes que un EDR genera frente a un implant de red team sin evasión son:
Memoria ejecutable privada anónima. Cuando un proceso tiene una región de memoria con permisos de ejecución que no está respaldada por ningún archivo en disco (tipo Private en lugar de Image), el EDR lo marca como sospechoso. Es la firma más básica de shellcode inyectado.
Transición RWX o el patrón RW → RX. Una página de memoria que pasa de escribible a ejecutable es característica de un loader de shellcode. Si además esa página es Private y no tiene módulo asociado, la alerta es prácticamente inmediata. El peor caso es alocar directamente con PAGE_EXECUTE_READWRITE — todos los EDRs comerciales tienen reglas específicas para esto.
Call stack con frames anónimos. Los EDRs con capacidad de inspección de call stack pueden hacer un snapshot del stack de cada thread del proceso y verificar que cada frame de retorno apunte a código dentro de un módulo legítimo. Si algún frame apunta a una dirección sin módulo conocido — es decir, a memoria privada — el thread se marca como sospechoso. Esta técnica es usada por CrowdStrike Falcon y Elastic Security para detectar implants que duermen en memoria anónima.
Syscalls desde direcciones no pertenecientes a ntdll. El EDR puede monitorizar de dónde proviene cada llamada al sistema. En una aplicación legítima, las instrucciones syscall siempre se ejecutan desde dentro de ntdll.dll. Si la instrucción syscall se ejecuta desde memoria privada o desde una DLL inesperada, es una señal de que el código está intentando saltarse los hooks del EDR.
Hooks de user-mode en ntdll. La técnica de detección más extendida consiste en que el EDR modifica el prólogo de las funciones clave de ntdll (como NtAllocateVirtualMemory, NtProtectVirtualMemory, NtCreateThread) para añadir un JMP a su propio código antes de que se ejecute el syscall real. Así intercepta todas las llamadas al sistema y puede bloquearlas o registrarlas.
Tambien varia aveces segun el provedor de EDR y las configuraciones. Asique eso hay que tenerlo en cuenta
0.2 Por qué Stardust evade estas detecciones — en teoría
Stardust no elimina todos los vectores de detección, pero aborda directamente los más comunes:
Module stomping en lugar de memoria privada. En vez de alocar una región anónima nueva para el shellcode, Stardust copia el código dentro de la sección .text de una DLL legítima ya cargada (chakra.dll, por ejemplo). El resultado: la región ejecutable aparece de tipo Image y con el nombre de un módulo firmado por Microsoft. El EDR que busca Private + RX no ve nada.
Transición RW → RX sin RWX. El loader alloca la memoria como RW, copia el shellcode, y solo entonces cambia los permisos a RX. En ningún momento existe una página con los tres permisos simultáneamente. Esto evita las reglas más comunes de detección por permisos de memoria.
Call stack spoofing con draugr. Antes de entrar en el sleep entre beacons, el agente construye una cadena de frames de retorno falsa en el stack del thread, compuesta íntegramente por direcciones dentro de ntdll.dll y kernel32.dll. Cuando el EDR inspecciona el call stack durante el intervalo de reposo, ve solo código de Windows legítimo.
Indirect syscalls. En lugar de llamar a las funciones de ntdll directamente (donde los hooks del EDR están), el stager resuelve el número de syscall (SSN) de cada función de forma dinámica y ejecuta la instrucción syscall desde un gadget dentro del propio .text de ntdll. El EDR ve que el syscall se origina desde ntdll — exactamente igual que una llamada legítima.
La clave de todo esto es que ninguna de estas técnicas por sí sola es suficiente. Son capas que trabajan en conjunto: si el call stack está limpio pero la memoria es privada y anónima, el EDR lo detecta por la memoria. Si la memoria está stompeada pero el call stack tiene frames anónimos, el EDR lo detecta por el stack. Stardust intenta cerrar todos estos frentes simultáneamente.
Añadir que me e estado asesorando sobre si podia enseñar la evasion en mi blog. Devido a que no quiero jugarmela no puedo aclarar si lo que yo explico aqui evade al 100% una infrastructura EDR ni puedo enseñar una demostracion. Si fuera en ponencia o en un estudio respladado si que podria dar estos datos
1. Arquitectura de Secciones y Layout de Memoria
El núcleo del diseño de Stardust reside en el control preciso del layout de memoria mediante un script de enlazador (linker.ld). Dado que el shellcode carece de un cargador del SO, la posición de las instrucciones y los datos debe garantizar la auto-referencia sin colisiones.
1.1 Ordenación Estratégica de Secciones
Stardust segmenta el binario en sub-secciones ordenadas alfabéticamente dentro del segmento .text:
.text$A(Entry Point): Contiene el punto de entrada (stardust), la alineación de pila y las rutinas de localización (RipStart). Debe residir en el byte 0 del binario final..text$B(Core Logic): Alberga la lógica principal del implante en C/C++ compilado..rdata(Read-Only Data): Contiene los literales de cadena y constantes. Su posición intermedia es crítica para el cálculo de direcciones en el templatesymbol<T>— todos los offsets de.rdatase calculan como distancias hacia atrás desde el anclaRipData..text$C(Anchor): Sección final del código ejecutable. ContieneRipData. Actúa como ancla para calcular el tamaño total del implante y como referencia inversa para acceder a datos en.rdata..global(Writable State): Página separada alineada a0x1000para permitir cambios de permisos granulares. Esta sección NO se incluye en el.binextraído porobjcopy— punto crítico con consecuencias directas en runtime.
1.2 El Script de Enlazador
El script fuerza la fusión de estas secciones en un bloque contiguo. Solo .text$A, .text$B, .rdata y .text$C forman el shellcode extraído con objcopy. La sección .global se localiza y habilita en tiempo de ejecución mediante NtProtectVirtualMemory.
1.3 El PE Intermedio y la Extracción
El proceso de compilación genera un PE Windows legítimo como artefacto intermedio. Este PE se descarta — solo se extrae su sección .text:
Esta es la diferencia fundamental con RDI: no hay ningún MZ header, ninguna tabla de imports, ninguna relocation table. El shellcode es completamente autocontenido.
2. Primitivas de Localización: RipStart y RipData
RipStart y RipDataEl shellcode desconoce su dirección de carga en tiempo de ejecución — ASLR y los loaders externos pueden colocarlo en cualquier dirección. Stardust resuelve esto mediante dos funciones ensamblador que establecen los límites del implante de forma completamente dinámica.
2.1 Cálculo de la Base (RipStart)
RipStart)Situado en .text$A (byte 0 del shellcode), RipStart utiliza la técnica call/pop adaptada a x64:
El valor 0x1b (27 bytes) es el tamaño exacto de las instrucciones desde el inicio de stardust hasta la instrucción call RipPtr. NASM lo calcula en tiempo de ensamblaje. El resultado: rax contiene la dirección en memoria donde empieza el shellcode, independientemente de dónde haya sido cargado.
2.2 Ancla de Datos (RipData) y END_OFFSET
RipData) y END_OFFSETPara acceder a cadenas embebidas y marcar el final del código, Stardust coloca una función centinela al final en .text$C:
RipData() devuelve su propia dirección en tiempo de ejecución. La función ocupa exactamente 15 bytes en el binario compilado.
La constante END_OFFSET (definida en common.h, típicamente 0x10) representa cuántos bytes hay desde el inicio de RipData hasta el primer byte de los datos adicionales que el builder añade al final:
Lección aprendida (duramente): Si el builder añade cualquier estructura entre el final del shellcode y los datos — marcadores mágicos, padding de alineación, checksum —
END_OFFSETdeja de ser correcto ystart()lee basura comodemon_size. El resultado es un crash inmediato. El layout del builder debe coincidir byte a byte con lo que esperastart().
3. El Template symbol<T>: Acceso Posicional a Datos
symbol<T>: Acceso Posicional a DatosEl problema fundamental del PIC es que el compilador genera referencias absolutas a strings y constantes en .rdata. En un shellcode cargado en dirección aleatoria, esas referencias apuntan a basura. Stardust resuelve esto con el template symbol<T>:
La macro G_SYM() encapsula este mecanismo para uso cotidiano:
4. Instancia Global y Persistencia de Estado
4.1 La Sección .global y sus Implicaciones
.global y sus ImplicacionesLa sección .global almacena el puntero a la instancia principal (INSTANCE*) y cualquier estado persistente necesario entre callbacks. Durante la inicialización el loader:
Calcula la dirección de
.globalusandoRipStart()+ el offset calculado por el linker.Cambia sus permisos de
RXaRWviaNtProtectVirtualMemory.Escribe el puntero a la estructura
INSTANCErecién asignada en el heap.
4.2 La Trampa de .bss — El Error Más Común
.bss — El Error Más ComúnAquí está la trampa que muerde a casi todo el que trabaja con Stardust por primera vez. Cualquier variable global estándar de C++ que no esté declarada explícitamente en .global terminará en .bss. Y .bss no se extrae por objcopy --dump-section .text.
En tiempo de ejecución, esa variable simplemente no existe en la memoria del shellcode. Cualquier escritura sobre ella crasheará el proceso con EXCEPTION_ACCESS_VIOLATION (C0000005).
Lo identificamos durante el debugging: el crash se manifestaba como C0000005 Write en una dirección alta dentro del rango del módulo stompeado — exactamente el patrón de un write a una región RX que debería ser RW si .global estuviera correctamente habilitada.
5. Resolución de APIs y Hashing en Tiempo de Compilación
Stardust no tiene tabla de importaciones. Todas las APIs de Windows se resuelven en runtime mediante un walk del PEB y comparación de hashes calculados en tiempo de compilación con constexpr:
La resolución ocurre en dos fases:
Módulos: Iterando
PEB->Ldr->InLoadOrderModuleListy comparando hashes de nombres de DLL.Funciones: Parseando la Export Address Table (EAT) de cada DLL y comparando hashes de los nombres exportados.
6. Call Stack Spoofing: Draugr
Stardust integra el mecanismo de spoofing de call stack draugr (de The Cracked Group), que construye una cadena de retorno falsa para evadir EDRs que inspeccionan el call stack en tiempo de ejecución.
6.1 El Problema que Resuelve
Sin stack spoofing, cuando un EDR hace un snapshot del call stack del thread del agente durante el sleep, ve algo así:
Con draugr activo, el mismo snapshot muestra:
Cada frame apunta a código legítimo de Windows. El agente es invisible en el call stack.
6.2 Arquitectura de draugr
El stub draugr.x64.asm manipula el stack frame construyendo la cadena falsa de retorno:
Los parámetros de configuración viven en la estructura DRAUGR_PARAMS:
6.3 Selección del Gadget y Stack Sizing
init_spoof() escanea el segmento .text de ntdll buscando gadgets FF 25 XX XX XX XX (jmp QWORD PTR [rip+disp32]) con un stack frame suficientemente grande (>= MIN_TRAMPOLINE_STACK). Para cada candidato, calcula el tamaño del frame parseando la unwind information de la sección .pdata.
Punto crítico: Los offsets dentro de
BaseThreadInitThunkyRtlUserThreadStartusados como fake return addresses deben apuntar a instruccionesRET(0xC3) válidas. Usar offsets hardcodeados rompe con cada actualización de Windows. La aproximación robusta es buscar dinámicamente el primer0xC3dentro de cada función en el módulo cargado en runtime.
7. Pipeline de Construcción
Formato exacto del payload que consume start() en main.cc:
No debe haber ningún byte de padding ni marcador entre el .bin y el uint32. Cualquier dato intermedio es leído como demon_size, produciendo un valor incorrecto que crashea en el siguiente acceso de memoria.
8. Demostración: Integración con Havoc C2
8.1 Entorno de Prueba
Atacante
Exegol (host fedora 43)
C2
Havoc Framework
Target
Windows 11 x64
Técnica de ejecución
Module Stomping sobre chakra.dll
8.2 Preparación
Compilar Stardust para x64:
Generar el shellcode de Demon desde Havoc y construir el payload:

8.3 Ejecución via Module Stomping
Utilizando stomper.x64.exe (incluido en el repositorio de Stardust como herramienta de test) para inyectar el payload en la sección .text de chakra.dll:

chakra.dll tiene una sección .text de ~6MB — más que suficiente para alojar el payload de 107KB.
8.4 Beacon Activo en Havoc
Tras la ejecución, Stardust:
Resuelve
ntdll.dllykernel32.dlldesde el PEB.Localiza el shellcode de Demon mediante
RipData() + END_OFFSET.Alloca memoria RW, copia el Demon, cambia protección a RX.
Salta al entry point del Demon.
El resultado en el teamserver de Havoc:

9. Lo que Ven las Herramientas de Análisis
Esta sección documenta las observaciones reales durante las pruebas de laboratorio con Process Hacker y x64dbg, comparando directamente la ejecución del shellcode de Demon sin ningún loader frente a la ejecución con Stardust.
9.0 Escenario Baseline — Demon sin Stardust
Antes de analizar lo que hace Stardust, documentamos cómo se ve el Demon ejecutado directamente con un loader mínimo sin ninguna técnica de evasión. Este escenario representa lo que detectaría un EDR sin contramédidas.
Entorno: loader.exe demon.x64.bin — el shellcode crudo de Havoc cargado con VirtualAlloc(RWX) + CreateThread directo.
Mapa de memoria en x64dbg (Alt+M):
La región del Demon tiene tipo PRV (Private), permisos ER (Execute+Read) y la columna de módulo completamente vacía. No pertenece a ningún archivo en disco. Este es el indicador más básico y más detectado por cualquier EDR: memoria ejecutable privada sin respaldo de módulo.
La diferencia entre Current Protection: ER--- e Initial Protection: ERW-- revela el patrón clásico del loader: RWX → RX o RW → RX. El EDR ve esta transición y, combinada con la ausencia de módulo, genera la alerta.
Threads en x64dbg para el mismo proceso (loader sin Stardust, PID del Demon activo):

El hilo del Demon es el ID=6728 — creado tarde y con el mayor número de CPU cycles. Su Entry apunta a 00007FFA07B55A90, que parece ntdll, pero eso es solo la dirección de arranque del wrapper del thread. La dirección real de inicio del shellcode queda oculta en Entry=0000000000000000 del Main.
Call stack del hilo del Demon (ID=6728):

Los tres frames del call stack apuntan a direcciones dentro del rango 0x22FED870000 — exactamente la región privada anónima identificada en el mapa de memoria. Un EDR con inspección de call stack generaría alerta inmediata: código ejecutándose desde memoria sin módulo asociado.
Syscall visible desde memoria anónima:
En el Main Thread se observa ntdll.ZwAllocateVirtualMemory llamado desde la cadena de enumeración de red (iphlpapi.GetAdaptersInfo → ... → ZwAllocateVirtualMemory). La instrucción syscall proviene directamente del shellcode en la región privada — sin ninguna indirección. Un EDR que monitorice el origen de los syscalls lo ve con claridad.
Resumen del escenario baseline:
Tipo de región
PRV (Private)
✅ Sí
Permisos
ER sin módulo
✅ Sí
Frames call stack
Direcciones anónimas
✅ Sí
Origen syscalls
Desde memoria privada
✅ Sí
Módulo asociado
Ninguno
✅ Sí
9.1 Escenario con Stardust — Process Hacker
Sin module stomping, el agente residiría en una región privada anónima ejecutable — señal de alerta inmediata:
Con module stomping activo, Process Hacker muestra:

El código del agente aparece como parte del espacio de memoria de chakra.dll. Un analista revisando las regiones de memoria no ve ningún ejecutable privado anónimo. La única forma de detectarlo sería comparar el contenido en memoria de la sección .text de chakra.dll contra el archivo en disco.
Call stack del thread durante sleep (con stack spoofing activo). En la pestaña de threads de Process Hacker:

Ningún frame apunta a memoria privada. El thread parece legítimo en su totalidad.
9.2 Escenario con Stardust — x64dbg
Como se a mencionado anteriormente mi stardus esta modificado personalmente para implementar multiples tecnicas. Los resultados que yo enseño SON DE MI CONFIGURACION, NO DE STARDUSRT BASE. y pueden variar segun tu configuracion
Con stomper.x64.exe payload.x64.bin (Demon via Stardust), la misma inspección en x64dbg muestra resultados radicalmente diferentes.
Mapa de memoria (Alt+M) — región del Demon:

La región del Demon aparece con permisos RW — sin ejecución. Ekko está activo: durante el intervalo de sleep entre beacons, el Demon cifra su propio contenido en memoria y cambia los permisos de RX a RW. Un escáner de memoria que capture este instante no encuentra ninguna región ejecutable anónima — solo una región privada de datos, aparentemente inerte.
Threads en x64dbg con Stardust activo:

El hilo ID=6068 es el Demon. Su Entry es 0000029169C90000 — la dirección de inicio del shellcode en la región privada. Con CPU cycles de 0xD9C5DD2 (el más alto con diferencia), es inequívocamente el hilo del implant. El hilo ID=10056 (mismo RIP, WaitReason=UserRequest) es el hilo de Ekko gestionando el timer del sleep.
Call stack del hilo del Demon (ID=6068):

Cero frames anónimos. Todos los frames pertenecen a ntdll.dll y kernel32.dll. Un EDR inspeccionando este call stack no encuentra ninguna señal de alerta.
Module stomping visible en el Main Thread:

El stager de Stardust aparece en el call stack del Main Thread ejecutándose desde dentro de chakra.dll. El module stomping es verificable directamente: el código que lanzó el proceso del Demon tiene su origen dentro de un módulo legítimo de Microsoft.
Tabla comparativa final:
Tipo de región del Demon
PRV, ER, sin módulo
PRV, RW (Ekko en sleep)
Permisos en reposo
Siempre ejecutable (ER)
No ejecutable (RW) durante sleep
Frames call stack
Direcciones anónimas
ntdll + kernel32 legítimos
Origen del stager
Memoria privada anónima
chakra.dll (module stomping)
Syscalls
Directas desde shellcode
Indirectas via gadget en ntdll
9.3 Workflow de Debugging durante el Desarrollo
Durante el desarrollo usamos x64dbg extensivamente para diagnosticar fallos. El flujo que demostró ser más efectivo:
Paso 1: Insertar __debugbreak() al inicio de start()
Paso 2: Lanzar el stomper desde x64dbg
Al saltar el EXCEPTION_BREAKPOINT, estamos dentro del shellcode. La ventana de módulos confirma que RIP está dentro de chakra.dll:
Paso 3: Identificar el crash por código de excepción
Durante el desarrollo encontramos los siguientes patrones de fallo:
C0000005 Write
Dentro del módulo stompeado (dirección alta)
Variable global en .bss — no existe en el .bin, escritura sobre región RX
C0000005 Read
Dirección baja (0x00–0xFF)
Null pointer dereference — función no resuelta en PEB walk
C0000005 Read
Dirección alta dentro del módulo
END_OFFSET incorrecto — start() lee basura como demon_size y luego como puntero
80000003
—
__debugbreak() alcanzado — normal durante debugging
El crash de END_OFFSET fue el más difícil de diagnosticar. Los registros en el momento del fallo mostraban:
La causa: nuestro builder añadía 4 bytes de padding de alineación entre el shellcode y el uint32 de tamaño. END_OFFSET era 0x10 pero con ese padding debería haber sido 0x14. Solución: eliminar el padding del builder para que el uint32 quede inmediatamente contiguo al último byte del .bin.
Paso 4: Validar el descifrado con un breakpoint en VirtualProtect
Poniendo un breakpoint justo antes de la llamada a VirtualProtect(stomped_region, RX), el buffer temporal pPlain todavía contiene el shellcode descifrado en texto claro:
Después de VirtualFree(pPlain), esa región desaparece — no queda ningún artefacto con el shellcode en claro en memoria.
10. Metodología de Debugging: Referencia Rápida
Cuando el shellcode no produce beacon, esta es la secuencia de diagnóstico:
Breakpoints estratégicos en start()
start()Diagnóstico por excepción
C0000005 Write en módulo stompeado
Escritura en RX
Variable global en .bss. Añadir __attribute__((section(".global")))
C0000005 Read en dirección 0x0–0xFF
Null pointer
Función no resuelta en PEB walk. Verificar hashes
C0000005 Read en dirección alta sin módulo
Puntero basura
END_OFFSET incorrecto. Auditar el builder byte a byte
Beacon nunca llega, sin crash
Ejecución silenciosa
Resolver APIs de red — verificar que WinHttpOpen etc. se resuelven
Validar demon_size
demon_sizeUn valor correcto de demon_size es el tamaño real del shellcode de Demon: típicamente 0x11000–0x1B000 (70–110 KB). Si el valor es pequeño (0x1, 0x90, 0x10) o absurdo (0xDEADC0DE), END_OFFSET es incorrecto.
11. Comparativa Arquitectónica: Stardust vs. Crystal Palace
Ambos proyectos abordan el desarrollo PIC pero representan filosofías opuestas.
Abstracción vs. Automatización
Stardust requiere que el desarrollador gestione explícitamente el layout, las variables globales y los accesos a datos. Control total, pero alta responsabilidad.
Crystal Palace adopta un enfoque de transformación post-compilación. Usa archivos .spec para reescribir el código máquina ya compilado automáticamente.
Gestión de Variables Globales
En Stardust, las variables globales fuera de .global van a .bss y crashean silenciosamente. Crystal Palace resuelve esto con fixbss — transforma referencias a .bss en accesos relativos de forma transparente, sin cambios en el código fuente.
Mutación de Binarios
Crystal Palace ofrece +disco (barajado de funciones) y +mutate (mutación de constantes) post-compilación. Stardust produce un blob estático — no hay mutación del shellcode en sí.
Resumen
Control total sobre el layout
✅
❌
C++ moderno (constexpr, templates)
✅
Agnóstico
Globals automáticos
❌ (manual)
✅ (fixbss)
Mutación post-build
❌
✅
Curva de aprendizaje
Alta
Media
Tamaño del stager
~4 KB
Variable
Conclusiones
Stardust demuestra que es posible escribir shellcode complejo con la ergonomía de C++ moderno: variables globales, templates, abstracciones de alto nivel — sin renunciar a la independencia posicional.
La integración con Havoc C2 funciona de forma efectiva en laboratorio: el agente Demon ejecutándose dentro del espacio de memoria de chakra.dll, con stack spoofing activo, sin ninguna región RWX en ningún momento, sin artefactos de shellcode en claro en memoria tras la ejecución del loader, y con un call stack completamente limpio visible desde Process Hacker.
Los problemas que encontramos — .bss silencioso, END_OFFSET roto por padding inesperado del builder — no están documentados. Son trampas que solo se descubren en ejecución real, y espero que esta investigación ahorre tiempo a quien trabaje con estas herramientas.
Las invariantes que no puedes olvidar:
.bssno existe en el shellcode extraído. Todo global debe ir en.globalo pasarse como parámetro explícito.END_OFFSETdebe coincidir byte a byte con el layout real del builder. Sin padding. Sin marcadores mágicos intermedios.Nunca
RWX. La transición es siempreRW → RX.El módulo objetivo del stomp debe tener
.textsuficientemente grande para el payload completo.RipData()es un ancla, no una dirección de datos. Los datos están enRipData() + END_OFFSET.
Referencias
[1] Cracked5pider, "Modern implant design: position independent malware development," 5pider.net, Jan. 27, 2024. https://github.com/Cracked5pider/ [2] Stardust Project Repository — -- https://github.com/Cracked5pider/Stardust [3] The Cracked Group, "draugr: Call Stack Spoofing," TCG Tradecraft Repository, 2024. [4] Crystal Palace Documentation, "Overview and Linker Script Language," Tradecraft Garden, 2024. https://tradecraftgarden.org/crystalpalace.html [5] Havoc Framework, "Demon C2 Agent" — https://github.com/HavocFramework/Havoc https://github.com/HavocFramework/Havoc [6] am0nsec / smelly__vx, "Hell's Gate" — https://github.com/am0nsec/HellsGate
Nota: Este artículo tiene fines exclusivamente educativos y de investigación en seguridad. Las técnicas descritas deben utilizarse únicamente en entornos controlados y con autorización explícita. Y no me hago responsable de cualquier uso indevido
Última actualización