elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: AIO elhacker.NET 2021 Compilación herramientas análisis y desinfección malware


  Mostrar Temas
Páginas: 1 [2] 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ... 19
11  Seguridad Informática / Criptografía / Paridad de un punto en Curvas Elipticas Criptograficas en: 27 Febrero 2021, 09:08 am
Quisiera abrir el siguiente hilo para saber si es posible determinar la paridad de un punto en una curva Eliptica utilizada en criptografía.

Encontré un video en youtube donde un programador de C# afirma tener la formula para determinar si un punto dado es par o impar para una curva en especifico.

Tiene una pagina

:http://remon78eg.tk/curve/mod2/

Utiliza un valor P custom: 115792089237316195423570985008687907853269984665640564039457584007908834675927

El cual afirma que es un valor débil o vulnerable.

El usuario no revela mucho de su método o test de paridad de un punto o publickey.

Las preguntas aquí son las siguientes:
¿Qué tiene de débil o vulnerable su orden de la curva?
¿Cuál seria el test de paridad que se pueda implementar para determinar si un punto (X,Y) pertenece a una privatekey par o impar?

Saludos!
12  Seguridad Informática / Criptografía / Rompecabezas de Bitcoin, Medio millón USD en premios en: 8 Febrero 2021, 19:28 pm
TL:TR

El balance actual de los desafios 969 Bitcoin (29 Millones USD a la fecha de hoy 16 de Abril 2023).

Numero total de desafios es de 160 de los cuales ya fueron reclamados 76 quedando pendiente 84, la dificultad de los mismos es exponencial y cada desafio es el doble de dificl que el anterior.

Link con la informacion de todos los desafios:

https://docs.google.com/spreadsheets/d/1vZyRZ67iNl7aIwYNB55OY8LvZLAaoBxSanxqnGMZlWA/edit?usp=sharing



Lista de rompecabezas al final:

Muy buen día a todos últimamente hablando con Kub0x sobre curvas elípticas me sugirió publicar aquí los rompecabezas existentes de bitcoin, hay aproximadamente 12 bitcoin en premios. Para los rompecabezas Importantes y algunos otros bitcoin para rompecabezas pequeños.

Los rompecabezas se puede abordar de varias formas, pero abordarlos por fuerza bruta es casi imposible a no ser que tengan mucha mucha mucha suerte (El tema de Fuerza bruta exclusiva no va a ser tratado aqui).

Estos rompecabezas fueron hechos con el propósito explicito de ser crackeados desde el 2015 y en caso de conseguirlo pueden tomar el bitcoin de premio que se encuentra ahi, ya que el autor para eso los creo, fueron creados cuando el bitcoin se cambiaba por  160 Dolares cada uno, hoy en dia cuesta cada uno mas de 40 Mil dólares

A continuación los rompecabezas en el siguiente formato:
Código:
#Numero de Bits ( Dirección public de bitcoin ) Monto actual de la cartera
Inicio del rango del privatekey
Fin del rango del privatekey
Llave publica en formato comprimido

Puzzles:

Código:

#120 bits ( 17s2b9ksz5y7abUm92cHwG8jEPCzK3dLnT ) 1.20000000 BTC
800000000000000000000000000000
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
02CEB6CBBCDBDF5EF7150682150F4CE2C6F4807B349827DCDBDD1F2EFA885A2630

#125 bits ( 1PXAyUB8ZoH3WD8n5zoAthYjN15yN5CVq5 ) 1.25000000 BTC

10000000000000000000000000000000
1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
0233709EB11E0D4439A729F21C2C443DEDB727528229713F0065721BA8FA46F00E

#130 bits ( 1Fo65aKq8s8iquMt6weF1rku1moWVEd5Ua ) 1.30000000 BTC
200000000000000000000000000000000
3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
03633CBE3EC02B9401C5EFFA144C5B4D22F87940259634858FC7E59B1C09937852

#135 bits ( 16RGFo6hjq9ym6Pj7N5H7L1NR1rVPJyw2v ) 1.35000000 BTC
4000000000000000000000000000000000
7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
02145D2611C823A396EF6712CE0F712F09B9B4F3135E3E0AA3230FB9B6D08D1E16

#140 bits ( 1QKBaU6WAeycb3DbKbLBkX7vJiaS8r42Xo ) 1.40000000 BTC
80000000000000000000000000000000000
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
031F6A332D3C5C4F2DE2378C012F429CD109BA07D69690C6C701B6BB87860D6640

#145 bits ( 19GpszRNUej5yYqxXoLnbZWKew3KdVLkXg ) 1.45000000 BTC
1000000000000000000000000000000000000
1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
03AFDDA497369E219A2C1C369954A930E4D3740968E5E4352475BCFFCE3140DAE5

#150 bits ( 1MUJSJYtGPVGkBCTqGspnxyHahpt5Te8jy ) 1.50000000 BTC
20000000000000000000000000000000000000
3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
03137807790EA7DC6E97901C2BC87411F45ED74A5629315C4E4B03A0A102250C49

#155 bits ( 1AoeP37TmHdFh8uN72fu9AqgtLrUwcv2wJ ) 1.55000000 BTC
400000000000000000000000000000000000000
7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
035CD1854CAE45391CA4EC428CC7E6C7D9984424B954209A8EEA197B9E364C05F6

#160 bits ( 1NBC8uXJy1GiJ6drkiZa1WuKn51ps7EPTv )  1.60000793 Bitcoin
8000000000000000000000000000000000000000
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
02E0A8B039282FAF6FE0FD769CFBC4B6B4CF8758BA68220EAC420E32B91DDFA673


Para quienes piensen  abordar el puzzle por fuerza bruta, estos son mas o menos los tiempos estimados para escanear el rango completo de acuerdo a la velocidad conseguida:

Código:
Puzzle 120 @ 1 Terakeys/s :     21074771622667996 años
Puzzle 120 @ 1 Petakeys/s :     21074771622667 años
Puzzle 120 @ 1 Exakeys/s :      21074771622 años
Puzzle 120 @ 1 Zettakeys/s :    21074771 años
Puzzle 120 @ 1 Yottakeys/s :    21074 años
Puzzle 125 @ 1 Terakeys/s :     674392691925375886 años
Puzzle 125 @ 1 Petakeys/s :     674392691925375 años
Puzzle 125 @ 1 Exakeys/s :      674392691925 años
Puzzle 125 @ 1 Zettakeys/s :    674392691 años
Puzzle 125 @ 1 Yottakeys/s :    674392 años
Puzzle 130 @ 1 Terakeys/s :     21580566141612028377 años
Puzzle 130 @ 1 Petakeys/s :     21580566141612028 años
Puzzle 130 @ 1 Exakeys/s :      21580566141612 años
Puzzle 130 @ 1 Zettakeys/s :    21580566141 años
Puzzle 130 @ 1 Yottakeys/s :    21580566 años
Puzzle 135 @ 1 Terakeys/s :     690578116531584908094 años
Puzzle 135 @ 1 Petakeys/s :     690578116531584908 años
Puzzle 135 @ 1 Exakeys/s :      690578116531584 años
Puzzle 135 @ 1 Zettakeys/s :    690578116531 años
Puzzle 135 @ 1 Yottakeys/s :    690578116 años
Puzzle 140 @ 1 Terakeys/s :     22098499729010717059011 años
Puzzle 140 @ 1 Petakeys/s :     22098499729010717059 años
Puzzle 140 @ 1 Exakeys/s :      22098499729010717 años
Puzzle 140 @ 1 Zettakeys/s :    22098499729010 años
Puzzle 140 @ 1 Yottakeys/s :    22098499729 años
Puzzle 145 @ 1 Terakeys/s :     707151991328342945888372 años
Puzzle 145 @ 1 Petakeys/s :     707151991328342945888 años
Puzzle 145 @ 1 Exakeys/s :      707151991328342945 años
Puzzle 145 @ 1 Zettakeys/s :    707151991328342 años
Puzzle 145 @ 1 Yottakeys/s :    707151991328 años
Puzzle 150 @ 1 Terakeys/s :     22628863722506974268427923 años
Puzzle 150 @ 1 Petakeys/s :     22628863722506974268427 años
Puzzle 150 @ 1 Exakeys/s :      22628863722506974268 años
Puzzle 150 @ 1 Zettakeys/s :    22628863722506974 años
Puzzle 150 @ 1 Yottakeys/s :    22628863722506 años
Puzzle 155 @ 1 Terakeys/s :     724123639120223176589693541 años
Puzzle 155 @ 1 Petakeys/s :     724123639120223176589693 años
Puzzle 155 @ 1 Exakeys/s :      724123639120223176589 años
Puzzle 155 @ 1 Zettakeys/s :    724123639120223176 años
Puzzle 155 @ 1 Yottakeys/s :    724123639120223 años
Puzzle 160 @ 1 Terakeys/s :     23171956451847141650870193314 años
Puzzle 160 @ 1 Petakeys/s :     23171956451847141650870193 años
Puzzle 160 @ 1 Exakeys/s :      23171956451847141650870 años
Puzzle 160 @ 1 Zettakeys/s :    23171956451847141650 años
Puzzle 160 @ 1 Yottakeys/s :    23171956451847141 años

Si tienen alguna duda favor de comentarla en este hilo.

He creado un canal privado de Telegram, si alguno gusta discutir el tema ahí, favor de enviarme mensaje privado a https://t.me/albertobsd y si lo considero oportuno los agregare al grupo.



Take Bobby's Bitcoin

WEB:

Estos son 2 Desafios

#1
Wallet con 1.0 BTC
Public Address: 1JxWyNrkgYvgsHu8hVQZqTXEB9RftRGP5m
Private Key: 6PnQmAyBky9ZXJyZBv9QSGRUXkKh9HfnVsZWPn4YtcwoKy5vufUgfA3Ld7
BIP-38 Passphrase: ???

#2
Wallet con 1.0 BTC
Public Address: 1QGtbKxx6FKDD66LwnrzHCAHmyZ7mDHqC4
Private Key: ???
BIP-38 Passphrase: 594Y-L2RW-4ME7-2XVX-9B41
BIP-38 Confirmation Code: cfrm38VUh2i5qzzCqedWtc8ekFxT3UpcQnfb42JRrLbTWCRTfgVTCXqLp3FYxqiyQDo4D3DyWzY


Bitcoin Challenge Transaction

Transaccion: https://www.blockchain.com/es/btc/tx/08389f34c98c606322740c0be6a7125d9860bb8d5cb182c02f98461e5fa6cd15


El balance total restante es de 98.74 Bitcoin, las direcciones son:

Código:
16jY7qLJnxb7CHZyqBP8qca9d51gAjyXQN
13zb1hQbWVsc2S7ZTZnP2G4undNNpdh5so
1BY8GQbnueYofwSuFAT3USAhGjPrkxDdW9
1MVDYgVaSN6iKKEsbzRUAYFrYJadLYZvvZ
19vkiEajfhuZ8bs8Zu2jgmC6oqZbWqhxhG
1PWo3JeB9jrGwfHDNpdGK54CRas7fsVzXU
1JTK7s9YVYywfm5XUH7RNhHJH1LshCaRFR
12VVRNPi4SJqUTsp6FmqDqY5sGosDtysn4
1FWGcVDK3JGzCC3WtkYetULPszMaK2Jksv
1DJh2eHFYQfACPmrvpyWc8MSTYKh7w9eRF
1Bxk4CQdqL9p22JEtDfdXMsng1XacifUtE
15qF6X51huDjqTmF9BJgxXdt1xcj46Jmhb
1ARk8HWJMn8js8tQmGUJeQHjSE7KRkn2t8
15qsCm78whspNQFydGJQk5rexzxTQopnHZ
13zYrYhhJxp6Ui1VV7pqa5WDhNWM45ARAC
14MdEb4eFcT3MVG5sPFG4jGLuHJSnt1Dk2
1CMq3SvFcVEcpLMuuH8PUcNiqsK1oicG2D
1K3x5L6G57Y494fDqBfrojD28UJv4s5JcK
1PxH3K1Shdjb7gSEoTX7UPDZ6SH4qGPrvq
16AbnZjZZipwHMkYKBSfswGWKDmXHjEpSf
19QciEHbGVNY4hrhfKXmcBBCrJSBZ6TaVt
1EzVHtmbN4fs4MiNk3ppEnKKhsmXYJ4s74
1AE8NzzgKE7Yhz7BWtAcAAxiFMbPo82NB5
17Q7tuG2JwFFU9rXVj3uZqRtioH3mx2Jad
1K6xGMUbs6ZTXBnhw1pippqwK6wjBWtNpL
15ANYzzCp5BFHcCnVFzXqyibpzgPLWaD8b
18ywPwj39nGjqBrQJSzZVq2izR12MDpDr8
1CaBVPrwUxbQYYswu32w7Mj4HR4maNoJSX
1JWnE6p6UN7ZJBN7TtcbNDoRcjFtuDWoNL
1CKCVdbDJasYmhswB6HKZHEAnNaDpK7W4n
1PXv28YxmYMaB8zxrKeZBW8dt2HK7RkRPX
1AcAmB6jmtU6AiEcXkmiNE9TNVPsj9DULf
1EQJvpsmhazYCcKX5Au6AZmZKRnzarMVZu
18KsfuHuzQaBTNLASyj15hy4LuqPUo1FNB
15EJFC5ZTs9nhsdvSUeBXjLAuYq3SWaxTc
1HB1iKUqeffnVsvQsbpC6dNi1XKbyNuqao
1GvgAXVCbA8FBjXfWiAms4ytFeJcKsoyhL
1824ZJQ7nKJ9QFTRBqn7z7dHV5EGpzUpH3
18A7NA9FTsnJxWgkoFfPAFbQzuQxpRtCos
1NeGn21dUDDeqFQ63xb2SpgUuXuBLA4WT4
174SNxfqpdMGYy5YQcfLbSTK3MRNZEePoy
1MnJ6hdhvK37VLmqcdEwqC3iFxyWH2PHUV
1KNRfGWw7Q9Rmwsc6NT5zsdvEb9M2Wkj5Z
1PJZPzvGX19a7twf5HyD2VvNiPdHLzm9F6
1GuBBhf61rnvRe4K8zu8vdQB3kHzwFqSy7
17s2b9ksz5y7abUm92cHwG8jEPCzK3dLnT
1GDSuiThEV64c166LUFC9uDcVdGjqkxKyh
1Me3ASYt5JCTAK2XaC32RMeH34PdprrfDx
1CdufMQL892A69KXgv6UNBD17ywWqYpKut
1BkkGsX9ZM6iwL3zbqs7HWBV7SvosR6m8N
1PXAyUB8ZoH3WD8n5zoAthYjN15yN5CVq5
1AWCLZAjKbV1P7AHvaPNCKiB7ZWVDMxFiz
1G6EFyBRU86sThN3SSt3GrHu1sA7w7nzi4
1MZ2L1gFrCtkkn6DnTT2e4PFUTHw9gNwaj
1Hz3uv3nNZzBVMXLGadCucgjiCs5W9vaGz
1Fo65aKq8s8iquMt6weF1rku1moWVEd5Ua
16zRPnT8znwq42q7XeMkZUhb1bKqgRogyy
1KrU4dHE5WrW8rhWDsTRjR21r8t3dsrS3R
17uDfp5r4n441xkgLFmhNoSW1KWp6xVLD
13A3JrvXmvg5w9XGvyyR4JEJqiLz8ZySY3
16RGFo6hjq9ym6Pj7N5H7L1NR1rVPJyw2v
1UDHPdovvR985NrWSkdWQDEQ1xuRiTALq
15nf31J46iLuK1ZkTnqHo7WgN5cARFK3RA
1Ab4vzG6wEQBDNQM1B2bvUz4fqXXdFk2WT
1Fz63c775VV9fNyj25d9Xfw3YHE6sKCxbt
1QKBaU6WAeycb3DbKbLBkX7vJiaS8r42Xo
1CD91Vm97mLQvXhrnoMChhJx4TP9MaQkJo
15MnK2jXPqTMURX4xC3h4mAZxyCcaWWEDD
13N66gCzWWHEZBxhVxG18P8wyjEWF9Yoi1
1NevxKDYuDcCh1ZMMi6ftmWwGrZKC6j7Ux
19GpszRNUej5yYqxXoLnbZWKew3KdVLkXg
1M7ipcdYHey2Y5RZM34MBbpugghmjaV89P
18aNhurEAJsw6BAgtANpexk5ob1aGTwSeL
1FwZXt6EpRT7Fkndzv6K4b4DFoT4trbMrV
1CXvTzR6qv8wJ7eprzUKeWxyGcHwDYP1i2
1MUJSJYtGPVGkBCTqGspnxyHahpt5Te8jy
13Q84TNNvgcL3HJiqQPvyBb9m4hxjS3jkV
1LuUHyrQr8PKSvbcY1v1PiuGuqFjWpDumN
18192XpzzdDi2K11QVHR7td2HcPS6Qs5vg
1NgVmsCCJaKLzGyKLFJfVequnFW9ZvnMLN
1AoeP37TmHdFh8uN72fu9AqgtLrUwcv2wJ
1FTpAbQa4h8trvhQXjXnmNhqdiGBd1oraE
14JHoRAdmJg3XR4RjMDh6Wed6ft6hzbQe9
19z6waranEf8CcP8FqNgdwUe1QRxvUNKBG
14u4nA5sugaswb6SZgn5av2vuChdMnD9E5
1NBC8uXJy1GiJ6drkiZa1WuKn51ps7EPTv


Saludos!
13  Programación / Programación General / Ordenar archivo binario de 100GB en: 21 Enero 2021, 05:02 am
Ok, veamos necesito una forma eficiente de ordenar un archivo de de 100 GB, Cada registro del archivo son 36 Bytes en binario.

Usualmente lo hacia con archivos pequeños 10 o 5 GB pero en RAM. Esto con el algoritmo Introsort y es bastante eficiente, pero ahora estoy utilizando el mismo método pero en Disco duro ya que el archivo es muy grande, Lo que estoy haciendo es leer los registros del disco, cargarlos en memoria, compararlos y escribir en disco en caso de que necesiten ser ordenados. Este proceso es muy lento directo en el disco duro.

Podría tratar de dividir el proceso he ir cargando de 10 en 10 GB en RAM u otra cantidad ordenarlos en memoria y seguir con los demás pedazos, sin embargo el problema es ordenar entre pedazos separados.

El proceso de generación de registros es aleatorio y no se en que orden se generaran los registros, quiero hacer este proceso lo mas eficiente y rápido posible, ya que si funciona este archivo tendré que generar un archivo similar de 500 o 1000 GB. No tengo problemas de Espacio en disco.

¿Alguna idea adicional a hacerlo directo desde el disco duro?


Edit:

Ayer miestras publicaba este teme tambien pense en la solucion, pero no queria publicarla hasta implementarla.

Dado que la generación de los registros es aleatoria y es uniforme entre el rango de A a B entonces se me ocurre que una vez generado el archivo de 100 GB, dividir el rango de A a B en subrangos manejables en RAM
por decil algo tengo los siguientes rangos para registros de 32 bytes:

Código:
From 0000000000000000000000000000000000000000000000000000000000000000 to 0ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
From 0ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc to 1999999999999999999999999999999999999999999999999999999999999998
From 1999999999999999999999999999999999999999999999999999999999999998 to 2666666666666666666666666666666666666666666666666666666666666664
From 2666666666666666666666666666666666666666666666666666666666666664 to 3333333333333333333333333333333333333333333333333333333333333330
From 3333333333333333333333333333333333333333333333333333333333333330 to 3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc
From 3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc to 4cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc8
From 4cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc8 to 5999999999999999999999999999999999999999999999999999999999999994
From 5999999999999999999999999999999999999999999999999999999999999994 to 6666666666666666666666666666666666666666666666666666666666666660
From 6666666666666666666666666666666666666666666666666666666666666660 to 733333333333333333333333333333333333333333333333333333333333332c
From 733333333333333333333333333333333333333333333333333333333333332c to 7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8
From 7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8 to 8cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc4
From 8cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc4 to 9999999999999999999999999999999999999999999999999999999999999990
From 9999999999999999999999999999999999999999999999999999999999999990 to a66666666666666666666666666666666666666666666666666666666666665c
From a66666666666666666666666666666666666666666666666666666666666665c to b333333333333333333333333333333333333333333333333333333333333328
From b333333333333333333333333333333333333333333333333333333333333328 to bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4
From bffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4 to ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc0
From ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc0 to d99999999999999999999999999999999999999999999999999999999999998c
From d99999999999999999999999999999999999999999999999999999999999998c to e666666666666666666666666666666666666666666666666666666666666658
From e666666666666666666666666666666666666666666666666666666666666658 to f333333333333333333333333333333333333333333333333333333333333324
From f333333333333333333333333333333333333333333333333333333333333324 to ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff

Entonces buscamos en el archivo los valores que entren en alguno de los rango anteriores, se ordenan en RAM y se escriben en un archivo aparte. Una vez completado el proceso para todos los sub-rangos se unen los archivos en uno solo y se borra el archivo desordenado.

Esto se puede hacer así debido a que la distribución de los registros es uniforme en el rango original de A a B, en caso de que la data este sesgada y existan mas valores en un sub-rango dado es conveniente poner un limite de cantidad de registros leídos para que el mismo no sobrepase la cantidad de RAM.

Saludos!
14  Foros Generales / Foro Libre / 15 Años en el foro, muchas gracias a todos :) en: 20 Noviembre 2020, 18:35 pm
Pues nada compañeros esta próxima semana cumplo 15 años registrado en el foro.

Yo se que tengo mas años viendo el foro, sin embargo hasta ese momento abrí mi cuenta.

Quiero agradecer a todos los miembros de este foro, a los que ya no están y a los que aun siguen. En este foro he aprendido mucho, de muchos temas distintos, aunque sea un poco de todo, estoy muy agradecido.

Desde ya muchas GRACIAS

Saludos!
15  Seguridad Informática / Criptografía / Implementacion practica Padding Oracle Attack en: 20 Noviembre 2020, 05:29 am
Recientemente me interesa ese tipo de temas otra vez, he aprendido mucho y me gustaría compartirlo con ustedes.

Si no saben de que va el tema aquí dejo unos links.

Block cipher mode of operation
https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation

Wikipedia Padding oracle attack
https://en.wikipedia.org/wiki/Padding_oracle_attack

Padding oracle attack
https://robertheaton.com/2013/07/29/padding-oracle-attack/

Este tipo de Ataque tiene ciertas condiciones iniciales para ser llevado acabo.

  • El cliente solo puede saber si su paquete fue aceptado o no.
Esto es debido al check que hace el servidor sobre el mensaje recibido

  • El servidor no Cambia de KEY utilizada durante el proceso de cifrado y descifrado.
Esto es debido a una mala implementación, ya que el servidor debería de renovar el KEY cada X tiempo y con cada cliente distinto.

  • El servidor tiene algún leak de información ya sea por error o mediante otro tipo de ataque.
  • El cliente solo podrá descifrar Una parte de la información, excepto por el Bloque inicial


Dejo a continuación una imagen de prueba y el código, proximamente subire un video hablando del tema.






Codigo, este codigo ejemplifica el cliente y servidor mediante un hilo distinto, lo hice de esta manera para no complicarme con el protocolo en RED de los mismo, se puede hacer sin hilos, y solo con llamadas a funcion, pero la idea es garantizar que el cliente no tiene acceso al servidor.



Código
  1. /*
  2. Desarollado por AlbertoBSD
  3. email alberto.bsd@gmail.com
  4. g++ -O3 -o opk_example opk_example.c -Wint-to-pointer-cast  -pthread
  5. */
  6.  
  7. #include <time.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include<pthread.h>
  12. #include<unistd.h>
  13. #include"ctaes/ctaes.c"
  14.  
  15. #define AES_BLOCKSIZE 16
  16.  
  17. struct timespec tim, tim2,sim,sim2;
  18.  
  19. void crear_server();
  20. char *tohex(char *ptr,int length);
  21. void *process_server(void *vargp);
  22.  
  23. int MyCBCEncrypt(AES256_ctx *ctx, const unsigned char iv[AES_BLOCKSIZE], const unsigned char* data, int size, bool pad, unsigned char* out);
  24. int MyCBCDecrypt(AES256_ctx *ctx, const unsigned char iv[AES_BLOCKSIZE], const unsigned char* data, int size, bool pad, unsigned char* out);
  25.  
  26. /* Values between Server and client */
  27. int values_do;
  28. int values_pad;
  29. int values_length;
  30. int values_leaked;
  31. char *values_enc;
  32. char *values_leak;
  33.  
  34. pthread_mutex_t mtx_values;  //Mutex for those values
  35.  
  36. int main(){
  37.  /*
  38.     Set global values;
  39.   */
  40.  tim.tv_sec = 0;
  41.  tim.tv_nsec = 50000;
  42.  
  43.  sim.tv_sec = 0;
  44.  sim.tv_nsec = 50000;
  45.  values_do = 0;
  46.  values_pad = 0;
  47.  values_length = 0;
  48.  values_leaked = 0;
  49.  values_enc = (char*) malloc(48);
  50.  values_leak = (char*) malloc(48);
  51.  crear_server();  //create child "server"
  52.  
  53.  //This main process is the client
  54.  int i,j,k,entrar;
  55.  char *secret,*temp,*try_enc;
  56.  char *decrypted;
  57.  unsigned char GUESS;
  58.  secret = (char*) malloc(48);
  59.  try_enc = (char*) malloc(48);
  60.  decrypted = (char*) malloc(16);
  61.  memset(decrypted,0,16);
  62.  do  {  
  63.    sleep(1);
  64.  }while(values_leaked==0); //We need to wait to the leaked data
  65.  
  66.  memcpy(secret,values_leak,48);
  67.  
  68.  temp = tohex(secret,48);
  69.  printf("process_client: leaked is %s\n",temp);
  70.  free(temp);
  71.  i = 0;
  72.  j = 0;
  73.  while(i < 16)  {
  74.    memcpy(try_enc,secret,32);
  75.  
  76.    pthread_mutex_lock(&mtx_values);
  77.    switch(values_do)  {
  78.      case 0:
  79.        GUESS = j;
  80.        decrypted[15-i] = GUESS;
  81.        for(k = 0; k <= i;k++)  {
  82.          try_enc[15-k] = try_enc[15-k] ^ decrypted[15-k] ^ (unsigned char)(i+1);
  83.        }
  84.  
  85.        values_do = 1;
  86.        values_length = 32;
  87.        memcpy(values_enc,try_enc,32);
  88.      break;
  89.      case 1:
  90.      break;
  91.      case 2:
  92.        if(values_pad)  {
  93.          i++;
  94.          printf("Encontrado valor: %c : %.2x\n",GUESS,GUESS);
  95.          j = 0;
  96.        }
  97.        else  {
  98.          j++;
  99.        }
  100.        values_do = 0;
  101.      break;
  102.    }
  103.    pthread_mutex_unlock(&mtx_values);
  104.    nanosleep(&tim , &tim2);
  105.  }
  106.  printf("Decrypted data: %s\n",decrypted);
  107.  
  108. }
  109.  
  110. void *process_server(void *vargp)  {
  111.  AES256_ctx ctx;
  112.  FILE *urandom;
  113.  const char *secret = "The password is: Ywgo/@g:2$0Qsz<";
  114.  char *key,*dec,*enc,*iv,*temp;
  115.  int length,i,pad_valid,outlen;
  116.  unsigned char pad;
  117.  key = (char*) malloc(32);
  118.  dec = (char*) malloc(48);
  119.  enc = (char*) malloc(48);
  120.  iv  = (char*) malloc(16);
  121.  urandom = fopen("/dev/urandom","rb");
  122.  fread(key,1,32,urandom);
  123.  fread(iv,1,16,urandom);
  124.  fclose(urandom);
  125.  
  126.  AES256_init(&ctx,(const unsigned char*) key);
  127.  
  128.  /* LEAK THE secret */
  129.  pthread_mutex_lock(&mtx_values);
  130.  memset(enc,0,48);
  131.  
  132.  
  133.  outlen = MyCBCEncrypt(&ctx, (const unsigned char*) iv, (const unsigned char*) secret, strlen(secret), true, (unsigned char*) enc);
  134.  
  135.  memcpy(values_leak,enc,outlen);
  136.  values_leaked = 1;
  137.  pthread_mutex_unlock(&mtx_values);
  138.  /*END LEAK*/
  139.  
  140.  do  {
  141.    nanosleep(&sim , &sim2);
  142.    pthread_mutex_lock(&mtx_values);
  143.    if(values_do == 1)  {
  144.      length = values_length;
  145.      pad_valid = 0;
  146.      if(length <= 48)  {
  147.        memcpy(enc,values_enc,length);
  148.  
  149.        outlen = MyCBCDecrypt(&ctx,( const unsigned char*) iv, (const unsigned char*) enc, length, true, (unsigned char*) dec);
  150.        if(outlen > 0)  {
  151.          pad_valid =  1;
  152.          printf("Decrypted data seems legit : %i bytes\n",outlen);
  153.          temp = tohex(dec,length);
  154.          printf("Decrypted data %s\n",temp);
  155.          free(temp);
  156.        }
  157.        else  {
  158.          printf("Decrypted data doesnt seems legit\n",outlen);
  159.          temp = tohex(dec,length);
  160.          printf("Decrypted data %s\n",temp);
  161.          free(temp);
  162.        }
  163.      }
  164.      values_do = 2;
  165.      values_pad = pad_valid;
  166.    }
  167.    pthread_mutex_unlock(&mtx_values);
  168.  }while(1);
  169.  pthread_exit(NULL);
  170. }
  171.  
  172. void crear_server()  {
  173.  int s;
  174.  pthread_t tid;
  175.  pthread_attr_t attr;
  176.  s = pthread_attr_init(&attr);
  177.  if (s != 0)  {
  178.    perror("pthread_attr_init");
  179.    exit(6);
  180.  }
  181.  s = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
  182.  if(s != 0)  {
  183.    perror("pthread_attr_setstacksize");
  184.    exit(8);
  185.  }
  186.  s = pthread_create(&tid,&attr,process_server,NULL);
  187.  if(s != 0)  {
  188.    perror("pthread_create");
  189.  }
  190.  pthread_attr_destroy(&attr);
  191. }
  192.  
  193. char *tohex(char *ptr,int length){
  194.  char *buffer;
  195.  int offset = 0;
  196.  unsigned char c;
  197.  buffer = (char *) malloc((length * 2)+1);
  198.  for (int i = 0; i <length; i++) {
  199.  c = ptr[i];
  200.  sprintf((char*) (buffer + offset),"%.2x",c);
  201.  offset+=2;
  202.  }
  203.  buffer[length*2] = 0;
  204.  return buffer;
  205. }
  206.  
  207.  
  208. int MyCBCDecrypt(AES256_ctx *ctx, const unsigned char iv[AES_BLOCKSIZE], const unsigned char* data, int size, bool pad, unsigned char* out)
  209. {
  210.  int written = 0;
  211.  bool fail = false;
  212.  const unsigned char* prev = iv;
  213.  if (!data || !size || !out)
  214.    return 0;
  215.  if (size % AES_BLOCKSIZE != 0)
  216.    return 0;
  217.  while (written != size) {
  218.    AES256_decrypt(ctx, 1, out, data + written);
  219.    for (int i = 0; i != AES_BLOCKSIZE; i++)
  220.      *out++ ^= prev[i];
  221.    prev = data + written;
  222.    written += AES_BLOCKSIZE;
  223.  }
  224.  if (pad) {
  225.    unsigned char padsize = *--out;
  226.    fail = !padsize | (padsize > AES_BLOCKSIZE);
  227.    padsize *= !fail;
  228.    for (int i = AES_BLOCKSIZE; i != 0; i--)
  229.      fail |= ((i > AES_BLOCKSIZE - padsize) & (*out-- != padsize));
  230.    written -= padsize;
  231.  }
  232.  return written * !fail;
  233. }
  234.  
  235. int MyCBCEncrypt(AES256_ctx *ctx, const unsigned char iv[AES_BLOCKSIZE], const unsigned char* data, int size, bool pad, unsigned char* out)
  236. {
  237.  int written = 0;
  238.  int padsize = size % AES_BLOCKSIZE;
  239.  unsigned char mixed[AES_BLOCKSIZE];
  240.  
  241.  if (!data || !size || !out)
  242.    return 0;
  243.  
  244.  if (!pad && padsize != 0)
  245.    return 0;
  246.  
  247.  memcpy(mixed, iv, AES_BLOCKSIZE);
  248.  
  249.  // Write all but the last block
  250.  while (written + AES_BLOCKSIZE <= size) {
  251.    for (int i = 0; i != AES_BLOCKSIZE; i++)
  252.      mixed[i] ^= *data++;
  253.    AES256_encrypt(ctx, 1, out + written, mixed);
  254.    memcpy(mixed, out + written, AES_BLOCKSIZE);
  255.    written += AES_BLOCKSIZE;
  256.  }
  257.  if (pad) {
  258.    // For all that remains, pad each byte with the value of the remaining
  259.    // space. If there is none, pad by a full block.
  260.    for (int i = 0; i != padsize; i++)
  261.      mixed[i] ^= *data++;
  262.    for (int i = padsize; i != AES_BLOCKSIZE; i++)
  263.      mixed[i] ^= AES_BLOCKSIZE - padsize;
  264.    AES256_encrypt(ctx, 1, out + written, mixed);
  265.    written += AES_BLOCKSIZE;
  266.  }
  267.  return written;
  268. }
  269.  


Saludos!
16  Foros Generales / Criptomonedas / Como proteger una cartera Bitcoin en: 18 Noviembre 2020, 01:45 am
Como proteger una cartera Bitcoin

No sabemos qué pasará en el futuro, es decir no sabemos si nos robaran la cartera o la perderemos en algún USB y alguien la encontrara. Tampoco sabemos la cantidad de poder de computo que existira.

Pero además de tener cifrada nuestra cartera con un buen passphrase de más de 40 caracteres, se puede lograr una mejor seguridad, para en el caso de que sea robada sea inviable que por medio de fuerza bruta directo contra el passphrase.

Nuestra Cartera está protegida con el resultado de un hash sha512 derivado N veces a partir de nuestro Passphrase y un salt.

Es decir:

Código:
(key,IV) = PBKDF2_algo("sha512",passphrase+salt,N);

Normalmente el cliente bitcoin-core calcula ese N de tal forma que la Operación en total no lleve más de 1 Segundo

¿Por que? ¿Por que ponérsela fácil a los crackers de wallets?

Se puede editar el código fuente del bitcoin-core de tal forma que cuando nosotros cambiemos el passphrase este utilice un número N tal que N el proceso completo de PBKDF2_algo lleve al menos uno o dos minutos por passphare, es un pequeño precio de espera. Y el resultado será sumamente desalentador para quien se robe o encuentre la cartera.

¿Como hacer esta modificacion?

Si revisamos la versión estable y actual al dia de hoy, el bitcoin core 0.20 el archivo wallet.cpp tiene la solución:

https://github.com/bitcoin/bitcoin/blob/0.20/src/wallet/wallet.cpp En la linea 322 tenemos lo siguiente:

Código
  1. bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
  2. {
  3.    bool fWasLocked = IsLocked();
  4.  
  5.    {
  6.        LOCK(cs_wallet);
  7.        Lock();
  8.  
  9.        CCrypter crypter;
  10.        CKeyingMaterial _vMasterKey;
  11.        for (MasterKeyMap::value_type& pMasterKey : mapMasterKeys)
  12.        {
  13.            if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
  14.                return false;
  15.            if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
  16.                return false;
  17.            if (Unlock(_vMasterKey))
  18.            {
  19.                int64_t nStartTime = GetTimeMillis();
  20.                crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
  21.                pMasterKey.second.nDeriveIterations = static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime))));
  22.  
  23.                nStartTime = GetTimeMillis();
  24.                crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
  25.                pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + static_cast<unsigned int>(pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime)))) / 2;
  26.  
  27.                if (pMasterKey.second.nDeriveIterations < 25000)
  28.                    pMasterKey.second.nDeriveIterations = 25000;
  29.  
  30.                WalletLogPrintf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
  31.  
  32.                if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
  33.                    return false;
  34.                if (!crypter.Encrypt(_vMasterKey, pMasterKey.second.vchCryptedKey))
  35.                    return false;
  36.                WalletBatch(*database).WriteMasterKey(pMasterKey.first, pMasterKey.second);
  37.                if (fWasLocked)
  38.                    Lock();
  39.                return true;
  40.            }
  41.        }
  42.    }
  43.  
  44.    return false;
  45. }

Y solo tendria que quedar de la siguiente manera:

Código
  1. bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
  2. {
  3.    bool fWasLocked = IsLocked();
  4.  
  5.    {
  6.        LOCK(cs_wallet);
  7.        Lock();
  8.  
  9.        CCrypter crypter;
  10.        CKeyingMaterial _vMasterKey;
  11.        for (MasterKeyMap::value_type& pMasterKey : mapMasterKeys)
  12.        {
  13.            if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
  14.                return false;
  15.            if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, _vMasterKey))
  16.                return false;
  17.            if (Unlock(_vMasterKey))
  18.            {
  19.                pMasterKey.second.nDeriveIterations = 133707331;
  20.  
  21.                WalletLogPrintf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
  22.  
  23.                if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
  24.                    return false;
  25.                if (!crypter.Encrypt(_vMasterKey, pMasterKey.second.vchCryptedKey))
  26.                    return false;
  27.                WalletBatch(*database).WriteMasterKey(pMasterKey.first, pMasterKey.second);
  28.                if (fWasLocked)
  29.                    Lock();
  30.                return true;
  31.            }
  32.        }
  33.    }
  34.  
  35.    return false;
  36. }

Si quitamos todo lo relacionado con el calculo del tiempo y agregamos la linea:

Código
  1. pMasterKey.second.nDeriveIterations = 133707331;

En mi caso con el bitcoin-core oficial recompilado y con un procesador Intel Xeon CPU E3-1271 v3 @ 3.60GHz cambiar el passphrase toma alrededor de un minuto

Saludos!

17  Seguridad Informática / Criptografía / Como crackear una cartera bitcoin. Teoria y practica en: 4 Noviembre 2020, 19:42 pm

Como crackear una cartera bitcoin. (Teoria y practica).

Bueno esta investigación comenzó a manera de broma y solo por hobby. En las platicas que tenemos en la comunidad de elhacker.net en Telegram ( https://t.me/elhackerdotnet )

Se menciono hace tiempo la existencia de una  cartera de bitcoin con 69 Mil BTC, al tipo de cambio actual hoy 4 de Noviembre de 2020 serian unos 995 millones de dólares, entre bromas se menciono que teníamos que crackearla con algún computador cuántico.

En fin, el proceso "normal" para abrir una cartera cifrada utilizando las aplicaciones oficiales de Bitcoin-Core es el siguiente.

Primero cargamos la cartera

Código:
bitcoin-cli loalwallet "wallet.dat"

"wallet.dat" es un archivo que debe de existir en el directorio ~/.bitcoin/wallets/

Se puede llamar de otro modo, el punto es que debe de exisitir en ese path

Segundo desbloqueamos la cartera con nuestra passphrase o mas comúnmente contraseña

Código:
bitcoin-cli walletpassphrase "passphrase o password" 60

Entre comillas tenemos nuestro password y el 60 a continuación indica que desbloqueamos la cartera por 60segundos

Si el password es correcto no marcara error, de lo contrario lo indicará.

Código:
error code: -14
error message:
Error: The wallet passphrase entered was incorrect.

Ahora la forma lenta e ineficiente de intentar crackearla por fuerza fruta probando directamente distintos passphrase desde la misma terminal.
Sigue siendo lento incluso aunque se utilice algún script bash por que pasar del bash al programa y de regreso es ineficiente.

Necesitamos saber que hace internamente la aplicación, para tratar de reproducirlo en un programa en C y ejecutarlo por aparte posiblemente con multihilo para mejorar la eficiencia

¿Que hace el bitcoin core con nuestro passphrase?

Nuestro passphrase es combinado con un salt que se encuentra almacenado en el archivo, mediante un algoritmo estilo PBKDF y con mas de 25000 iteraciones generan un hash sha512.

De estos 64 bytes generados mediante PBKDF, se utilizan los primeros 32 bytes como KEY para inicializar el contexto de AES y los siguientes 16 bytes como IV para el algoritmo CBC

A este algoritmo AES256CBC se le pasa como parámetro para descifrar el mKey (master KEY) cifrado y se obtiene un mKey Descifrado

El master key ya descifrado se le hacen varias pruebas, se utiliza este valor como KEY para otros descifrados y en este caso como IV en todas las pruebas se utilizan 16 bytes del public Key de la cartera bitcoin obtenidos por una función interna llamada GetHash que desconozco que valores devuelva exactamente, solamente me limite a llamarla.

Y si el master key ya descifrado pasa todas las pruebas se almacena en memoria para sea utilizado en el futuro.

Fin de la triste Historia.  :silbar:

Resumen en pseudo codigo

El siguiente codigo en Pseudo C esta solo para representare que hace la aplicación internamente.

Código
  1. prekey = PBKDF(passphrase,IV, N Iteraciones,"sha512");
  2. memcpy(KEY,prekey,32);
  3. memcpy(IV,prekey+32,16);
  4. aesctx = AES256_init(KEY);
  5. if( AES256CBC_decrypt(aesctx,IV,ENC_mKey,DEC_mKEY) > 0) {
  6. foreach(OthersENC as oENC) {
  7. oCtx = AES256_init(DEC_mKEY);
  8. if(!AES256CBC_decrypt(oCtx,IV_fromPublickey,oENC,dummy) > 0) {
  9. return false;
  10. }
  11. }
  12. return true;
  13. }

Entonces si nuestro plan es un ataque por fuerza bruta podemos saltarnos el PBKDF que se ejecuta N Iteraciones (Mínimo 25000) y saltar directamente al Decrypt de AES.

Tenemos 2 opciones:

1.- Generar un par (KEY,IV) 48 bytes random o secuencial y empezar con el primer AES256CBC_decrypt y utilizar el valor generado para continuar con los AES256CBC_decrypt dentro del for.

2.- O generar solamente un KEY de 32 bytes random o secuencial y pasar directamente a los AES256CBC_decrypt dentro del For.

Asi con 32 bytes solo tenemos 1 de 115792089237316195423570985008687907853269984665640564039457584007913129639936 posibilidades de dar con la KEY correcto.
xD xD xD

Resultados vistos en la práctica.

Con la opción 1 solamente el 0.4% de los valores aleatorios generados pasaban el primer AES256CBC_decrypt posteriormente solo el 0.4% de esos valores pasaban el primer AES256CBC_decrypt dentro del FOR

Para la cartera que cree con el propósito de realizar las pruebas los challenge dentro del FOR eran sobre 500.

Sin embargo para la cartera lackeada con 69K BTC solo está disponible un solo challenge dentro del FOR, al ser solo dos AES256CBC_decrypt me dio bastantes KEY "Falsos positivos" aproximadamente uno de cada millón de valores random generados (KEY,IV) pasaban ambas pruebas

En conclusión

La aproximación por Fuerza Bruta a AES256CBC es improbable que funcione ojo, improbable no imposible, Tal vez en el futuro con mejor poder de computo disponible, o tal vez con Múltiples equipos trabajando de forma sincronizada con alguna RED tipo BOINC o algún tipo de BOTNET

Tengo el código utilizado para realizar este proceso, un poco de manera hardcodeada Ya que los Valores cifrados los saque directamente mediante Hexedit, si alguien esta interesado en la estructura del archivo no dude en comentarlo.

Saludos

Posdata
La cartera de 69K BTC fue vaciada por alguien el dia de ayer. 3 de Noviembre a las 3PM
https://twitter.com/albertobsd/status/1323752623510446080
https://decrypt.co/es/47133/wallet-de-bitcoin-con-955-millones-famosa-entre-hackers-se-acaba-de-vaciar?amp=1
18  Seguridad Informática / Criptografía / El patron de padding en la data descifrada es normal? en: 4 Noviembre 2020, 03:14 am
Anteriormente no me había fijado la salida del descifrado por AES 256 CBC con Pad habilitado.

Normalmente uno solo espera la data original descifrada, vamos que si ciframos la palabra "hola" esperamos de vuelta la misma palabra "hola" ya descifrada.

Cuando encriptas sin padding cada bloque del tamaño  "AES_BLOCKSIZE" devuelve la misma cantidad de bloques. Pero el cifrar con Padding agrega cierta cantidad mas de datos.

Por ejemplo si ciframos 32 bytes con AES256CBC con Padding nos devuelve un buffer con 48 bytes de data

Y cuando desciframos esos 48 bytes, nos devuelve la data original de 32 bytes + un buffer "sucio" es decir que hay mas datos en el buffer, en mi caso he comprobado que para este ejemplo siempre devuelve un buffer sucio de 16 bytes y cada uno de esos bytes tiene valor de uno.

Mi pregunta es ¿Es normal esto, o solo es la forma en la que trabaja la librería ctaes?

hice un programa que muestra que independientemente del key y del IV utilizados  siempre pasa lo mismo

Código:
albertobsd $ ./test_aes256cbc
key: fd792d4458dbc9bfee589482273ae061a37e24a72e95a0a5fba17109e4cb1daf
iv: 7d5559d5e50e340bb66618ceaad7ed1b
Data: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
len 48
cipher data 1117fcb2cbb27ee2f735ce4083d0aea743b51f6b7f61f59ce5a27a78bb5d454eab8b6a1733a5ad1d07b0b08ba1732e04
len 32
decipher data 414141414141414141414141414141414141414141414141414141414141414110101010101010101010101010101010
albertobsd $ ./test_aes256cbc
key: 1049354727fa2affd4410da40870f1757e211efeb96349b8576157c101fe5ab0
iv: 49547b6aac189b8487f60157d13185df
Data: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
len 48
cipher data e980ef82804a6fe5bec15dda0ad50064457c65259cd810055c38eb7c55e1d40071646c7c792e6d5a7ac6597057868267
len 32
decipher data 414141414141414141414141414141414141414141414141414141414141414110101010101010101010101010101010
albertobsd $ ./test_aes256cbc
key: 6d40ce0be48da5fcc7ede6531dae1b3613e5931a808e1ae99928ab74f74f3685
iv: ec1cebfa7894563a8329aa797610841c
Data: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
len 48
cipher data 395976ca9f00ace59ba64e8a1ee5dbaf55f45e786fada6520148d82a84c298e15b2854763a2fc82e7a62164936bf8f1f
len 32
decipher data 414141414141414141414141414141414141414141414141414141414141414110101010101010101010101010101010



De ser normal esto se podría tomar ese buffer sucio como una comprobación de que la key y el iv utilizados son los correctos?


Saludos
19  Seguridad Informática / Seguridad / Extraer MasterKey de cartera Bitcoin en: 29 Octubre 2020, 16:35 pm
Publico este tema aquí, ya que no se en qué sección queda mejor publicarlo.

Estoy intentando extraer la información Cifrada de una cartera bitcoin, en específico la información del Key para posteriormente intentar descifrarlo por algún ataque de fuerza bruta.

Quiero extraerla por que no quiero depender del bitcoin core ya que si se realiza el ataque por fuerza bruta mediante algún script bash o algun otro metodo NO compilado, el ataque puede ser realmente ineficiente.

También quiero brincarme algunos pasos innecesarios de funciones tipo rehash o PBKDF2 (key derivation) ya que aunque no consumen mucho CPU si quitan algunos miles de ciclos de procesamiento que a la larga pueden hacer aun mas eterno el proceso de crackeo.

Segun he leido la informacion del Key cifrado el salt y el numero de iteraciones esta contenida en un campo de 64 bytes del wallet.dat llamado mkey.

Segun vi en el siguiente Link:

Código:
https://bitcoin.stackexchange.com/questions/48070/format-of-mkey-field-in-encrypted-wallet-dat-file

La data contiene los siguientes campos:

mkey, nID, encrypted_key, salt, derivation_method, derivation_rounds, other_derivation_parameters

Citar
  • mkey - a size prefixed string denoting the start of the master key data.
  • nID - an integer whose purpose I have been unable to determine.
  • encrypted_key - a size prefixed buffer containing the encrypted master key.
  • salt - a size prefixed buffer containing the salt data used when encrypting the key.
  • derivation_method - an integer containing either 0 or 1 for the method used to encrypt the master key using the wallet password.
  • derivation_rounds – an integer containing the number of rounds used to encrypt the master key.
  • other_derivation_parameters
mkey es solo el ascii "mkey", se que el encrypted_key debe de ser de 32 bytes y el salt de 16, restando solo 12 bytes para los otros datos, sin embargo no estoy seguro del orden de los mismos.

Si vemos la siguiente imagen:





Vemos que ahí esta la data, escribí un pequeño programa que la encuentra y la extrae, pero no se en que orden este, con ver los datos de esta cartera y otras me doy cuenta de algunos datos que pueden ser números como los primeros 8 bytes después del mkey, pueden ser números, al igual que los últimos 4 antes de ckey.


Edit

Solucionado el master key cifrado son 48 bytes que se encuentran a un offset de -72 bytes de la primera coincidencia del string mkey.

Para esta cartera en cuestión el Master Key Cifrado es:

CEC646179A7F947349A0AA99EC7122B01F72BF18FFA4FDC760635D8C13109DA196D3DC802D5AABB23FA6C6AABA9A1DBB

Saludos

20  Seguridad Informática / Criptografía / Funcion BytesToKeySHA512AES en el bitcoin en: 29 Octubre 2020, 15:26 pm
Recientemente publique el tema:Como determina la función AES256CBCDecrypt una correcta desencriptación El cual esta relacionado con este de forma algo indirecta.

Todo esto viene del análisis que estoy realizando al código fuente del Bitcoin Core.

Hoy hablaré sobre la función BytesToKeySHA512AES la cual es una de las primeras que se utilizan cuando intentas desbloquear una cartera bitcoin protegida con un passphrase.

BytesToKeySHA512AES básicamente toma las passphrase ingresada + un salt proporcionado por el mismo archivo wallet.dat y los transforma en un (key, iv) para posteriormente utilizarlos como material para descifrar la llave cifrada.

El código fuente de BytesToKeySHA512AES, lo pueden encontrar en

Código:
https://github.com/bitcoin/bitcoin/blob/master/src/wallet/crypter.cpp
 

Tiene 3 parámetros de entrada y 2 de salida
Entrada:
Salt
Passphrase
Count

Salida:
Key
IV

La parte interesante del código es la siguiente:

Código
  1.    for(int i = 0; i != count - 1; i++)
  2.        di.Reset().Write(buf, sizeof(buf)).Finalize(buf);

Básicamente obtiene el hash sha512 de si mismo (count -1) veces ya la que primera vez fue el hash sha512 de (passphrase + IV) como muestra el siguiente código:

Código
  1.    di.Write((const unsigned char*)strKeyData.data(), strKeyData.size());
  2.    di.Write(chSalt.data(), chSalt.size());
  3.    di.Finalize(buf);

Posteriormente copia los primeros 32 bytes al Key y los siguientes 16 bytes al Vector IV

Si no están familiarizados con la sintaxis  del codigo anterior dejare un código en PHP ejemplificando lo que hace la función:

Código
  1. <?php
  2. $salt = "BBBBBBBBBBBBBBBB";
  3. $passphrase = "AAAAA";
  4. $key_ ="";
  5. $iv_ = "";
  6. BytesToKeySHA512AES($salt ,$passphrase,2,$key_, $iv_ );
  7.  
  8. echo "Key:\n";
  9. var_dump($key_);
  10. echo "IV:\n";
  11. var_dump($iv_);
  12.  
  13. function BytesToKeySHA512AES($chSalt,$strKeyData,$count,&$key,&$iv) {
  14. $ctx = hash_init('sha512');
  15. hash_update($ctx,$strKeyData);
  16. hash_update($ctx,$chSalt);
  17. $buf = hash_final($ctx,true);
  18. $i = 0;
  19. while($i != $count -1) {
  20.  
  21. /* //Estas tres líneas básicamente se transforman en una simple llamada a hash
  22. $ctx = hash_init('sha512');
  23. hash_update($ctx,$buf);
  24. $buf = hash_final($ctx,true);
  25. */
  26. $buf = hash('sha512',$buf,true);
  27. $i++;
  28. }
  29. echo "hash:\n";
  30. var_dump($buf);
  31. $key = mb_substr($buf,0,32);
  32. $iv = mb_substr($buf,32,16);
  33. }
  34. ?>

Lo escribí en PHP ya que es mas fácil darle seguimiento a las funciones hash, solo que no estoy 100% seguro de como manejar las copia de los bytes del hash resultante al key y al IV respectivamente.

Saludos
Páginas: 1 [2] 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ... 19
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines