google translator

lunes, 19 de septiembre de 2011

Claves WPA para WLAN_XXXX y JAZZTEL_XXXX

El siguiente script no es nada especial, solo me he dedicado a escribir en Python los datos que he ido recopilando de la red. No he descubierto nada nuevo, si no que he 'mejorado?' lo que ya habia.

Hace tiempo, estuve buscando informacion sobre la seguridad en las redes wireless y especialmente me centre en investigar las redes WLAN.
Movistar (antigua Telefonica) siempre ha estado en el punto de mira de los investigadores de seguridad. Una compañia sin piedad que llena titulares tan escandalosos como el ERE de 8500 empleados habiendo obtenido unos beneficios records de un 31% sobre el ejercicio anterior durante un periodo de crisis economica brutal.

Pero, como diria Francisco Umbral, yo he venido aqui a hablar de mi libro y mas exactamente de como se puede romper la seguridad en las redes WLAN_XXXX y JAZZTEL_XXXX y su clave WPA.

La gente de SeguridadWireless fueron los primeros en dar la primicia que acababan de descubrir el algoritmo de encriptacion para las claves por defecto de los router Comtrend. Optaron por no liberar el codigo e intentar sacar beneficio a traves de AdSense posteando en su web un formulario. Algo que personalmente me parece muy feo.

La comunidad, ante esta agresión, trabajó para descubrirlo y demostraron el método de encriptacion, basado en cifrar a MD5 una cadena generada mediante el ESSID y el BSSID del router. Esta proeza la consiguio elvecinoo dumpeando la memoria del router y buscando cadenas. Simplemente estaba ahi escrita, esperando a ser encontrada.
El hilo se siguió de cerca desde lampiweb.

Dejando a un lado la historia, voy a la parte tecnica que es la que nos gusta a todos.

Primero hay que quitar los : al BSSID. Solo estorban ;-)
El ESSID normalmente se genera restando 3 a el ultimo bloque del BSSID, pero hay que tener en mente que el usuario ha podido cambiar el ESSID a su router.

Coge papel y boli que empezamos.

La clave se obtiene de la cadena compuesta por:
bcgbghgg + 8 primeros caracteres del BSSID + 4 ultimos caracteres del ESSID + BSSID completo
La cadena resultante, se encripta a MD5 y se acorta a los 20 primeros caracteres.

En el caso de que se haya cambiado el ESSID la clave se sacaria de esta manera:
bcgbghgg + los 10 primeros caracteres del BSSID + resta 3 a los dos ultimos caracteres del BSSID + BSSID
Igual que antes, solo nos quedamos con los 20 primeros caracteres del MD5.

Esto queda mas claro con este ejemplo:
Mi red es WLAN_B2B0 y el BSSID es 64:68:0C:B1:B2:B3
La cadena que me resulta es:
bcgbghgg + 8 primeros caracteres del BSSID + 4 ultimos caracteres del ESSID + BSSID completo
bcgbghgg + 64680CB1 + B2B0 + 64680CB1B2B3 = bcgbghgg64680CB1B2B064680CB1B2B3

Convertido a MD5 es 20fbc01c79ee84a8bdde311e15aebb91 y me quedo con los 20 primeros caracteres.
El pass de la red es 20fbc01c79ee84a8bdde

Bonus:
La clave de los router Zyxel es mas sencilla. Estos router tienen como BSSID 00:1f:a4:XX:YY:ZZ.
Se crea una cadena con los 8 primeros digitos del BSSID + 4 ultimos digitos del ESSID
Al igual que con los Comtrend se convierte a MD5 y se acorta ese MD5 a los 20 primeros caracteres.

De nuevo lo explico con un ejemplo:
Mi red tiene como BSSID 00:1f:a4:b1:b2:b3 y esta identificada mediante el ESSID WLAN_B2B0
Creo la cadena:
8 primeros digitos del BSSID + 4 ultimos digitos del ESSID
001fa4b1 + b2b0 = 001fa4b1b2b0

Lo convierto a MD5 y queda 9689bde42d0f3aec317fc7d1a70a4bee
Me quedo solo con los 20 caracteres y el resultado es la contraseña
El password de la red es 9689BDE42D0F3AEC317F

URL SVN:
https://www.assembla.com/code/PynTester/subversion/nodes/trunk/WJ4x/WJ4x_BBDD.py

Creando un plugin para immunity debugger

Muchas veces, cuando estamos depurando una aplicación con el immunity debugger, siempre pensamos que hay algo que debería tener pero que no tiene. Incluso perdemos el tiempo repitiendo tareas que podríamos evitar tener que hacer mil veces si hubiera un plugin que lo hiciese. Pues bien, en este post voy a hacer una pequeña introducción a como realizar un plugin para el immunity, para que os sirva de introducción, y podáis haceros luego vuestros propios plugins.

El plugin que vamos a realizar es muy sencillo, simplemente buscará unas instrucciones en ensamblador por todo el programa que estemos depurando (incluso sus librerías), y nos mostrará por pantalla donde se encuentra dichas instrucciones. Para realizarlo, lo vamos a hacer con Python, un lenguaje que se lleva muy bien con Immunity y con el que además vamos a programar el plugin muy rápido.

Todas los plugins de immunity se encuentran en el directorio "PyCommands" del directorio de instalación de Immunity (No confundir con el directorio "PyPlugins"). Con lo cual vamos a crear un fichero en esa carpeta llamado "buscador.py". Para hacer una prueba y ver como funciona esto de los plugins, vamos a hacer primero el típico "hola mundo". Para ello abrimos el fichero "buscador.py" y escribimos lo siguiente:

def main(args):
	return "Hola mundo!"

Una vez guardado, abrimos el immunity cargando cualquier programa (yo he cargado en notepad) y en la parte inferior de la ventana tecleamos lo siguiente:

!hola 

Después de eso veremos con se muestra justo debajo de donde hemos escrito el mensaje "hola mundo!", como podemos ver en la imagen.



Con esto ya nos podemos hacer un poco a la idea de como van los plugins de immunity. Así que ahora vamos a explicar como hacer más cosas.

La librería que nos trae immunity para hacer plugins se llama "immlib", y es en lo que nos vamos a basar para hacer cualquier plugin ya que con esta libreria podemos hacer casi de todo con immunity. El propio immunity trae en el menú una parte dedicada a "immlib" y si extendemos el menú veremos que tenemos ayuda sobre immlib y su API. Aunque la mejor ayuda esta en el directorio "documentation/ref" del la carpeta principal de immunity. Si hacemos doble click sobre index.html veremos la documentación completa de immlib y esta sí que es muy buena, si perdemos un poco de tiempo echándole un vistazo podemos hacer cosas bastante chulas (hooks, breakpoints, etc..)

Para hacer el plugin vamos a utilizar alguna de las funciones que nos ofrece immlib. Para ello lo primero que deberemos de hacer es importar "immlib" e instanciar la clase "debugger" que es la que vamos a usar en nuestro plugin. Los métodos que vamos a usar para el plugin van a ser solo tres:
  • log - Con el cual vamos a escribir en la ventana de log.
  • searchCommands - El cual buscará las instrucciones en ensamblador que le pasemos.
  • getMemoryPageByAddress - Como el nombre indica devuelve una página de memoria, desde una dirección que devuelve "searchCommands"
Buenos ahora que ya sabemos los tres comandos que vamos a necesitar voy a mostrar el código completo del plugin y lo vamos comentando:

from immlib import *

def main(args):

  imm = Debugger()
  if not args:
     imm.log("!prueba [asm]")
     imm.log("Ejemplo: !prueba pop r32|pop r32|ret")
     return "[*] No se ha usado correctamente. Vea la ventana de logs"

  codigo = " ".join(args).replace("|","\n")
  res = imm.searchCommands(codigo.upper())

  for aux in res:
    memoria = imm.getMemoryPageByAddress( aux[0] )
    permisos = memoria.getAccess(human = True)
    if "execute" in permisos.lower():
      imm.log("[*] Coincidencia: %s (0x%08x) en %s" % (codigo.replace("\n","|"),aux[0], aux[2]))
 

  return "[*] Ejecutado sin errores. Consulte la ventana de logs para ver los resultados"

Como se puede ver el código no es complicado, en las primeras lineas lo único que hago es instanciar la clase Debugger, y si el usuario introduce mal los argumentos mostrarle como debe hacerlo.

En la segunda parte, sustituyo las tuberías (que hago que el usuario introduzca para separar comandos) por un salto de linea (necesario para que "searchCommands" funcione correctamente) y hago que "searchCommands" busque las instrucciones.

En la ultima parte, con cada resultado devuelto, uso getMemoryPageByAddress para saber que permisos tiene dicha región de memoria, y en el caso de que esa región sea ejecutable la muestro por pantalla. Muchos os preguntareis, ¿Por qué ejecutable? Pues bien, este plugin lo hice con la intención de buscar pop/pop/ret para los exploits, por lo cual necesitaba que la región donde se encuentren estas instrucciones fuera ejecutable. Así que si no os interesa esta parte simplemente la podéis comentar y solo mostrar los resultados de la busqueda con "searchCommands", o si os vale con que la memoria sea de lectura pues podéis poner "read", esto ya os lo dejo a vuestra imaginación.

Si queréis probar el plugin, ya sabéis como hacerlo, copiáis el codigo en un fichero (para los vagos os lo podéis bajar de aquí) y luego lo ponéis en la carpeta "PyCommands". Abrir el immunity debugger con alguna aplicación y en la parte baja de la ventana, el nombre que le hayáis puesto al fichero más la cadena a buscar. Por ejemplo, si al fichero lo habéis llamado buscador y queréis buscar la famosa cadena pop/pop/ret, podéis poner lo siguiente:

!buscador pop eax|pop ebx|ret 



y buscará todas las instrucciones que se correspondan con esa cadena y las mostrará en la ventana de logs. Sencillo, no?