LinuxParty
NUESTRO SITIO necesita la publicidad para costear hosting y el dominio. Por favor considera deshabilitar tu AdBlock en nuestro sitio. También puedes hacernos una donación entrando en linuxparty.es, en la columna de la derecha.
Durante años, desde que los ordenadores han estado al alcance de las más calenturientas mentes de los hackers de antaño, multitud de extrañas ideas han pasado por sus cabezas, muchas de las cuales fueron llevadas a la práctica y de entre todas ellas, una que creó escuela (sobre todo allá por los años ochenta y principios de los noventa) fue la de infección de binarios. Escribir un programa que puede inocularse a otro, pegársele como un parásito y extenderse por ahí, suena casi a ciencia ficción, ¿cómo resistirse? lo largo de la historia de la
computación, fueron múltiples las implementaciones prácticas de la
infección de archivos ejecutables. Algunos veteranos recordarán las
historias del paquistaní Brain, el Virdem, el Vienna, el WHALE y el más
moderno CIH.
Todos estos son diversos tipos
de virus de DOS/Windows que infectaban ejecutables tipo COM y EXE, y hay
mucha literatura acerca de infección sobre este tipo de binarios. Sin
embargo, ya no hay tanto (y menos en español) acerca de infección bajo
Unix. Lo bueno -o malo, según se mire- de Unix es que de aquí a hace
unos años existe un estándar de facto en lo que al tema de formato de
ejecutables se refiere. Hablo, por supuesto del Executable and Linkable
Format (ELF) cuyo éxito motiva el siguiente artículo.
Y es a partir de aquí cuando debo introducir el DISCLAIMER
de rigor para que los geos no me hagan una desagradable visita a la
puerta de mi casa. La única finalidad de esta publicación es ilustrar
por cuántos sitios un ELF puede ser explotado para a) securizar nuestras
aplicaciones incluyendo diversas comprobaciones al arranque o b)
aplicar lo expuesto como alguna retorcida técnica a utilizar en algún
CTF o como simple curiosidad para aquellos a los que nos gusta jugar con
cosas así de raras. El hacer algo más allá ya no es que me limite a
decir que es responsabilidad del que lo usa, que cae de cajón, si no que
afirmo categóricamente que es mala idea. No es la primera vez que un
bicho de estos se escapa de la cámara de incubación para la que ha sido
diseñado, y sus desafortunadas leyendas perduran.
Y aclarado esto, saquemos nuestras herramientas de doctor Frankenstein. Vamos a pensar cómo se podría crear un monstruo.
Como este artículo toca tantas
cosas, y probablemente me enfrento a un conjunto de lectores con muy
diversos grados de conocimiento, he decidido dividirlo en 5 entregas
para que cada cual salte a la que le interese:
- Introducción al formato ELF y el código PIC
- Técnicas de inyección.
- Técnicas de activación.
- Técnicas de armouring y antidebug.
- Securización.
Estas entregas van a ser en general bastante técnicas, por lo que sería bueno que el lector estuviese familiarizado con:
- El lenguaje C y el compilador de C de GNU
- Unix en general, y Linux en particular.
- Programación en ensamblador para x86 (32 bits)
- El inline assembly de GCC.
Hay mucho que escribir
sobre este tema, y dedicar el humilde espacio que una entrada de blog
puede darme me obligará a saltarme muchas cosas. Aún así, espero poder
aproximarme a la realidad de la explotación de un binario ELF.
El formato ELF
El
formato ELF es un estándar que nació en el seno de los Unix System
Laboratories de AT&T Bell allá por el 1997 con la intención de
superar las limitaciones del antiguo formato a.out. A día de hoy es
usado por la mayoría de sistemas *nix como Linux, BSD o Solaris sobre
procesadores tanto de 32 como de 64 bits, little endian o big endian,
dando como resultado la existencia de dos grandes subconjuntos de
formatos: El ELF de 32 bits y el ELF de 64 bits, cuyas cabeceras son
ligeramente diferentes debido a las diferencias en el ancho de palabra.
El formato ha sido pensado tanto
para ejecutables como para bibliotecas dinámicas, pasando por ficheros
objeto y volcados de memoria, aunque este artículo va a estar enfocado
sobre todo hacia el primero.
En cualquier caso, se suele decir que
un fichero ELF se compone de una cabecera al principio del archivo con
unos números mágicos apropiados e información general (del tipo "yo soy
un ELF ejecutable para tal procesador y me ejecuto a partir de aquí") y
de (hasta) dos tablas de cabeceras que sirven para dotar al fichero ELF
de dos "vistas": una vista de segmentos (la cual es indexada mediante un array de estructuras llamado tabla de cabeceras de programa) y una vista de secciones (indexada por otro tipo de array de estructuras llamado tabla de cabeceras de sección).
Si bien las dos sirven para definir de algún modo el tipo de
información que alberga nuestro fichero ELF, la primera es necesaria
para decirle al kernel (o al enlazador si nuestro binario es dinámico)
qué porciones de nuestro fichero se cargan en qué partes del espacio de
direcciones virtuales y con qué permisos (lectura / escritura /
ejecución), y la segunda tiene como finalidad darle al enlazador
información sobre qué bibliotecas necesita cargar, qué símbolos debe
importar, qué símbolos exporta, etc.
Lo importante de ambas tablas es que no cubren todo el binario,
y en la tabla de segmentos habrá zonas que incluso se solapen. Esto
tiene como consecuencia que existirán zonas no referenciadas por ninguna
de las dos tablas, existirán espacios vacíos o gaps que
podríamos modificar a nuestro antojo de forma totalmente asintomática de
cara al funcionamiento del binario (aquí probablemente ya haya alguno
al que se le pongan los dientes largos).
Este estudio se centrará en el
ELF ejecutable para x86, o sea que trabajaremos con ELFs de 32 bits y
little endian. En teoría, esto se podría extrapolar a otros formatos (de
hecho, me habría gustado probar esto en un UltraSPARC IIe a 64 bits,
pero el router que lo saca a Internet ha muerto :( espero poder hacer un
anexo más adelante cuando tenga el cacharro de nuevo en mis manos),
pero de momento nos conformaremos con esta arquitectura, a día de hoy
todavía muy extendida y bien conocida por muchos.
A lo largo de esta serie de
entregas voy a referirme constantemente a las diversas estructuras que
son contenidas por los ficheros ELF, así que a modo de referencia rápida
incluiré una pequeña referencia de las mismas. Para trabajar con ellas
desde C bastará con incluir el fichero de cabecera < elf.h >. La
cabecera del ELF32 es tal que así:
Leer aquí el resto del artículo.
Leer aquí el resto del artículo.
-
Seguridad
- Drones, vigilancia y reconocimiento facial: una startup llamada 'Sauron' presenta un sistema de seguridad para el hogar de estilo militar
- Conexión Segura NFS en Linux, Tunelizar NFS sobre SSH y Configuración de NFS sobre SSH para Mayor Seguridad
- ¿Olvidó su contraseña? Cinco razones por las que necesita un administrador de contraseñas
- Cómo limitar las conexiones SSH (puerto TCP 22) con ufw en Ubuntu Linux
- Utilizar ssh sin contraseña con ssh-keygen y ssh-copy-id
- Millones de teléfonos móviles podrían ser vulnerables a la vigilancia del gobierno chino
- Cómo limitar las conexiones SSH a la red local en Linux
- Los televisores inteligentes son como un «caballo de Troya digital» en los hogares
- Snort para Windows, detección de Intrusos y seguridad.
- Detección de Intrusiones con las herramientas: BASE y Snort.
- El Sistema de Detección de Intrusos: Snort. ( Windows y Linux )
- Configuración con Ejemplos de Snort para Windows, detección de intrusiones
- ¿El gobierno de EE. UU. ignoró la oportunidad de hacer que TikTok fuera más seguro?
- ¿Qué es SSH y cómo se utiliza? Los conceptos básicos de Secure Shell que necesitas saber
- Asegurar memcached del servidor, para evitar amplificar ataques DDoS