howto: convert btcrecover bc: hashes to hashcat hash format
#1
Recently an user contacted me via forum PM on how to convert a "bc:" hash extracted by btcrecover from a bitcoin wallet (wallet.dat) to the format that hashcat supports:
Code:
-m 11300 = Bitcoin/Litecoin wallet.dat

(see https://github.com/3rdIteration/btcrecov...re-mkey.py)

the answer of course is that you need to understand each field and the format that btcrecover uses (it's some binary data concatenated together and base64 encoded).
The "bc:" at the start of the decoded string indicates that it's a hash of the bitcoin core wallet.

So the answer is to study and try to understand the extract script of btcrecover and construct a hashcat-compatibe script out of it.

You can use this conversion script to automatically convert them (it's a very simple script, not guaranteed to work in 100% of the cases, but it definitely worked for the user):
Code:
#!/usr/bin/env perl

# Author: philsmd
# Date: August 2020
# License: public domain, credits go to philsmd and hashcat

use strict;
use warnings;

use MIME::Base64 qw (decode_base64);

# Example:
# YmM6CcwT/6fzCWA95uNbWemYLaaJDCQbQ59hvgNpUlQLXu3DUa02UDvnzdsUAgC3gZPC:abc

if (scalar (@ARGV) != 1)
{
  print "USAGE: $0 <base64 string>\n";

  exit (1);
}

my $base64_string = $ARGV[0];

if (length ($base64_string) != 68)
{
  print "ERROR: The base64 string (hash, salt, iterations) was not specified correctly as the second command line argument\n";

  exit (1);
}

my $bin_string = decode_base64 ($base64_string);

if (length ($bin_string) != 3 + 32 + 8 + 4 + 4)
{
  print "ERROR: the base64 decoded string does NOT have a valid length\n";

  exit (1);
}

if (substr ($bin_string, 0, 3) ne "bc:")
{
  print "ERROR: signature of the decoded base64 string did not match 'bc:'\n";

  exit (1);
}

my $mkey  = substr ($bin_string,  3, 32);
my $salt  = substr ($bin_string, 35,  8);
my $iter  = substr ($bin_string, 43,  4);
my $crc32 = substr ($bin_string, 47,  4);

$iter = unpack ("L<", $iter);

print sprintf ("\$bitcoin\$%i\$%s\$%i\$%s\$%i\$%i\$%s\$%i\$%s\n",
  length ($mkey) * 2,
  unpack ("H*", $mkey),
  length ($salt) * 2,
  unpack ("H*", $salt),
  $iter,
  # fake data at the end:
  2,
  unpack ("H*", "\x00"),
  2,
  unpack ("H*", "\x00"),
);

exit (0);

The problem seemed to be that the user didn't have access to the original wallet.dat file (for instance a wallet recovery service etc could be in that situation, just an example, but again: it's still dangerous to share those hashes with untrusted parties).

So just to be very clear: if you have access to the wallet.dat file you shouldn't use this method but use bitcoin2john.py instead
Reply