::::::::::::::::::::[WEB 1]::::::::::::::::::::
En este reto nos dan una página web, http://ctf.navajanegra.com/WEB%201.php
::::::::::::::::::::[Phreaking 1]::::::::::::::::::::
En este reto nos dan una página web, http://ctf.navajanegra.com/WEB%201.php
en la que aparece un boton que pone "Click Here!" dentro y al acercarnos con el cursor este cambia de posición y no nos permite pulsarlo. Si analizamos el código vemos que es imposible pulsarlo y en la linea 41 encontramos la evidencia,
<button id="bt" onmousemove="fun();" onClick="alert('Do not waste time with this button!
De donde se deduce que si el código es lo interesante, mas interesante será descargar el archivo WEB 1.php que está en el servidor que en ocasiones puede ser distinto al que visualizamos a traves de la web.
wget http://ctf.navajanegra.com/WEB%201.php
Abrimos el archivo con cualquier editor que tengamos a mano y vemos que despues de <body> aparece el flag.
<body>
Password: 6e3e92ebfcec506d0cc56f24a929ac11
::::::::::::::::::::[WEB 2]::::::::::::::::::::
Nos daban una pagina web con el campo usuario y contraseña vulnerable a sql injection. La vulnerabilidad se ha explotado con la herramienta sqlmap.
::::::::::::::::::::[STG 1]::::::::::::::::::::
Nos proporcionan una imagen con un mensaje oculto en la que aparece un astronauta tomándose una cerveza en la luna.
Con strings obtenemos las cadenas de caracteres de la imagen
Al final de todo vemos una cadena en base 64,
:ozy:TXkgc2VjcmV0IGNvZGU6IDFlZjFkODM0NzMzMWFmYjc1YjgyMjgxOWZkNGU2ZDNiIA==
Que descifrada quedaria; My secret code: 1ef1d8347331afb75b822819fd4e6d3b
Flag: 1ef1d8347331afb75b822819fd4e6d3b
::::::::::::::::::::[STG 2]::::::::::::::::::::
Nos dan una pista de audio con una grabación telefónica de un servicio de venta de tickets, en la que el cliente mete los números de su tarjeta de crédito para realizar la compra.
Cuando el cliente pulsa una tecla se genera un tono DTMF (Dual-Tone Multi-Frequency) que viene dado por dos frecuencias determinadas que corresponden a cada tecla segun la siguiente tabla:
Para saber cuales son los pares de frecuencias que generan cada tono seleccionamos el trozo de pista donde se emite el tono y usamos el análisis de espectro de Audacity.
Los dos primeros picos se corresponden con las frecuencias que determinan que número estamos pulsando y sus valores vienen dados por la frecuencia de pico al situarnos con el cursor sobre cada uno de ellos.
Para los cuatro primeros numeros tenemos los siguientes pares de frecuencias, que aunque no son exactas, debemos de aproximarlas a la mas cercana para entrar en la tabla y obtener el número correspondiente:
{774, 1341}Hz ----> 5
{773, 1205}Hz ----> 4
{776, 1468}Hz ----> 6
{698, 1202}Hz ----> 1
Realizando el mismo proceso en el resto de los tonos sacamos el numero:
5461765425671065
::::::::::::::::::::[Phreaking 2]::::::::::::::::::::
En este reto nos daban una captura de una comunicación voIP en la que se debia obtener la contraseña original de la comunicación e introducirla con el formato: hash:pass
Una vez descargue el archivo SipPHK2.pcapng, lo abrí con whireshark y comprobé que usaba el protocolo SIP.
...
User-Agent: Linksys/PAP2T-3.1.15(LS)
Contact: <sip:nn4ed@94.133.99.2:49156>
Expires: 0
Authorization: Digest username="nn4ed", realm="sip.12voip.com", nonce="720058375", uri="sip:sip.12voip.com", response="3c58ee4488a90ad08d67a24b4c2c9beb", algorithm=MD5
Content-Length: 0
...
Si la analizamos un poco vemos que el usuario es "nn4ed" y el hash MD5: 3c58ee4488a90ad08d67a24b4c2c9beb
Con sipdump se vuelca las sesión capturada a un archivo pass.txt.
A continuación usamos sipcrack para crackear la contraseña haciendo uso de un diccionario.
Luego de probar varios diccionarios sacó la contraseña: passw
Finalmente la flag era: 3c58ee4488a90ad08d67a24b4c2c9beb:passw
::::::::::::::::::::[CRK 1]::::::::::::::::::::
Tras abrir el ejecutable
“CrackMe1.exe” nos aparece una pantalla en la que debemos
introducir un usuario y contraseña.
Introducimos un usuario y contraseña
cualesquiera y se nos muestra un mensaje de error
A continuación abrimos este
ejecutable con la herramienta Dependency Walker y vemos que está
enlazada con MSVBM60.DLL, con esto sabemos que estamos ante un exe
compilado con Visual Basic 6
Como el mensaje de error tiene toda
la pinta de ser el mostrado por las APIs de Windows “MesageBox”
vamos a depurar el ejecutable con OllyDBG y pondremos varios
BreakPoints en las funciones que puede mostrar este mensaje:
MesageBoxA, MesageBoxW, MesageBoxExA, MesageBoxExW,
MesageBoxIndirectA, MesageBoxIndirectW, MesageBoxTimeoutA y
MesageBoxTimeoutW. Todas estas funciones están en user32.dll
A continuación lanzamos el programa
en el depurador de OllyDBG, ponemos un usuario y clave y vemos como
el depurador se nos detiene en la función MesageBoxIndirectA
Ahora vamos a salir paso a paso de
cada procedimiento hasta que retornemos al punto de ejecución en el
ejecutable principal desde el cual se ha invocado a este
MessageBoxIndirectA, pulsamos CTRL + F9 hasta retornar al ejecutable
Crackme1.exe.
Tras salir de user32.dll y
msvbvm60.dll nos encontramos en el ejecutable, justo tras la llamada
que nos ha mostrado el mensaje de error.
Ahora con la ejecución del programa
detenida en ese punto, hacemos scroll hacia arriba a ver si vemos
alguna cadena de texto con un mensaje del tipo de “clave correcta”
o algo similar.
Vemos un “Enhorabuena, has
superado el reto.” Y un poco antes vemos dos cadenas de texto
sospechosas: “…N….N” y “Albacete”.
Abrimos otro crackme1.exe para
probar suerte y….
Segundo intento…
MD5 de “…N….N” --->
0047c0baeb5faccc8a71319c72fa6af2
Reto superado!!
::::::::::::::::::::[CRK 2]::::::::::::::::::::
Tras ejecutar el archivo crackme2
vemos se nos piden dos números de serie. Introducimos dos números y
nos aparece un mensaje: “Bad Hacker!”.
Desensamblamos el ejecutable y
comenzamos a analizar su código
En esta primera parte vemos dos
llamadas a la función de librería “scanf”, usadas para leer los
números que habíamos introducido. Vemos también la existencia de 4
variables numéricas con los valores iniciales: 0x7F06F93, 0xBB, 0x2
y 0x0, la existencia de estos cuatro números nos hace pensar que
serán usadas en algún calculo posterior.
En esta segunda parte vemos dos
bucles que hacen dos comprobaciones idénticas, una para cada uno de
los números que hemos introducido, en estos bucles vemos que se usan
dos de las variables que vimos en el punto anterior, el 0x2 y el 0x0.
En estos algoritmos se comprueba que ambos números son primos,
dividiendo cada uno de los números entre todos los números enteros
que van desde el 2 hasta el propio número, si en alguna de esas
divisiones el resto de la división es 0 entonces el número no es
primo. En caso de que alguno de los números no sea primo se salta al
siguiente bloque de código:
Aquí se nos muestra el mensaje “Bad
Hacker!” y finaliza la ejecución del programa.
Si ambos números son primos, no se
toma el salto y el programa continúa en el siguiente bloque:
En este punto se realiza en primer
lugar una división mediante la función __divdiv3, esta función de
división la genera automáticamente el compilador cuando en la
división interviene un número de 64bits y el programa se compila
para 32 bits. Sabiendo que los operadores son dos números de 64 bits
y que estos se pasan en forma de 4 parámetros de 32 bits cada uno…
vemos que el primer operador es en realidad la concatenación de las
dos primeras variables que vimos en el primer punto (0x7F06F93, 0xBB)
lo que nos da el número 0xBB07F06F93. El segundo parámetro es el
número por el cual vamos a dividir, y vemos que es el segundo número
que nos pide el programa (este es un numero de 32bits y los 32bits de
nivel superior se rellenan con 0: mov [esp+0Ch], edx <-- edx =0]).
La segunda parte de este fragmento
de código, compara el resultado de la división anterior con el
primer número que nos pide el programa, si el resultado coincide nos
muestra el mensaje “Serial number Correct!”, si el resultado no
coincide se nos muestra “Tray Again!”.
En resumen:
Los números buscados tienen que ser
primos, y además el resultado de multiplicar ambos tiene que ser
0xBB07F06F93 (803292082067). También sabemos que los números
introducidos son enteros de 32bits con signo (por el “%d” que se
usa en el scanf), con lo cual el máximo valor que puede tener cada
uno de los números va a ser 2147483647.
Ahora necesitamos una comprobación
de fuerza bruta que pruebe todos los productos de números primos
entre sí desde 2 hasta 2147483647 (el mayor número entero de 32bits
con signo), hasta encontrar una combinación cuyo resultado sea el
número 803292082067.
Usamos un
diccionario de números primos y esta pequeña utilidad escrita en c#
para multiplicar todos los primos entre sí:
using System; using System.Collections.Generic; using System.IO; using System.Threading.Tasks; using System.Linq; namespace Primos { class Program { static void Main(string[] args) { long resultado = 803292082067; Listl = new List (); using (StreamReader sr = new System.IO.StreamReader(@"D:\primos.txt")) { while (!sr.EndOfStream) { l.Add(int.Parse(sr.ReadLine())); } } l.Sort(); using (StreamWriter sw = new StreamWriter(@"D:\resultado.txt")) { Parallel.For(0, l.Count, new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount }, i => { for(int j = i;j < l.Count;j++) { long calc = (long)l[i] * (long)l[j]; if (calc == resultado) { lock (sw) { string r = l[i] + " x " + l[j] + " = " + resultado; Console.WriteLine(r); sw.WriteLine(r); sw.Flush(); } break; } else if(calc>resultado) { break; } } }); } Console.WriteLine("Finalizado..."); Console.ReadKey(); } } }
Esta herramienta nos indica que la
multiplicación de 880543 x 912269 da como resultado el
número buscado.
MD5 de 880543 ->
0f15116e1011443612420bc1ca223c68
MD5 de 912269 ->
3310cd38956c9a35abae340d91f42925
Reto superado.
Nota:
Realmente existirían otros dos números posibles, que serían el
-880543 y -912269 ya que su multiplicación también da el resultado
buscado. No se ha comprobado si el reto también se daba por válido
el MD5 de alguno de esos números negativos.
::::::::::::::::::::[EXTRA]::::::::::::::::::::
En el enlace de la imagen nos lleva al siguiente link:
http://ctf.navajanegra.com/extra.php
Hi, James Bond, what is your agent number?
Podemos predecir que nos pide que usemos el agent, asi que cambiamos el user-agent por el 007.
Se actualiza la página y nos da un qrcode.
Lo decodificamos y nos da un md5.
Googleamos el md5 y ya fue desencriptado: f3807a187fce8cd0d901726ee33331bc == BUDA
Tambien nos dice que enviemos via POST el master code.
Tambien nos dice que enviemos via POST el master code.
Usando hackbar puede hacerse y nos lleva a un link para descargar una maquina virtual de mega.
Descargamos la maquina virtual y al montarla nos pedia usuario y contraseña para iniciar sesión. Como no habia ganas de hacer mas fuerza bruta optamos por montar el disco en otra máquina y asi pudimos acceder a los archivos saltandonos esa protección.
En el directorio /home encontramos un readme.txt que decia:
En el directorio /home encontramos un readme.txt que decia:
Encuentra la contraseña del archivo /home/navaja/bof1, desbordando la pila, para obtener la clave del nivel :)Bueno xD, lo que se hizo fue abrir el archivo bof1 con IDA para echarle un vistazo:
En la linea en donde está el breakpoint se encuentra la contraseña en claro:
GNU/Linux, asique no era necesario explotar el BOF para superar el reto.
Calculamos su MD5: 4a58db979d107ca6300f1be1406b3605
Reto superado!!
Como este reto Extra tuvo un final un tanto descafeinado, decidimos ser "legales" y sacar la contraseña provocando un stack overflow:
Ejecutamos bof1 y nos aparece el siguiente mensaje “Pista:
0x8048474”, Pulsamos enter y nos aparece “Introducistes:” y el programa se
cierra.
Aparentemente en 0x8048474 existe algo interesante…
Vamos lanzar el programa con gdb y echar un vistazo a ver
que hay en 0x8048474
Nos encontramos una función llamada “foo”, la cual llama a “printf” y luego a “fflush”. Ese printf suena a que nos van a mostrar algún mensaje…
Volvemos a ejecutar el programa y escribimos algo
Parece que el programa lee lo que escribimos y a
continuación lo muestra y finaliza.
Escribimos un texto largo a ver qué pasa:
Escribimos un texto de 250 caracteres y vemos que se
muestran, pero a continuación el programa falla, con un error SIGSEGV. La causa
más posible de este error es porque el programa ha intentado acceder a una zona
de memoria que no contiene código ejecutable o no tiene permisos de ejecución o
de lectura. El error con total seguridad se ha producido porque la variable
destinada a guardar el texto introducido no tiene el tamaño suficiente para
guardar las 250 letras y no se ha hecho una comprobación previa de su longitud,
a partir de aquí el trozo de texto que excede la longitud máxima ha sobrescrito
otras variables y posiblemente la dirección de retorno de la función actual,
con cual se ha derivado el retorno de esta función hacia una zona de memoria
que no es ejecutable.
Vamos a repetir el paso anterior lanzando el programa en
gdb:
Nos aparece el mismo error de violación de segmento, y vemos
que ha sido en la dirección de memoria 0x61616161, además vemos que el valor de
eip es 0x61616161, con lo cual sabemos que se ha intentado ejecutar algo que
estaba en esa dirección. Realmente 0x61616161 no es una dirección válida, sino
que son las aaaa… que hemos escrito: 0x61 es el valor hexadecimal de la letra ‘a’,
si hubiésemos puesto bbbb… tendríamos el error en 0x62626262.
Si volvemos al principio vemos que nos daban una pista: 0x8048474…
Parece lógico que deberíamos hacer que la ejecución del programa saltase a esa
dirección.
Sabemos que en algún punto entre la primera a y la última de
las 250 existen 4 a’s que nos sobrescriben el valor de retorno desde la
dirección original por la 0x61616161.
A partir de aquí tendríamos que localizar en que punto
de las 250 a’s tenemos que insertar nuestra dirección 0x8048474. Esto lo
podemos hacer cambiando las 250 a’s por grupos de 10 a’s, 10 b’s, 10 c’s....
Una vez encontrado el grupo de 10, cambiamos ese grupo por abcdefgijk y comprobando
el valor del registro eip con los valores hexadecimales de las letras tendríamos
la posición exacta en la que poner nuestra dirección de la pista 0x8048474, tendríamos
que buscar el valor hexadecimal de las letras en orden inverso al que vemos en
gdb, ej. Si el error se produce en 0x64636261 serían las letras de la posición abcd
(Little endian). El resto de letras las podemos omitir, puesto que una vez
llegado a ese punto el programa va a continuar la ejecución en la nueva
dirección que le indiquemos. El 0x8048474 lo tendremos que escribir también ivnertido:
0x74840408 (Little endian).
Realizada la búsqueda de la posición por el método anterior
vemos que tras la introducción de 212 a’s, los 4 caracteres siguientes son los
que van a machacar la dirección de retorno y dirigirnos a la dirección de
memoria que le indiquemos, en este caso la dirección de la pista.
Para escribir estos 4 bytes hexadecimales de la dirección a
continuación de las a’s podemos crear un archivo con un editor hexadecimal y
luego dirigirlo al programa con el comando cat o podemos usar Python o Perl
para generar una cadena de texto con letras junto con la dirección al programa:
Con este comando creamos 212 a’s y a continuación la
dirección y luego lo dirigimos al programa.
Contraseña: “GNU/Linux”
No hay comentarios:
Publicar un comentario