Articulo de referencia

Shellcode

El shellcode es un código ejecutable diseñado para usarse como carga útil para explotar una vulnerabilidad de software . El término incluye "shell" porque originalmente describí...

El shellcode es un código ejecutable diseñado para usarse como carga útil para explotar una vulnerabilidad de software . El término incluye "shell" porque originalmente describía un ataque que abría una consola de comandos que el atacante podía usar para controlar la máquina objetivo, pero cualquier código que se inyecte para obtener acceso no permitido puede denominarse shellcode. Por esta razón, algunos consideran que el nombre shellcode es impreciso. [ 1 ]

Un ataque suele inyectar código ejecutable en un proceso antes o durante la explotación de una vulnerabilidad para obtener el control. El contador de programa se establece en el punto de entrada del shellcode para que este se ejecute. El despliegue del shellcode se suele realizar incluyendo el código en un archivo que un proceso vulnerable descarga y luego carga en su memoria.

La sabiduría popular dicta que, para maximizar la efectividad, la carga útil de un shellcode debe ser pequeña. [ 2 ] El código máquina proporciona la flexibilidad necesaria para lograr el objetivo. Los autores de shellcode aprovechan pequeños códigos de operación para crear shellcode compacto. [ 3 ] [ 4 ]

Tipos

Local

Un ataque de shellcode local permite al atacante obtener privilegios de acceso elevados en su ordenador. En algunos casos, la explotación de una vulnerabilidad puede lograrse provocando un error, como un desbordamiento de búfer . Si tiene éxito, el shellcode permite el acceso a la máquina mediante los privilegios elevados otorgados al proceso objetivo.

Remoto

Un ataque remoto mediante shellcode se dirige a un proceso que se ejecuta en una máquina remota , ya sea en la misma red local , intranet o internet . Si tiene éxito, el shellcode permite acceder a la máquina objetivo a través de la red. Normalmente, el shellcode abre una conexión de socket TCP/IP para acceder a una consola en la máquina objetivo.

Un ataque remoto de shellcode se puede categorizar según su comportamiento. Si el shellcode establece la conexión, se denomina shell inversa o shellcode de conexión inversa . Por otro lado, si el atacante establece la conexión, el shellcode se denomina bindshell porque se enlaza a un puerto específico de la máquina de la víctima. Un bindshell de puerto aleatorio omite la parte del enlace y escucha en un puerto aleatorio. [ a ] ​​Un shellcode de reutilización de sockets es un exploit que establece una conexión con el proceso vulnerable que no se cierra antes de que se ejecute el shellcode, de modo que este pueda reutilizar la conexión para permitir el acceso remoto. El shellcode de reutilización de sockets es más complejo, ya que necesita averiguar qué conexión reutilizar y la máquina puede tener muchas conexiones abiertas. [ 5 ]

Un cortafuegos puede detectar las conexiones salientes realizadas por shellcode de conexión inversa, así como las conexiones entrantes realizadas por shells de enlace, ofreciendo así cierta protección contra ataques. Incluso si el sistema es vulnerable, un cortafuegos puede impedir que el atacante se conecte al shell creado por el shellcode. Una de las razones por las que se utiliza el shellcode de reutilización de sockets es que no crea nuevas conexiones y, por lo tanto, es más difícil de detectar y bloquear.

Descargar y ejecutar

Un ataque de shellcode de descarga y ejecución descarga y ejecuta malware en el sistema objetivo. Este tipo de shellcode no crea una consola, sino que ordena a la máquina que descargue un archivo ejecutable específico de la red y lo ejecute. Actualmente, se utiliza comúnmente en ataques de descarga automática , donde la víctima visita una página web maliciosa que intenta ejecutar dicho shellcode para instalar software en su equipo.

Una variante de este ataque descarga y carga una biblioteca . [ 6 ] [ 7 ] Las ventajas de esta técnica son que el código puede ser más pequeño, que no requiere que el shellcode inicie un nuevo proceso en el sistema objetivo y que el shellcode no necesita código para limpiar el proceso objetivo, ya que esto puede hacerlo la biblioteca cargada en el proceso.

Escenificado

Cuando la cantidad de datos que un atacante puede inyectar en el proceso objetivo es demasiado limitada para lograr el efecto deseado, puede ser posible desplegar el shellcode en etapas que proporcionen progresivamente mayor acceso. La primera etapa podría limitarse a descargar el código de la segunda etapa, que a su vez proporcionaría el acceso deseado.

Búsqueda de huevos

Un ataque de shellcode de búsqueda de huevos es un ataque por etapas en el que el atacante puede inyectar shellcode en un proceso, pero desconoce su ubicación dentro del mismo. Un shellcode de segunda etapa, generalmente más pequeño que el primero, se inyecta en el proceso para buscar en su espacio de direcciones el primer shellcode (el huevo ) y ejecutarlo. [ 8 ]

Tortilla

Un ataque de shellcode tipo omelet, similar a la búsqueda de huevos, busca múltiples bloques pequeños de datos ( huevos ) y los combina en un bloque más grande ( omelet ) que luego se ejecuta. Esto se utiliza cuando un atacante tiene un límite en el tamaño del código inyectado, pero puede inyectar varios. [ 9 ]

Codificación

El código shell se suele escribir para sortear las restricciones de datos que permite un proceso. Las técnicas generales incluyen:

Optimizar para tamaño

Optimiza el código para reducir su tamaño.

Código automodificable

Modificar su propio código antes de ejecutarlo para utilizar valores de bytes que de otro modo estarían restringidos.

Cifrado

Para evitar la detección de intrusiones , codifique como autodescifrable o polimórfico .

Codificación de caracteres

Un ataque dirigido a un navegador podría ofuscar el código malicioso en una cadena JavaScript utilizando una codificación de caracteres expandida. [ 10 ] Por ejemplo, en la arquitectura IA-32 , aquí hay dos instrucciones de no operación sin codificar (utilizadas en una diapositiva NOP ):

90 NOP 90 NOP

Tal como está codificado:

Libre de nulos

El shellcode debe escribirse sin bytes de valor cero cuando se pretende inyectarlo en una cadena terminada en nulo que se copia en el proceso objetivo mediante el algoritmo habitual (es decir, strcpy ) de terminar la copia en el primer byte cero , llamado carácter nulo en los conjuntos de caracteres comunes . Si el shellcode contuviera un nulo, la copia se truncaría y no funcionaría correctamente. Para producir código sin nulos a partir de código que los contiene, se pueden reemplazar las instrucciones de máquina que contienen ceros por instrucciones que no los contienen. Por ejemplo, en la arquitectura IA-32, la instrucción para establecer el registro EAX en 1 contiene ceros como parte del literal ( 1se expande a 0x00000001).

B8 01000000 MOV EAX,1

Las siguientes instrucciones logran el mismo objetivo (EAX conteniendo 1) sin bytes cero incrustados, estableciendo primero EAX a 0 y luego incrementándolo a 1:

33C0 XOR EAX,EAX 40 INC EAX
Texto

Un shellcode alfanumérico consiste únicamente en caracteres alfanuméricos (0–9, A–Z y a–z). [ 11 ] [ 12 ] Este tipo de codificación fue creado por hackers para ofuscar código máquina dentro de lo que parece ser texto plano . Esto puede ser útil para evitar la detección del código, para permitir que el código pase a través de filtros que eliminan los caracteres no alfanuméricos de las cadenas. [ b ] Un tipo de codificación similar se llama código imprimible y utiliza todos los caracteres imprimibles (alfanuméricos más símbolos como  !@#%^&*). Una variante igualmente restringida es el código ECHOable que no contiene ningún carácter que no sea aceptado por el comando ECHO . Se ha demostrado que es posible crear shellcode que parezca texto normal en inglés. [ 13 ] Escribir dicho shellcode requiere una comprensión profunda de la arquitectura del conjunto de instrucciones de las máquinas objetivo. Se ha demostrado que es posible escribir código alfanumérico que sea ejecutable en más de una máquina, [ 14 ] constituyendo así código ejecutable de arquitectura múltiple .

Rix publicó una solución alternativa en Phrack 57 [ 11 ] donde demuestra que es posible convertir cualquier código en código alfanumérico. A menudo, se utiliza código automodificable porque permite que el código tenga valores de bytes que de otro modo no estarían permitidos, reemplazando los valores codificados en tiempo de ejecución. Se puede crear un decodificador automodificable que inicialmente solo utilice los bytes permitidos. El código principal del shellcode se codifica, también utilizando solo bytes dentro del rango permitido. Cuando se ejecuta el shellcode de salida, el decodificador modifica su código para usar las instrucciones que requiere y luego decodifica el shellcode original. Después de decodificar el shellcode, el decodificador le transfiere el control. Se ha demostrado que es posible crear shellcode arbitrariamente complejo que se ve como texto inglés normal. [ 13 ]

El software moderno utiliza Unicode para admitir la internacionalización y la localización . A menudo, el texto ASCII de entrada se convierte a Unicode antes de su procesamiento. Cuando un carácter ASCII ( generalmente Latin-1 ) se transforma a UTF-16 (Unicode de 16 bits), se inserta un byte cero después de cada byte (carácter) del texto original. Obscou demostró en Phrack 61 [ 12 ] que es posible escribir shellcode que se ejecute correctamente después de esta transformación. Existen programas que pueden codificar automáticamente cualquier shellcode en un shellcode alfanumérico a prueba de UTF-16, basados ​​en el mismo principio de un pequeño decodificador automodificable que decodifica el shellcode original.

Compatibilidad

Generalmente, el shellcode se implementa como código máquina, ya que permite un acceso relativamente desprotegido al proceso objetivo. Dado que el código máquina es compatible dentro de un contexto informático relativamente limitado ( procesador , sistema operativo , etc.), un fragmento de shellcode tiene una compatibilidad limitada . Además, dado que un ataque de shellcode tiende a funcionar mejor cuando el código es pequeño y apuntar a múltiples exploits aumenta el tamaño, normalmente el código apunta a un solo exploit. No obstante, un único fragmento de shellcode puede funcionar para múltiples contextos y exploits. [ 15 ] [ 16 ] [ 17 ] La versatilidad se puede lograr creando un único fragmento que contenga una implementación para múltiples contextos. El código común se ramifica a la implementación para el contexto de tiempo de ejecución.

Análisis

Como el shellcode generalmente no es ejecutable por sí solo, para estudiar su funcionamiento, normalmente se carga en un proceso especial. Una técnica común consiste en escribir un pequeño programa en C que contenga el shellcode como datos (es decir, en un búfer de bytes) y transfiera el control a las instrucciones codificadas en el puntero a la función de datos o en el código ensamblador en línea . Otra técnica consiste en utilizar una herramienta en línea, como shellcode_2_exe , para incrustar el shellcode en un ejecutable predefinido que luego se puede analizar con un depurador estándar. También existen herramientas especializadas para el análisis de shellcode, como el proyecto iDefense sclog (lanzado originalmente en 2005 en el Malcode Analyst Pack). Sclog está diseñado para cargar archivos de shellcode externos y ejecutarlos dentro de un marco de registro de API. También existen herramientas de análisis de shellcode basadas en emulación, como la aplicación sctest , que forma parte del paquete multiplataforma libemu. Otra herramienta de análisis de shellcode basada en emulación, construida alrededor de la biblioteca libemu, es scdbg , que incluye una consola de depuración básica y funciones de generación de informes integradas.

Véase también

Notas

  1. El puerto aleatorio de bindshell es el shellcode de bindshell estable más pequeño para x86_64 disponible hasta la fecha.
  2. En parte, dichos filtros fueron una respuesta a las vulnerabilidades de los shellcodes no alfanuméricos.

Referencias

  1. Foster, James C.; Price, Mike (12 de abril de 2005). Sockets, Shellcode, Porting, & Coding: Reverse Engineering Exploits and Tool Coding for Security Professionals . Elsevier Science & Technology Books. ISBN 1-59749-005-9.
  2. Anley, Chris; Koziol, Jack (2007). Manual del programador de shell: descubrimiento y explotación de vulnerabilidades de seguridad (2.ª ed.). Indianápolis, Indiana, EE. UU.: Wiley. ISBN  978-0-470-19882-7OCLC 173682537 
  3. Foster, James C. (2005). Ataques de desbordamiento de búfer: detección, explotación y prevención . Rockland, MA, EE. UU.: Syngress. ISBN 1-59749-022-9OCLC 57566682 
  4. "Tiny Execve sh - Assembly Language - Linux/x86" . GitHub . Consultado el 1 de febrero de 2021 .
  5. BHA (2013-06-06). "Shellcode/Socket-reuse" . Recuperado el 2013-06-07 .
  6. SkyLined (11/01/2010). "Se ha publicado el shellcode Download and LoadLibrary" . Archivado del original el 23/01/2010 . Consultado el 19/01/2010 .
  7. "Descargar y cargar código shell de biblioteca para Windows x86" . 11 de enero de 2010. Consultado el 19 de enero de 2010 .
  8. Skape (09-03-2004). "Búsqueda segura en el espacio de direcciones virtuales del proceso" (PDF) . nologin . Recuperado el 19-03-2009 .
  9. SkyLined (16 de marzo de 2009). "w32 SEH omelet shellcode" . Skypher.com. Archivado del original el 23 de marzo de 2009. Consultado el 19 de marzo de 2009 .
  10. "Se detectó un gran número de patrones de escape en JavaScript" . Archivado del original el 3 de abril de 2015.
  11. 1 2 rix (11/08/2001). "Escribiendo shellcodes alfanuméricos ia32" . Phrack . 0x0b (57). Phrack Inc. #0x0f de 0x12. Archivado del original el 08/03/2022 . Recuperado el 26/05/2022 .
  12. 1 2 obscou (2003-08-13). "Building IA32 'Unicode-Proof' Shellcodes" . Phrack . 11 (61). Phrack Inc. #0x0b de 0x0f. Archivado del original el 26-05-2022 . Recuperado el 29-02-2008 .
  13. 1 2 Mason, Joshua; Small, Sam; Monrose, Fabian; MacManus, Greg (noviembre de 2009). English Shellcode (PDF) . Actas de la 16.ª conferencia ACM sobre seguridad informática y de comunicaciones. Nueva York, NY, EE. UU. págs. 524–533 . Archivado (PDF) del original el 26 de mayo de 2022. Recuperado el 10 de enero de 2010 . (10 páginas)
  14. "Explicación del shellcode alfanumérico de 64 bits y multiarquitectura (x86)" . Black Hat Academy. Archivado del original el 21 de junio de 2012.
  15. eugene (11 de agosto de 2001). "Arquitectura que abarca Shellcode" . Phrack . Phrack Inc. #0x0e de 0x12. Archivado del original el 9 de noviembre de 2021. Recuperado el 29 de febrero de 2008 .
  16. nemo (13-11-2005). "OSX - Shellcode multiarquitectura" . Divulgación completa . Archivado del original el 26-05-2022 . Recuperado el 26-05-2022 .
  17. Cha, Sang Kil; Pak, Brian; Brumley, David ; Lipton, Richard Jay (2010-10-08) [2010-10-04]. Programas independientes de la plataforma (PDF) . Actas de la 17.ª conferencia ACM sobre seguridad informática y de comunicaciones (CCS'10). Chicago, Illinois, EE. UU.: Universidad Carnegie Mellon , Pittsburgh, Pensilvania, EE. UU. / Instituto Tecnológico de Georgia , Atlanta, Georgia, EE. UU. pp. 547–558 . doi : 10.1145/1866307.1866369 . ISBN  978-1-4503-0244-9. Archivado (PDF) del original el 26-05-2022 . Recuperado el 26-05-2022 .(12 páginas) (Véase también:)
  • Base de datos Shell-Storm de shellcodes multiplataforma.
  • Introducción a los desbordamientos de búfer y al código malicioso (shellcode)
  • Conceptos básicos de shellcoding (PDF) Una descripción general del shellcoding x86 por Angelo Rosiello
  • Introducción al desarrollo de shellcode
  • Contiene ejemplos de shellcode para arquitecturas x86 y no x86, así como una interfaz en línea para la generación y codificación automática de shellcode, del Proyecto Metasploit.
  • un archivo de shellcode, ordenado por sistema operativo .
  • Tutorial de diseño de shellcode para Microsoft Windows y Linux, desde lo básico hasta lo avanzado .
  • Tutorial de shellcode para Windows y Linux con ejemplos paso a paso .
  • El diseño de shellcode desmitificado
  • ALPHA3 Un codificador de shellcode que puede convertir cualquier shellcode en shellcode alfanumérico, tanto en Unicode como en ASCII, en mayúsculas y con mayúsculas y minúsculas.
  • Cómo escribir código shell pequeño, por Dafydd Stuttard. Un documento técnico que explica cómo hacer que el código shell sea lo más pequeño posible optimizando tanto el diseño como la implementación.
  • Escritura de bucles decodificadores de shellcode con conjunto de instrucciones restringido IA32 por SkyLined Archivado el 3 de abril de 2015 en Wayback Machine Un documento técnico que explica cómo crear shellcode cuando los bytes permitidos en el shellcode están muy restringidos.
  • BETA3 Una herramienta que puede codificar y decodificar shellcode utilizando una variedad de codificaciones comúnmente utilizadas en exploits.
  • Shellcode 2 Exe - Convertidor en línea para incrustar shellcode en el núcleo de un ejecutable
  • Sclog - Versión actualizada de la herramienta de análisis de shellcode sclog de iDefense (Windows)
  • Libemu : biblioteca de análisis de shellcode basada en emulación (*nix/Cygwin)
  • Scdbg : depurador de shellcode basado en la biblioteca de emulación libemu (*nix/Windows).