Capture the Coins – Bitcoin Challenge – Explicado

En Agosto de 2014, Kulkan Security participó del “Capture the coins” challenge, presentado por coinspect.co – realizado para Ekoparty 2014. En este artículo los guiamos paso a paso por el razonamiento que nos llevó a solucionar el desafío, y les mostramos en detalle las herramientas y metodología que utilizamos en el proceso.

La intención es que los lectores del articulo no solo entiendan el challenge de coinspect.co y como solucionarlo, sinó que también puedan adoptar técnicas para utilizar en un cruce entre Bitcoin e Infosec en un futuro. Si bien intento escribir esto de la manera mas clara y efectiva (con el diario del Lunes abajo del brazo..) quisiera aclarar que el challenge llevó bastantes horas de dibujar en papeles cual loco, de estar al borde de un ataque de locura, e incluso vino a visitarme mientras dormía. Esta bien equivocarse, esta genial sufrir aprendiendo – ahora de estas cosas no me olvido más. Acompáñenme en el proceso de pasar de entender 0.00 Bitcoin, a 0.01 Bitcoin (o 1000000 satoshi.)

El artículo esta organizado en PARTES, les sugiero que no se salteen ninguna:



PARTE 0 – INTRO AL CHALLENGE

Coinspect primero muestra de evidencia via twitter la siguiente direccion:

3GSgmPLShQpKGDbLaAXJ6t1dknu5NmY1eZ

Con el siguiente aviso: “The multisig wallet used to test the Copay exploit is broken for ever? Take the bitcoins if you can.”

y vía la lista de Ekoparty, presenta otra dirección:

32GkPB9XjMAELR4Q2Hr31Jdz2tntY18zCe

avisando que se podía “ganar algunos bitcoins” (similar a lo que publicaron via coinspect.)

Luego publican via twitter la actualización:

..bitcoins still there and more coming. Best write up about the challenge gets VIP ticket to @ekoparty.32GkPB9XjMAELR4Q2Hr31Jdz2tntY18zCe



PARTE I – RECOLECTANDO FUENTES DE INFORMACION

Entonces, comenzamos con la siguiente informacion:

  • El ataque implica poder explotar un bug relacionado al Advisory de coinspect: “Copay wallet emptying vulnerability
  • El objetivo del ataque es poder enviarnos bitcoins a un address nuestro.

Acto seguido, buscamos el advisory para “Copay wallet emptying vulnerability”, que deriva en los dos siguientes links:

Digerimos el advisory, y para las cosas que no entendemos de Bitcoin investigamos y encontramos documentos útiles:

Accedemos al link de blockchain.info que nos pasaron al inicio, y vemos que el sitio puede usarse para:

  • Ver transacciones e info para direcciones (ej: https://blockchain.info/address/32GkPB9XjMAELR4Q2Hr31Jdz2tntY18zCe)
  • Ver detalle de transacciones (ej https://blockchain.info/tx/6102bfd4bad33443bcb99765c0751b6b8e4e65f4db4e3b65324c5e9e3dac8132)
  • Entre muchas otras cosas, algunas proveidas en su API: https://blockchain.info/api


PARTE II – ENTENDIENDO EL BUG DE COPAY Y LOS SIGHASH TYPES

Algo que Coinspect hace enfasis al respecto en su Twit y luego en la lista de Ekoparty, es que el advisory de “Wallet emptying” encontrado en Copay esta estrictamente relacionado con el challenge. Entonces pasamos a leer el Advisory (les recomiendo que lo lean, y vean el video en coinspect.co.), utilizando de apoyo los sources of information listados arriba. Aqui va nuestra explicacion:

  • El problema es en Copay (https://copay.io), y fue arreglado luego de que coinspect les avisara.
  • Esta relacionado a multisignature wallets – donde mas de 1 persona es dueña de una direccion y autoriza una transaccion a 1 o mas destinatarios.
  • Sucede porque al momento de armar una propuesta de transaccion, la segunda persona que firma la misma (y/o subsecuentes), no se da[n] cuenta que esta[n] firmando una transaccion con HASHTYPE_NONE, o HASHTYPE_SINGLE. En vez de forzar HASHTYPE_ALL, copay utiliza el “hashtype” proveido por quien inicio la propuesta de transaccion.

Veamos un ejemplo didáctico:

Imaginemos una entidad bancaria en la cual se puede abrir cuentas, depositar dinero y emitir cheques para retirar o transferir dinero. El banco permite abrir cuentas particulares, o de empresa. Para la cuenta particular, el dueño de la cuenta es el unico que firma sus cheques. Para la cuenta de empresa, el banco provee seguridad y requiere que al menos 2 de 3 socios (o 4 de 6, o 7 de 10, etc.. eso se decide al crear la cuenta) firmen los cheques para que estos sean considerados validos. De esa manera (en este ejemplo), al menos 2 de los 3 socios autorizan cuanto dinero se paga, y a quien se le paga. De modo contrario, 1 socio podria, en contra de su voluntad o no, llevarse todo el dinero de la cuenta armando y firmando uno o varios cheques.

El banco brinda un beneficio mas! Si varias dueños de cuenta (particulares y/o empresas) se ponen de acuerdo, pueden emitir un cheque en comun para pagar a una o mas personas/entidades. Si dos empresas comparten el alquiler de un piso en un departamento por ejemplo, pueden ponerse de acuerdo en emitir un cheque 1 vez al mes, donde cada uno pague la mitad del costo del alquiler, y como destinatario pondrian al dueño. Lo mismo si fuera una o mas empresas y uno o mas particulares, o entre particulares. Tambien podrian poner como destinatario el alquiler, la luz, Internet, todo en un mismo cheque con montos separados para cada uno. Es simple!

Ahora, tengamos en cuenta que hay formas distintas de firmar el cheque. Cada empresa, o particular, que aparezcan en el cheque como cuentas desde las cuales se obtienen los fondos, decide de que manera firmar el papel. En una cuenta empresarial, todos los socios que firmen deben ponerse de acuerdo en firmar de la misma manera. En una cuenta individual, no hay mucho que acordar dado que solo hay 1 firma, la del unico dueño.

Las formas de firmar el cheque son:

SIGHASH_ALL – Se firma la cara visible del cheque. La tinta pasa por encima del nombre de cada destinatario y el monto que le corresponde. De esa manera, si el cheque cae en malas manos, nadie puede borrar o cambiar los nombres de destinatarios, o los montos, y reescribirlo.

SIGHASH_SINGLE – Se firma la cara visible del cheque, parecido a SIGHASH_ALL, pero se firma unicamente por encima del monto y nombre del destinatario que esta en el mismo renglon o linea de la empresa o particular que esta firmando. Por eso se llama SINGLE – en espanol “solo”; porque el particular/empresa decide firmar por encima de 1 solo de los destinatarios. Si hay solo 1 destinatario en el cheque, entonces en teoria el cheque es seguro. Pero si hay mas cantidad de destinatarios que de empresas/particulares que originan el cheque, y estos deciden firmar como SIGHASH_SINGLE, entonces los destinatarios que queden por debajo/encima de la ultima cuenta de origen de fondos, quedaran sin firma. Situacion riesgosa!

SIGHASH_NONE – Se firma la parte de atras del cheque! La tinta no llegar a pisar ningun nombre o monto de destinatarios. Las firmas son requeridas, pero el banco valida las firmas en la parte de atras del cheque. Esto es lo mas parecido a un cheque en blanco! Horror!

SIGHASH_ANYONECANPAY – En este caso, quienes se hayan puesto de acuerdo para crear el cheque (1 o mas empresas/individuos) – pueden agregar una leyenda al cheque donde permiten que otras empresas/individuos con cuentas se sumen al pago! Tendria sentido para, por ejemplo, un cheque con una Donación.

El cheque termina siendo seguro o inseguro en base a si se han firmado todos los destinatarios, algunos, o ninguno – una vez que todos los que ponen fondos hayan terminado de firmar.

El advisory de Copay considera un escenario malicioso dentro de 1 cuenta empresa. Donde los socios asumen que los cheques que su empresa emite son de tipo SIGHASH_ALL, pero el socio maligno puede imponer un tipo de cheque de SIGHASH_SINGLE o SIGHASH_NONE. Los socios creen que estan firmando el cheque seguro; pero el socio maligno puede:

1) De usar SIGHASH_NONE, puede directamente cambiar 1 o mas destinatarios y los montos. Termina con un cheque valido en sus manos, equivalente a un cheque en blanco. Un golazo para el tipo.

2) De usar SIGHASH_SINGLE y el cheque esta dirigido a dos o mas destinatarios, puede cambiar uno o mas destinatarios y sus montos.

En otras palabras, Copay le permitia a quien originaba la propuesta de transaccion establecer el HashType para toda la propuesta! Cuando en realidad se deberia haber forzado SIGHASH_ALL. Por suerte, ahora, Copay fuerza SIGHASH_ALL.

Bueno, a este punto entendemos el uso de los HashTypes, y entendemos el bug de Copay que ya fue arreglado. Pero.. de que nos sirve todo esto? Ya veremos! Ahora a la PARTE III.



PARTE III – CONCEPTOS BASE & PYCOIN

A partir de este momento asumimos que ya leimos los sources arriba listados de Bitcoin y entendemos:

  • Que en bitcoin las monedas pasan de 1 o mas inputs a 1 o mas outputs.
  • Que es un output unspent (se compone por la direccion de la transaccion[tx] + el index, que arranca en 0, e indica donde quedo coins sin gastar [parentesis dentro de parentesis: sin gastar == que no hay otra transaccion _validada_ que referencie a ese output como un input]) Tambien cabe aclarar que, por mas que una transaccion referencie al output unspent como input e incluya un monto de transferencia _menor_ al monto disponible como ‘unspent’, el restante del monto _no se guarda_ sres. Se regala! Se paga como fee de la transaccion; cual donacion voluntaria. Por eso hay que tener extremo cuidado al momento de crear una transaccion a mano, de no errarle al monto que especificamos recibe el/los destino[s].
  • Que bitcoin usa un lenguaje de SCRIPT propio para validar firmas, hashear, copiar cosas, etc.
  • Que el lenguaje de SCRIPT se usa en la parte de output de una transacción y ahi se llama ScriptPubKey.
  • Que el lenguaje de SCRIPT también se usa en la parte de Input de una transacción, y ahi se llama ScriptSig.
  • Que el ScriptPubKey se usa para establecer condiciones al momento de validar una transacción que utilice tal output como input

Si el bug de Copay tiene que ver con HashTypes y la manera en la cual estan armadas las firmas, vamos a necesitar ver el contenido de una transaccion. Buscando en google, encontramos varias opciones Web. Pero finalmente vamos a darnos cuenta que algo command-line va a ser mas practico/mas comodo (al menos en nuestro caso), y damos con:

https://github.com/richardkiss/pycoin

Bajamos e instalamos. Es super simple de instalar y de usar [python setup.py install] – Tiene un par de comandos interesantes, pero el que vamos a utilizar ahora es “tx”. Leemos toda la documentacion disponible en:

https://github.com/richardkiss/pycoin/blob/master/COMMAND-LINE-TOOLS.md

Pero.. que transaccion miramos? Y cual de los 2 address que publico coinspect es el indicado? Lo vemos en la siguiente parte, dale? dale.



PARTE IV – IDENTIFICANDO EL BT ADDRESS VICTIMA

Tenemos 2 direcciones de Bitcoin proveidas por Coinspect al challenge. Cual miramos? las dos nos sirven? ninguna? El objetivo del challenge es poder enviarnos Bitcoins a una cuenta nuestra, por lo que tenemos que partir de una transaccion a un address cuyos Coins todavia esten “unspent” (sin gastar.) Si el bug estuviera relacionado a outputs “spent” – mas que challenge esto seria un quilombo; asi que damos por _sentado_ que la idea es enviarnos bitcoins _unspent_.

Cargamos los address de coinspect en Blockchain.info:

https://blockchain.info/address/3GSgmPLShQpKGDbLaAXJ6t1dknu5NmY1eZ
https://blockchain.info/address/32GkPB9XjMAELR4Q2Hr31Jdz2tntY18zCe

y buscamos dinero sin gastar (unspent.) Tambien podemos utilizar ahora que tenemos instalado el pack de “pycoin”, el comando fetch_unspent, de la siguiente manera:

Como ven arriba, la primera direccion no devolvio nada, no tiene un saldo unspent. La segunda, si. Asi que ya identificamos, con un alto nivel de posibilidad, que el dinero lo tenemos que transferir DESDE la direccion 32GkPB9XjMAELR4Q2Hr31Jdz2tntY18zCe.

Sin importar como hayamos hecho el análisis, via blockchain.info, o fetch_unspent, tambien vemos que la transaccion (en este caso) cuyo output es la direccion victima (32GkPB9XjMAELR4Q2Hr31Jdz2tntY18zCe) con saldo disponible, tiene de id:

9a5b462b6ecae93fc091cb9d3402c8c1e053ae30720150509c029e9e92602bd1.

Muy bien; entonces – hasta ahora – tenemos lo que creemos es:

  • La dirección victima con saldo unspent de la cual vamos a “pedir prestado” bitcoins: 32GkPB9XjMAELR4Q2Hr31Jdz2tntY18zCe
  • La transacción que posee en alguno de sus outputs a la dirección victima, y posee saldo “unspent”: 9a5b462b6ecae93fc091cb9d3402c8c1e053ae30720150509c029e9e92602bd1

Pero.. si entendimos el ejemplo de la PARTE II, necesitaríamos encontrar un cheque o transacción inseguro/a que este originada por la cuenta con saldo disponible para alterar! Un cheque donde los autorizantes hayan firmado con SIGHASH_NONE o SIGHASH_SINGLE.

Para eso, vuelvo a blockchain.info y busco transacciones originadas por la cuenta victima:
http://blockchain.info/address/32GkPB9XjMAELR4Q2Hr31Jdz2tntY18zCe

Encuentro una con id “6102bfd4bad33443bcb99765c0751b6b8e4e65f4db4e3b65324c5e9e3dac8132” que posee 3 inputs, y los 3 son del mismo address (didacticamente: serian 3 cuentas empresariales distintas, pero de la misma empresa.):
https://blockchain.info/tx/6102bfd4bad33443bcb99765c0751b6b8e4e65f4db4e3b65324c5e9e3dac8132

Dentro de la informacion que nos muestra blockchain, no es evidente que HashType utiliza cada uno de los inputs. Entonces aprovechamos que tenemos instalado “tx”, y con el siguiente comando obtenemos un dump en Hexa de toda la transaccion:

La parte que nos interesa es el dump en hexadecimal al final del output. En el paso siguiente vemos como parsear los datos para entender que HashType se utilizó, entre otras cosas!



PARTE V – DESARMANDO UNA TX E IDENTIFICANDO LOS HASHTYPES

Usando el comando “tx”, en la PARTE IV bajamos el contenido de una transaccion encodeada en hexadecimal. Podemos utilizar distintas herramientas para desencodearla, como por ej: https://blockchain.info/decode-tx, pero siempre es mas lindo si lo hacemos a mano. Usando los documentos de Bitcoin ya mencionados, a la transaccion de la PARTE IV la vemos de la siguiente manera:

01000000 [Version]
03 [Cantidad de Inputs totales en la transaccion]
77b5aa00744a7fee0754bcacb5aa5c46c8bd03ad3c1fd3f1ad5dacc3ca402aec [primera TX de input, invertido: ec..77]
01000000 [index dentro de la TX anterior. Arranca en 0]
fdff00
00 [Comienzo de Firmas/Signatures]
48 [Cantidad de bytes que ocupa la primera Firma]
3045022100e5d7c59ea1fb5d0285e755dfc09634e1e3af36d12950b9b5d5f92b136021b3d202202c181129443b08dcfb8d9ced3018
7186c57c96f9cdb3f3914e0798682ea35d2b
03 [HashType! Lo encontramos. Al final de CADA firma, se incluye el Hashtype.]
49 [Cantidad de bytes que ocupa la segunda Firma]
3046022100e1f8dbad16926cfa3bf61b66e23b3846323dcabf6c75748bcfad762fc50bfaf402210081d955160b5f8d2b9d09d8838a2
cf61f5055009d9031e0e106e19ebab234d949
03 [HashType de la segunda firma]
4c [OP_PUSHDATA1]
69 [OP_VERIFY]
52 [OP_2 – Se usa de separador, y al ser _2 establece ‘un minimo de 2 firmas’]
21 [Largo de la primera public key]
023927b5cd7facefa7b85d02f73d1e1632b3aaf8dd15d4f9f359e37e39f0561196
21 [Largo de la segunda public key]
03d2c0e82979b8aba4591fe39cffbf255b3b9c67b3d24f94de79c5013420c67b80
21 [Largo de la tercera public key]
03ec010970aae2e3d75eef0b44eaa31d7a0d13392513cd0614ff1c136b3b1020df
53 [OP_3 – Se usa de separador, y al ser _3 establece ‘de un total de 3 pubkeys’]
ae [OP_CHECKMULTISIG – Verifica las firmas!]
ffffffff [Separador entre Inputs. Lo anterior fue todo lo del primer Input]
06198d754e425f17f7d749dd8c2f03538159621d0c69ad1d71c7768b22fdeb30 [segunda TX de input, invertida]
00000000 [Indice dentro de la TX]
fdfe00
00 [Comienzan firmas]
49 [Largo de la firma, 0x49]
3046022100b762c6946eb7f349e53cb5b7f129375bfee75a1b5e042c2e2f26233af106f54c022100be0e0f8838681ef439f931709c93
5fbff4cca1949f4b9ad4ef143857180c0698
03 [HashType]
47 [Largo de la siguiente firma, 0x47]
30440220275e7e34a066fdaacfd63030bca9e234f4380b6ae2c0f20e6ffe0dd6ddd7e24702202f62435cc36d4ada9586d605faa039e9f5a1e2684631152c96d8dd5850171825
03 [HashType]
4c [OP_PUSHDATA1]
69 [OP_VERIFY]
52 [OP_2: Minimo 2 firmas]
21 [Largo public key #1]
023927b5cd7facefa7b85d02f73d1e1632b3aaf8dd15d4f9f359e37e39f0561196
21 [Largo public key #2]
03d2c0e82979b8aba4591fe39cffbf255b3b9c67b3d24f94de79c5013420c67b80
21 [Largo public key #3]
03ec010970aae2e3d75eef0b44eaa31d7a0d13392513cd0614ff1c136b3b1020df
53 [OP_3: ..de un total de 3 keys]
ae [OP_CHECKMULTISIG – Verifica las firmas!]
ffffffff [Separador entre Inputs]
c50f192f5d21fd1ea12488cac94536f7428ad9aebf5ee7a106e26a80d47637c2 [Tercer input TX, invertido]
00000000 [Indice dentro de la TX]
fdfd00
00 [Comienzan firmas]
48 [Largo de la firma, 0x48]
3045022100dfcfafcea73d83e1c54d444a19fb30d17317f922c19e2ff92dcda65ad09cba24022001e7a805c5672c49b222c5f2f1e67bb
01f87215fb69df184e7c16f66c1f87c29
03 [HashType]
47 [Largo siguiente firma, 0x47]
304402204a657ab8358a2edb8fd5ed8a45f846989a43655d2e8f80566b385b8f5a70dab402207362f870ce40f942437d43b6b993
43419b14fb18fa69bee801d696a39b3410b8
03 [HashType]
4c [OP_PUSHDATA1]
69 [OP_VERIFY]
52 [OP_2: Minimo 2 firmas]
21 [Largo public key #1]
023927b5cd7facefa7b85d02f73d1e1632b3aaf8dd15d4f9f359e37e39f0561196
21 [Largo public key #2]
03d2c0e82979b8aba4591fe39cffbf255b3b9c67b3d24f94de79c5013420c67b80
21 [Largo public key #3]
03ec010970aae2e3d75eef0b44eaa31d7a0d13392513cd0614ff1c136b3b1020df
53 [OP_3: ..de un total de 3 keys]
ae [OP_CHECKMULTISIG – Verifica las firmas!]
ffffffff [Separador: Ahora comienza la seccion de OUTPUT]
02 [Cantidad de outputs: 2]
204e000000000000 [Cantidad de Satoshis que recibe el 1er output: 0x4e20 == 20000]
19
76a9 [OP_DUP, OP_HASH160]
14 [Largo del address/hash de Destino]
123a7dc5daca3b4a6ebb5ca788b60405dcee84ee
88ac [OP_EQUALVERIFY, OP_CHECKSIG]
e075090000000000 [Cantidad de Satoshis que recibe el 2ndo output: 0x9075e0 == 620000]
17
a9 [OP_HASH160]
14 [Largo del address/hash de Destino #2]
1f420aab25a69dc3a192ffc7f937fc82bb57afb6
87 [OP_EQUAL]
00000000

Resumiendo lo que vemos arriba, de haber parseado la TX:

  • Hay 3 inputs.
  • Cada uno de los 3 inputs lleva 2 firmas, de un total de 3 posibles.
  • Cada firma tiene un HashType 0x03 [SIGHASH_SINGLE]
  • Hay 2 outputs.


PARTE VI – ENCONTRAMOS UNA TX CON SIGHASH_SINGLE

Como vimos en la TX que desarmamos en la PARTE V, ya tenemos los HashTypes que fueron utilizados en la transaccion. Los mismos son 0x03, y segun la documentacion de OP_CHECKSIG (https://en.bitcoin.it/wiki/OP_CHECKSIG), significa que son SIGHASH_SINGLE. TODOS los INPUT de la TX usan ese HashType.

Recordando lo que aprendimos con el bug de Copay, nos damos cuenta que cada INPUT esta firmando UN solo OUTPUT. El OUTPUT que esta en su mismo indice/renglon/nivel. Esto quiere decir que, siendo los inputs:

INPUT 1 – ec2a40cac3ac5dadf1d31f3cad03bdc8465caab5acbc5407ee7f4a7400aab577:1
INPUT 2 – 30ebfd228b76c7711dad690c1d62598153032f8cdd49d7f7175f424e758d1906:0
INPUT 3 – c23776d4806ae206a1e75ebfaed98a42f73645c9ca8824a11efd215d2f190fc5:0

y los outputs:

OUTPUT 1– 12fPEVz7t6tpvUUCzMT1iCCmtKcNqpUhv1 [20000 Satoshis == 0.0002 BTC]
OUTPUT 2 – 34YHz9Suwcfi1DsgvMwQVVyy1k5dX5oN6B [620000 Satoshis == 0.0062 BTC]

Entonces INPUT 1, firma OUTPUT 1. Y luego INPUT 2, firma OUTPUT 2.

Pero.. INPUT 3? Recordamos el ejemplo de Mayor cantidad de Outputs que Inputs. Pero que pasa si hay un INPUT extra, firmado con SIGHASH_SINGLE? Firma una parte fuera del cheque? Se pasa de los limites del papel y escribe en la mesa? Nos volvemos locos. Dormimos mal. No entendemos porque el mundo es un lugar tan oscuro.

Y luego, releyendo una vez mas el documento que leimos un centenar de veces.. (https://en.bitcoin.it/wiki/OP_CHECKSIG) encontramos bajo la descripcion de SIGHASH_SINGLE:

“Note: The transaction that uses SIGHASH_SINGLE type of signature should not have more inputs than outputs. However if it does (because of the pre-existing implementation), it shall not be rejected, but instead for every “illegal” input (meaning: an input that has an index bigger than the maximum output index) the node should still verify it, though assuming the hash of 0000000000000000000000000000000000000000000000000000000000000001″

El parrafo arriba dice que, si bien una TX con inputs SIGHASH_SINGLE no debe tener nunca mas inputs que outputs, en el caso de tenerlos, no debe ser rechazada. Y por ende cada INPUT que esta de mas, debe ser satisfactoriamente verificado. Esto es por compatibilidad con implementaciones anteriores.

Nos golpeamos la cabeza contra la mesa. Entendemos que estamos cerca, pero no conectamos todavia los puntos.



PARTE VII – OTRA PERSPECTIVA AYUDA A CONECTAR LOS PUNTOS

Para intentar conectar los puntos, cambiamos la forma de ver el problema. Pasamos a plantear como deberia ser la TX que publicaremos en la red de Bitcoin, para que sea validada y nos llevemos las monedas de 32GkPB9XjMAELR4Q2Hr31Jdz2tntY18zCe.

Pensamos en la transaccion base:

  • De INPUT, usamos una transaccion con saldo unspent de 32GkPB9XjMAELR4Q2Hr31Jdz2tntY18zCe
  • De OUTPUT, usamos una direccion nuestra.

Para poder utilizar de INPUT una transaccion de 32GkPB9XjMAELR4Q2Hr31Jdz2tntY18zCe, tenemos que poder crear la firma! Necesitamos la clave privada, y consideramos que no es parte del challenge empezar a enviarle e-mails con client-side a Coinspect. Ademas, eso seria la forma OFICIAL de resolver el problema, y nosotros queremos aplicar la magia del bug de Copay.

Si no podemos crear la firma de 32GkPB9XjMAELR4Q2Hr31Jdz2tntY18zCe – podemos reusar una firma de ellos creada antes? Algo se activa en la cabeza. Justamente, si una transaccion fue creada de manera insegura por medio de SIGHASH_NONE o SIGHASH_SINGLE, podriamos usar las firmas (plural, porque recordemos son m2..n3, o.. 2 de 3) y encontrar la manera de cambiar el output a nuestra direccion! Pero como?!

  1. De INPUT usamos una transaccion con saldo unspent de 32GkPB9XjMAELR4Q2Hr31Jdz2tntY18zCe, y en donde va la firma del INPUT, la pisamos con una de las firmas de la transaccion con HashType 03 que obtuvimos antes (Luego explico como pisarla)
  2. De OUTPUT usamos una direccion nuestra.

Funciona? No! Tampoco. No funcionaría, porque Hay 1 input, y 1 output. Y ya vimos que SIGHASH_SINGLE requiere que se firme el output que esta en su mismo renglon/nivel/indice. Entonces necesitariamos la llave privada para que la firma incluya el output nuestro, y por mas que le roguemos a Coinspect que nos firme el output, no lo harán! maldicion!

Pero entonces.. agreguemos mas INPUTs!

voilà! Se ilumina el cielo. Se abren las nubes. Sale el Sol. Igual, de lo que pasa afuera no nos enteramos, porque estamos internados con la compu hace horas.

Si agregamos mas INPUTs, y dejamos solo ese output, entonces los SIGHASH_SINGLE que queden ‘de sobra’, por Ley de Bitcoin (lo que explicamos en la PARTE VI) no van a requerir de un OUTPUT firmado en su nivel, se conforman con el OUTPUT que firmo el otro / los otros INPUT[s]. Entonces:

INPUT #1 – Alguno que agreguemos extra. No lo agregamos en posicion #2 porque entonces volvemos al mismo tema. Y tampoco nos sirve agregar como INPUT una transaccion unspent de otra persona, porque no vamos a tener la llave privada para firmar el OUTPUT que esta en el mismo renglon/indice/nivel! Que agregamos?

INPUT #2 – La TX con Unspent de la direccion victima de la que nos vamos a llevar los Bitcoin.

OUTPUT #1 – Nuestra dirección! Aca vamos a recibir todas las monedas que, a esta altura, nos merecemos.

Pensamos que agregar para INPUT #1, y entre las opciones esta:

1- Buscar una TX con saldo unspent, de alguien que haya creado una transaccion insegura con SIGHASH_NONE. Un poco DIFICIL de encontrar a ultimo momento, pero podriamos intentar..

2- Poner una Tx con saldo unspent nuestra! Total la privada la tenemos – podemos firmar el OUTPUT nosotros mismos!

Elegimos la opcion #2.

A esta altura hace falta tener la clave privada para una direccion que tenga una transaccion unspent. Yo utilice el comando de pycoin “ku” para crear una nueva direccion, a la cual me transferi un saldo en BTC, que entonces quedo “unspent”. Intenten que el saldo que se transfieran sea muy bajo, para no perder mucho dinero en alguna equivocacion!



PARTE VIII – ARMANDO LA TRANSACCION MALICIOSA

De la parte anterior, ya sabemos que es lo que tenemos que hacer. Ahora, como armamos la TX? Para aprender, la pueden armar a mano, es una experiencia inolvidable. Pero sino, aqui muestro como utilizar el mismo comando “tx” para armarla, y luego editamos solo una partecita a mano.

1- Buscamos las transacciones con saldo unspent de nuestra direccion:

2- Buscamos las transacciones con saldo unspent de la direccion victima, en las cuales sabemos usaron HashType 0x03:

3- Creamos una transaccion sin firmar (una TX sin firmar simplemente tiene un relleno de Script en donde iria la firma, y obviamente es invalida hasta que incluya todas las firmas necesarias.) pasandole a “tx” una lista separada por espacios de INPUT tx’s con sus index IDs, montos, y al final el address de destino:

4- Validamos que la TX hasta ahora sea como nosotros queriamos:

Vemos que tx automaticamente calcula los montos de destino (de haber sabido que no era necesario hacerlo a mano en un principio..) y que al lado de cada input hay una leyenda “BAD SIG”. Es logico, todavia no esta firmado por nosotros nuestro Input, y el Input del address victima tampoco tiene la firma que nos vamos a robar de la TX con HashType 03.

4- Firmamos la TX con NUESTRA firma. Eso va a firmar NUESTRO input. Va a quedar todavia un INPUT sin firmar. Le pasamos a tx para esto nuestra clave privada en formato Wif (obviamente no incluida en el ejemplo):

legendary:Desktop lucas$ tx tx-unsigned.hex XXXXX-CLAVE-PRIVADA-FORMATO-WIF-XXXXXXXXX -o tx-signed.hex
signing…
warning: 1 TxIn items still unsigned
all incoming transaction values validated
legendary:Desktop lucas$

Verificamos de nuevo la TX, y vemos que efectivamente la TX esta casi del todo firmada. Nuestro input ahora dice “sig ok”. Falta nomas la firma de la victima:

5- Copiamos de la PARTE #5 los bytes de cualquiera de las firmas que tengan HashType 0x03, incluyendo las publicas. Desde el primer byte siguiente al indice del input dentro de la TX, hasta el ultimo byte antes del siguiente separador de INPUT (0xffffffff). Por ejemplo, una firma seria extraida seria:

fdff0000483045022100e5d7c59ea1fb5d0285e755dfc09634e1e3af36d12950b9b5d5f92b136021b3d202202c181129443b08dcfb8
d9ced30187186c57c96f9cdb3f3914e0798682ea35d2b03493046022100e1f8dbad16926cfa3bf61b66e23b3846323dcabf6c75748b
cfad762fc50bfaf402210081d955160b5f8d2b9d09d8838a2cf61f5055009d9031e0e106e19ebab234d949034c695221023927b5cd
7facefa7b85d02f73d1e1632b3aaf8dd15d4f9f359e37e39f05611962103d2c0e82979b8aba4591fe39cffbf255b3b9c67b3d24f94de79
c5013420c67b802103ec010970aae2e3d75eef0b44eaa31d7a0d13392513cd0614ff1c136b3b1020df53ae

Reemplazamos en “tx-signed.hex” que acabamos de firmar con el comando “tx”, el byte 0x00 que esta antes del separador 0xffffffff ultimo, que indica el inicio de la seccion OUTPUT (esto puede cambiar dependiendo de la cantidad de firmas claro, el tema es reemplazar la firma vacia, por la firma que copiamos.) Guardamos, y revalidamos la transaccion con el comando “tx”:

Lo hicimos! Tenemos una TX valida, con fondos originados en el INPUT victima! Festejamos!



PARTE IX – PUSHEANDO LA TX A LA RED BITCOIN Y COBRANDO LA RECOMPENSA

Lo unico que nos queda por hacer es pushear la transaccion a la red. Para esto tenemos varias tools, por ej:

https://blockchain.info/pushtx
http://mec.blockr.io/tx/push

Pero la herramienta que mejor nos sirvio para este proposito, fue “sx” (https://sx.dyne.org) con el parametro “sendtx-p2p”:

Y listo! A esperar a que la TX sea validada en la red, y cobremos la recompensa.

Espero que hayan disfrutado de algo tan aburrido y tan largo, que para algunos es tan divertido!



PARTE X – LINKS/HERRAMIENTAS/FUENTES DE INFORMACION

Leave a Reply

Your email address will not be published. Required fields are marked *