<-!-> FAQ - Biblioteca - Recopilatorio de Shellcodes - ¡Leer!

<< < (2/3) > >>

Griph:
Nota: las direcciones offset de las cuales se habla en este texto son fictisias, simplemente se dan esos números para
proceder a la ejemplificación. No deben ser tomados en cuenta.

Un offset es un desplazamiento respecto de a una dirección de memoria. Por ejemplo, kernel32.dll se carga en memoria
a partir de la dirección (la siguiente es una fictisia) 0x76890000. Es decir, la dirección 0x76890000 empieza la
"DLL" (la cual recibe el nombre de dirección base). Bien, ahora, si por ejemplo usted quiere usar la función
LoadLibraryA (la cual se haya contenida en la DLL kernel32.dll), tendrá que informarse del offset de esa
función, le cual es: 0x7C. Lo cual quiere decir que la función la encuentra aquí:

Dir. Base + Offset = Dirección de la Función
0x76890000 + 0x7C = 0x7689007C

Entonces cuando quiere llamar a LoadLibraryA en ASM, tienes que mandar sus arguementos a la pila
(push eax/ebx/ecx o datos a mano..., teniendo en esos registros los argumentos, mandándolos en orden inverso).
Lo cual es de la siguiente forma:

push eax;  // Argumento 2º
push ebx;  // Argumento 1º
call 0x7689007C;  // Llamada a LoadLibraryA

Ese código ejecutará:

LoadLibraryA (argumento1, argumento2);

En el caso de los sistemas operativos de la empresa micro$oft las direcciones base de las DLL y los offset
de las diversas funciones cambian según la versión del sistema, los service packs instalados, parches y demás cuestiones.


Es decir:


Win 98 --> Dir Base kernel32.dll = 0x78960000

Win 2k --> Dir Base kernel32.dll = 0x79990000

Win 2k SP1 --> Dir Base kernel32.dll = 0x80000000

Win 2k SP4 --> Dir Base kernel32.dll = 0x79880000

Win XP --> Dir Base kernel32.dll = 0x80600000

Win XP SP1 --> Dir Base kernel32.dll = 0x80500000


Como puede ver, si durante la ShellCode deseamos llamar a LoadLibraryA simplemente tenemos que cambiar la dirección
de memoria del kernel32.dll y luego la de su offset, lo cual recibe el nombre de harcodear direcciones de memoria
o direcciones offsets). Por consiguiente nos damos cuenta que para cada shellcode que programemos tendremos que
desarrollar una para cada sistema operativo diferente. Aunque en realidad cabe decir que hay formas de lograr
una shellcode que se ocupe de buscar la dirección base y el offset de la función a utilizar de forma automática
(para que no la tengamos que cambiar y a la vez se pueda emplear en diferentes sistemas operativos).

Con la Pila (Stack) ocurre la misma situación: varía según el sistema operativo, service packs (SPs)
instalados, etc. Por eso puede que la dirección de memoria RET funcione en nuestro ordenador y no en otro.
De todos modos hay algoritmos que aplican la técnica de fuerza bruta (brute force) a la RET Address, hasta
que logran encontrar la dirección correcta a la que apunta la shellcode.

La Shellcode generalmente va como argumento del programa. Este arguemento se copia a un buffer mal construido, el
cual (dicho en palabras simples) peta. Luego se puede llamar a la shellcode a ese buffer que ha petado o en
donde estaba antiguamente, es decir en los argumentos (en ARGV, exactamente).

Griph:
¿Cómo se Usan los Exploits?

Los exploits son formas de explotar los bugs/vulnerabilidades que presenta un software  determinado, lo cual se puede llevar a cabo mediante una aplicación que fue programada especialmente para explotar una vulnerabilidad específica (un bug). En el transcurso de diseñar el exploit se lo puede programar para que explote la vulnerabilidad de forma remota o local.
Forma Local (exploit local): es el caso en el que tienes un entorno interactivo (una shell,  por ejemplo). Para ejecutar un exploit de forma local hay que tenerlo en la máquina y luego subirlo.

Forma Remota (exploit remoto): se ejecuta de la máquina en la cual se esta probando el  bug/vulnerabilidad que existe en otra máquina remota, aprovechando algún servicio que tenga conexión a la red y por consiguiente que tenga la vulnerabilidad que se está estudiando (pueden ser muchas, así como también una sola). De esta forma generalmente lo que se intenta es tener acceso a una shell. Tanto mediante un puerto privilegiado (los que son menores a 1024, los cuales están reservados para el sistema operativo y para el usuario root) o a un puerto no privilegiado (los que son mayores a 1024 en adelante). Respecto de los puertos privilegiados puede ser que con el "nc" puedes mandar una rootshell bin/bash (por ejemplo) y luego telnetear y tener la shell ahí lista para tipear comandos. Esto se puede ver en aquellos  exploit que envían la shell al puerto 80, por ejemplo (y cabe decir que el objetivo es el de saltarse los firewalls). De una u otra forma esto se consigue si el exploit logra tomar el privilegio de usuario root o ejecutarse en el espacio GDT del  kernel (de esta forma se puede abrir un puerto privilegiado). Referente a los puertos no privilegiados son puertos más "grandes" y por consiguiente tienen  una probabilidad de colapsar menor que un puerto privilegiado. Además es una forma de que el admin (sysop) no se de cuenta  de que hay un intruso en el sistema. Por otro lado cabe decir que un exploit puede programarse en cualquier lenguaje (siempre y  cuando tenga la suficiente capacidad para llevar a cabo un desarrollo de este tipo, generalmente en se encuentran  escritos en C; dado que se ha convertido en un estándar en la red.
Este es un ejemplo de código en Java que puede producir un exploit (esto es simplemente un  trozo de de código hecho en Java, y es precisamente un método o función):

Code:

public void processX(int i) {
int a = 10;
int result;
result = i / a;     // esta es la línea que puede causar un exploit
}

Este es el código de un método normal que espera una reducida cantidad de datos enteros (int) y lo procesa de acorde a algún valor definido dentro del mismo programa o su base de datos.
Podria no ser un valor cero, y esto haría un crash al sistema, el problema mayor de los  códigos es que no rechequean o válidan ninguna entrada de sus procesos, entonces un exploits puede hacer lo que desee, desde una tonteria hasta un serio programa de seguridad en flaws. En fin... los exploit son provocados por algún mínimo error que pueda tener un determinado software.



* Proceso de Compilación:

¿Qué es Compilar un Código Fuente?

Es un proceso realizado por un programa compilador, que consiste en la traducción del código  fuente escrito por el programador en alguno de los lenguajes de programación existentes (BASIC, C,C++,Java, Cobol, Pascal, Phyton, Perl, Delphi, Ada, Ensamblador, etc.) en código ejecutable (un programa) en un determinado sistema informático (UNIX, GNu/Linux, Windows,
Solaris, etc.).

Más información en: http://www.hispabyte.com/glosario/index.php?letra=c

[*] Compilar un exploit escrito en lenguaje C desde GNU/Linux sería:

*_* Compilación:

#gcc exploit.c -o exploit

*_* Ejecución:

#./exploit <parametros><parametros2> etc.

En caso de no tener acceso a un sistema GNU/Linux, se puede compilar desde windows. Mediante compiladores como: LCCWIN32, Dev C++, etc. Aunque cabe decir que muy pocos (esto se ve reflejado en el tema de los sockets, es decir en rigor de verdad por las librerías las cuales son distintas para cada sistema operativo y el exploit tendría que estar escrito especialmente para windows). De una u otra forma se puede leer el código fuente: cat  exploit.c , more exploit.c, etc. para ver el código fuente y leer las especificaciones que podría traer; tanto para la correcta compilación como para su posterior uso.

Puede ocurrir que en la compilación de las fuentes con DevCpp (comúnmente conocido como Dev- C++) surgan errores referentes a los archivos de encabezado (headers), los cuales se deben a que se quiere  utilizar un fichero ***.h que no es estándar (porque son creados por otros programadores, para otros compiladores o bien para  otros sistemas operativos). Es
decir este compilador trabaja con dos tipos de ficheros headers: Los ANSI (que son estandar) y los que trae de forma predeterminada windows (que también son ANSI pero sólo sirven para este sistema operativo, un ejemplo de estos ficheros es por ejemplo winsock.h que sirve para trabajar con wsockets en windows). Para evitar estos  problemas un compilador como
CYGWIN con el paquete GCC instalado.


[*] Un exploit en Perl (estos funcionan tanto para GNU/Linux como para MS-DOS, aunque para  este último hay que llevar a cabo algunos pasos anteriores antes de comenzar a compilar códigos):

perl exploit.pl <parametros> <parametros>

Luego se ejecuta el fichero exploit.pl. El intérprete de Perl lo va compilando línea por  línea (al exploit) y luego lo ejecuta secuencialmente. Para ejecutar estos exploit en windows se puede bajar el ACTIVE PERL, y luego se pueden  ejecutar los exploits escritos en
Perl desde una consola MS-DOS: C:\perl exploit.pl <parametros>


[*] Compilar un exploit en shellscript (éstos sólo funcionan en GNU/Linux):

./sh exploit.sh parametros

En fin así como se puede compilar o programar un exploit con estos lenguajes, se puede hacer  también con cualquier lenguaje del cual se tenga un buen dominio (que se lo sepa usar bien).



Para más información:

* www.securityfocus.com
* www.packetstorm.com
* www.securiteam.com
* Las e-zines de NetSearch.
* www.decowar.com
* www.cyruxnet.org (tiene muy buenos textos)
* www.zine-store.com.ar
* www.hackemate.com.ar (se las han ingeniado muy bien para recopilar tantos e-zines, son verdaderamente muchos)
* www.cyervonet.com.ar
* www.prehackers.com
* www.hackxcrack.com (hay información muy útil sobre seguridad avanzada en general, viene muy bien darle una mirada)
* http://www.cygwin.com/ (compilar y ejecutar exploits en windows, es una emulador de la shell para windows)
* http://cygwin.com/faq/
* http://cygwin.com/cgi-bin2/package-cat.cgi?file=gcc/gcc-3.2-3&grep=gcc (el compilador gcc)
* http://gcc.gnu.org/
* http://cygwin.com/cgi-bin2/package-grep.cgi?grep=gcc (paquetes para gcc)
* En caso de que falte la DLL CYGWIN.dll (hay que ubicarla en el directorio system32 o system):
http://www.cs.washington.edu/homes/kautz/blackbox/cygwin1.dll
* http://cyruxnet.org/rpcxploit.htm (Cómo usar un xploit)
* http://www.hackxcrack.com/phpBB2/viewtopic.php?t=14605 (son servidores para hacer poner en prueba los testeos de seguridad, cabe decir que es para prácticar cómo podría alguien atacar nuestro servidor u ordenador personal).

Griph:
El Desbordamiento del Buffer: Buffer OverFlow (desbordamiento de la memoria).

Los desbordamientos de buffer se basan en introducir el código en el espacio reservado para las variables locales (los argumentos de un método/función) y después modificar la dirección de retorno/regreso (RET), en donde regresa la información, para que apunte a un offset en donde hemos introducido nuestro código fuente. Este código puede ser - por ejemplo - una ShellCode, es decir, instrucciones para llevar a cabo la ejecución de un intéprete de comandos como puede ser: bash, sh, entre otros.

Una forma de aprovechar los desbordamientos del buffer (en el caso del Lenguaje de Programación C) es la función strcpy(), con la cual se sobreescribe una posición en la memoria (es decir, se sobreescribe un offset) "parecido a las funciones de las shell codes". El string origen (la cadena de caracteres) de la función "strcpy" contiene nuestro código al principio y después la nueva dirección de retorno (RET) repetida tantas veces como sea necesario para llegar a sobreescribir la antigua.

El desbordamiento del buffer se produce cuando un usuario o un proceso intenta introducir en el buffer una cantidad de datos superior para lo cual estaba preparado el buffer. Algunas funciones útiles para llevar a cabo el desbordamiento del buffer son, las siguientes:

Código:

* strcpy();
* strcat();
* sprintf();

Entre otras (nada es perfecto y por consiguiente es más que probable que hayan otras funciones que ayuden a la hora de desbordar un buffer).

Lo que provoca el desbordamiento de un buffer es una violación de la segmentación de memoria. El objetivo de esto es saltar a otra dirección offset, y por consiguiente caer en la librería que tiene el intérprete de comandos. Es decir la Shell para ejecutar los comandos, que para esto estaremos dentro del sistema del cual se está testeando.

De una forma un poco más detallada se puede explicar qué causa el fallos de la siguiente manera:

En realidad el fallo en sí no se provoca al desbordar el buffer o sobrepasar el valor para el cual está preparada la variable local, sino que al escribir más de lo que se había reservado se puede llegar a escribir la RET (la dirección de retorno). Luego el sistema operativo llevará a cabo la función a la cual se le ha desbordado buffer y se dirige a la pila. Después buscará el offset en el cual se encuentra la RET y encontrará en ésta una violación de segmento.

Existen dos tipos de desbordamientos: "Locales" y "Remotos".

Un buffer de longitud fija de 128 bytes, define la cantidad de datos que pueden almacenarse como entrada al mandato SendMail que puede servir para identificar usuarios (es decir que a tal fin está preparada para recibir 128 bytes, de lo contrario desbordará).

Entonces si envíaramos un bloque de 1000 caracteres (lo cual equivale a 1000 bytes) en lugar de un bloque de 128 caracteres (128 bytes) lo que sucede es que el buffer de SendMail se desborda; y por consiguiente se puede producir una denegación de servicio (es decir los ataques conocidos comúnmente como DoS, Denial of Service) y podría ejecutarse el comando /bin/sh. Lo grave es que si esto sucede un intruso puede tener privilegios de root (administrador):

Código:

Echo ?sendmail 'perl -e 'print ?a? x 1000' ' ? |nc www.victima.com 25

Por suerte no todos los programas responden de igual manera que SendMail. El código que se usó es EGG Assembly (Assembly, sinónimo de ensamblador).

De todos modos el código fuente en ensamblador depende del Sistema Operativo, uno para GNU/Linux es el siguiente:

Código:

char shellcode [] =
? \xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b?
? \x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd?
? \x80\xe8\xdc\xff\xff\xff\bin\sh ? ;

Griph:
Estaba leyendo un texto sobre ensamblador y vi una parte interesante que habla sobre la Pila (Stack) del Procesador. Dado que es un concepto que hay que tener claro a la hora de diseñar una shellcode para un exploit, etc. aquí les dejo el texto:

Citar

     - La pila del procesador:
     -------------------------
     La pila es una característica interna del 8086. Es una estructura de
     datos situada en la RAM. Proporciona a los programas un lugar donde
     almacenar datos de forma segura, pudiendo compartirlos con otros
     procedimientos o programas de forma cómoda y práctica.

     La función más importante de la pila es la de mantener las direcciones
     de retorno en las llamadas a procedimientos e interrupciones, así como
     guardar los parámetros pasados a estos procedimientos.
     La pila también se utiliza para almacenamiento temporal de datos dentro
     de un programa, y para muchas cosas más que se aprenden con la práctica.

     La pila tiene su nombre por analogía con los montones de platos apilados
     (pilas de platos). Cuando un dato nuevo es introducido en la pila, se dice
     que es apilado (push) debido a que se sitúa por encima de los demás, es
     decir se sitúa en la CIMA de la pila.

     Una pila opera en el orden  último-en-entrar - primero-en-salir:
     LIFO (LAST IN FIRST OUT) o lo que es lo mismo, el último en entrar es
     el primero en salir.

     Esto significa que cuando la pila se utiliza para seguir la pista de los
     retornos de las subrutinas, la primera llamada a subrutina que se hizo,
     es la última que se devuelve. De esta manera, la pila mantiene ordenado el
     funcionamiento del programa, las subrutinas y rutinas de tratamiento de
     interrupción, sin importar la complejidad de la operación.

     La pila crece en orden inverso. Es decir, a medida que se añaden nuevos
     datos, la cima de la pila se acerca más a posiciones más bajas de memoria.

     Existen 3 registros destinados a gestionar la pila.
     Registro de segmento de pila (SS): que indica la dirección base del
     segmento de pila
     Puntero de pila (SP): que apunta a la cima de la pila.
     Puntero base de pila (BP): que se usa para moverse a través de la pila
     sin cambiar la cima. Se suele utilizar para acceder a los distintos
     parámetros al llamar a una función.

     Los elementos que se almacenan en la pila son del tipo palabra (2 bytes).
     Esto quiere decir, entre otras cosas, que el puntero de pila (SP), así como
     el puntero base de pila (BP), incrementan/decrementan en 2 su valor para
     apuntar a un nuevo elemento dentro de la pila, fruto de apilar o desapilar
     un elemento.

     También conlleva el que si queremos almacenar un byte en la pila, primero
     lo debemos convertir en palabra (2 bytes), y luego almacenar esa palabra.
     Esto es muy sencillo, sólo hay que meter ese byte o registro de 8 bits
     en un registro de 16 bits y almacenar este registro.

     Las instrucciones para manejar la pila son:
     PUSH ---> Guarda un dato en la pila. Decrementando SP en 2 unidades, para
               que apunte al nuevo elemento a introducir.
               Ejemplo: PUSH AX --> Apila el contenido de AX en la cima de la
                        pila.

     POP ----> Obtiene un dato de la pila. Incrementando SP en 2 unidades, para
               que apunte al nuevo elemento a introducir.
               Ejemplo: POP AX --> Desapila el contenido de la cima de la pila
                        en el registro AX. Es decir, AX contendrá el valor
                        que hubiera en la cima de la pila, y el puntero de pila
                        se actualiza incrementándolo en 2.

     PUSHF --> Guarda el contenido del registro de estado (FLAGS) en la pila.
               Decrementando SP en 2 unidades, para que apunte al nuevo elemento
               a introducir.
               No es necesario indicar sobre qué actúa esta instrucción, lo
               lleva implícito en su nombre PUSHF (PUSH FLAGS).

     POPF ---> Introduce en el registro FLAGS el contenido de la cima de la
               pila. Incrementando SP en 2 unidades, para que apunte al nuevo
               elemento a introducir.
               Al igual que con la instrucción anterior, no es necesario indicar
               sobre qué actúa esta instrucción POPF (POP FLAGS).



     Conviene recordar el hecho de que la pila crece en orden inverso al
     normal, es decir de direcciones de memoria altas a direcciones bajas.
     Por lo tanto es necesario tener en cuenta el uso que se va a hacer de
     la pila en el programa, debido a que si reservamos espacio en nuestro
     programa para una pila pequeña, en caso de sobrepasarla haciendo muchos
     push seguidos, machacaría nuestro programa.

     Hay que tener en cuenta que no sólo es nuestro programa el que utiliza
     la pila mediante la instrucción PUSH y mediante llamadas a procedimientos,
     interrupciones, etc. Sino que mientras nuestro programa corre se están
     sucediendo numerosas interrupciones que conllevan muchos PUSH.
     Por ejemplo, 18'2 veces por segundo se produce la interrupción de reloj,
     con lo cual, todas estas veces se está apilando y posteriormente
     quitando información de la pila.

     Por regla general, basta con tener una pila de unos 2 KS, es decir, espacio
     para almacenar 1024 elementos. Es muy difícil que se sobrepase este tamaño.


Que les sirva.

Griph

sirdarckcat:
Recomiendo lean esto antes:
http://www.firewalls.com.br/files/shellcode.pdf
http://www.lsd-pl.net/documents/winasm-1.0.1.pdf
http://en.wikipedia.org/wiki/Shellcode
http://www.google.com/search?q=The+Shellcoders+HandBook

"Generador de shellcodes a la medida"
http://metasploit.com:55555/PAYLOADS

Recopilatorio de Shellcodes:
Windows
<Foro>
Analisis de una shellcode FALSA!!
Crea Admin
Microsoft Internet Explorer IFRAME Tag Overflow Exploit modificado para Reverse Shell por LoReDo & Gospel
Exploit Firewall XP SP2
<Externo (milw0rm)>
Shellcode para BoF's
Shellcode Download & Exec
Bind Shell (58821)
WinExec Shellcode
PoC Shellcode (ventana)

Linux
Agregar Usuario  t00r
execve("/bin/sh")
BindShell (5074)
BindPort y Connectback por ben _

Navegación

[0] Índice de Mensajes

[#] Página Siguiente

[*] Página Anterior