Decentralized Write Up

Buenas a todos ! En esta primera entrada del Blog os traigo la resolución a un reto muy interesante planteado en el CTF del congreso HoneyCon, organizado por la gente de Follow the White Rabbit. Muchas gracias a los organizadores por el tremendo curro.

La descripción del reto:

Nuestro equipo de inteligencia ha detectado una serie de transacciones maliciosas en una conocida criptomoneda, se han podido extraer dos transacciones importantes que aseguran ser de procedencia relacionada con el terrorismo y el narcotráfico, es mandatorio que consigas extraer la clave privada para que nuestro equipo pueda desproveer de fondos a esta terrorifica organización.

El formato de la flag es la clave privada en hexadecimal (0x010203..) dentro del formato habitual, es decir: honeyCON18{0x..}

Informacion extraida:

PublicKey: 0x02 33 c3 4b c8 d6 fa a1 51 ad c5 07 34 c6 fb 6a c7 ff 8c fa 76 d8 02 87 2c a2 06 76 87 3b 70 3e 5a

Transaction Hash: 0x71 c3 42 95 40 57 28 ea 65 f8 ca b8 72 34 80 75 b5 15 93 ab 16 30 ff 0d 35 9f c1 7e 68 89 2c f2

Signature:0x7d0543872fd6dda231d31b3d42a6717ed162a1a5124ef67cb9f84 3bb555ec6d6648b78d767616c2c91e2bf75dbca6fdbeb8fb19ff53420fcac937c937ff291b0


PublicKey: 0x02 33 c3 4b c8 d6 fa a1 51 ad c5 07 34 c6 fb 6a c7 ff 8c fa 76 d8 02 87 2c a2 06 76 87 3b 70 3e 5a

Transaction Hash: 0x8a 3a 8d fc d2 77 be b4 aa 59 ba 5b 93 6f 3a f3 8f 08 dc 03 92 85 8c f4 75 c5 1d c6 24 7c 3d 90

Signature:0x7d0543872fd6dda231d31b3d42a6717ed162a1a5124ef67cb9f843 bb555ec6d68e5685ba5e526f5923e2c07e9bf757b5ab2c6f9648f0f769a2669a1a34f8a243

Vamos al lío. Lo primero, averiguar el tipo de criptomoneda utilizada. Por el tamaño de clave pública (32 bytes + 1 cabecera), y el hash de las transacciones (32 bytes), se trata de dos transacciones de bitcoin. El algoritmo de criptografía detrás de esta criptomoneda está basado en curvas elípticas, más en concreto en secp256k1.

Despues de entender un poco como funciona la firma en bitcoin, buscamos ataques a este algoritmo, donde nos encontramos con Same k attack. Resumiendo el vídeo porque es un tostón no todos tenemos tiempo para verlos, es posible recuperar una clave privada de dos transacciones las cuales la r de cada firma se halla formado con la misma k (que es un valor aleatorio que no se debería repetir, que quede claro).

Para ejecutar este ataque a nuestras transacciones, utilizo un script en ruby, el cuál encontre tras horas de búsqueda en un post de stackexchange, y al que he tuneado un poco.

El hash de la firma de bytes no estaba en formato DER, luego los parseamos:

sig1_hex = '304402207d0543872fd6dda231d31b3d42a6717ed162a1a5124ef67cb9f843bb555ec6d60220648b78d767616c2c91e2bf75dbca6fdbeb8fb19ff53420fcac937c937ff291b0'
sig2_hex = '304402207d0543872fd6dda231d31b3d42a6717ed162a1a5124ef67cb9f843bb555ec6d602208e5685ba5e526f5923e2c07e9bf757b5ab2c6f9648f0f769a2669a1a34f8a243'

Introducimos los mensajes(Transaction hash) y la clave pública, y ejecutamos.

_config.yml

No entiendo ruby, pero al tratar el segundo s, interpretaba 08 como f y petaba. La solución a esto, es simplemente meter el entero a mano en cada llamada a sig2.s (eran 4).

field.mod((z1 - z2) * field.inverse(sig1.s - sig2.s))
lo cambiamos a
field.mod((z1 - z2) * field.inverse(sig1.s - Integer("0x8e5685ba5e526f5923e2c07e9bf757b5ab2c6f9648f0f769a2669a1a34f8a243")

Con esto, tendriamos la clave.

_config.yml

El código completo está aquí

Dentro de poco más.

Written on November 10, 2018