openwall / john

John the Ripper jumbo - advanced offline password cracker, which supports hundreds of hash and cipher types, and runs on many operating systems, CPUs, GPUs, and even some FPGAs
https://www.openwall.com/john/
Other
10.27k stars 2.1k forks source link

blockchain2john.py: Add support for v4 #5078

Closed isieditors closed 1 year ago

isieditors commented 2 years ago

blockchain2john.py problem with blockchain wallet v4

today i tried to extract the hash of blockchain wallet v4 using blockchain2john. initially I couldn't extract the hash and gave this error My Wallet Version 2 or 3 seems to be used, adding --json option is required!

later I removed the following information from the beginning of data inside json file:

{"pbkdf2_iterations":5000,"version":4,"payload":"

and used --base64 command to get the hash

and it gave me a strange hash which is 17500 characters long. and hashcat recognized it as -m 12700 mode but couldn't crack it with a known password.

is this problem because of hashcat ? or due to strange hash or faulty hash from blockchain2john?? the hash starts with: $blockchain$v2$5000$8704$

solardiz commented 2 years ago

@isieditors Can that hash you obtained be cracked with john?

isieditors commented 2 years ago

john didn't crack it although the correct password was inserted in the password file I used the following command:

C:\john\run>john --wordlist=password.txt blockchaintestv4.txt

and got the following output

Warning: detected hash type "Blockchain", but the string is also recognized as "blockchain-opencl"
Use the "--format=blockchain-opencl" option to force loading these as that type instead
Using default input encoding: UTF-8
Loaded 1 password hash (Blockchain, My Wallet [PBKDF2-SHA1 AES 256/256 AVX2 8x])
Will run 8 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
Warning: Only 43 candidates left, minimum 64 needed for performance.
0g 0:00:00:00 DONE (2022-02-16 17:18) 0g/s 1433p/s 1433c/s 1433C/s dddf@@ee55
Session completed

another thing to add is that btcrecover cracks the hash obtained by:

extract-blockchain-main-data.py

and gives the following output:

Wallet difficulty: 5,000 PBKDF2-SHA1 iterations
2022-02-16 08:33:32 : Using 8 worker threads
Notice: Loading File:  .\passwords\password.txt
Notice: Finished File:  .\passwords\password.txt
| 36  elapsed: 0:00:01  rate:  28.28  P/s

Password found: 'gggg@@GGGG1'
solardiz commented 2 years ago

@isieditors Well, it looks like this is a new wallet type we need to add support for. Is this a dummy test wallet that you can share? If so, please do. Otherwise please create a dummy test one that you can share, and do that. Thank you!

isieditors commented 2 years ago

@solardiz thanks for support and help

here is the json content of blockchian wallet v4 which I borrowed from test wallets of btcrecover by @3rdIteration

{"pbkdf2_iterations":5000,"version":4,"payload":"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"}

blockchain2john only extract its hash when the following data is removed from the beginning and --base 64 is added to command {"pbkdf2_iterations":5000,"version":4,"payload"

the password for the test wallet is:

btcr-test-password

isieditors commented 2 years ago

@solardiz did you check this hash details

solardiz commented 2 years ago

@isieditors I did not - I just wanted to make sure we have complete info on this issue for someone else to handle it later.

isieditors commented 2 years ago

@solardiz is there possibly a way to get it added faster

solardiz commented 2 years ago

OK, I've tried this trivial patch:

+++ b/run/blockchain2john.py
@@ -42,7 +42,7 @@ if __name__ == '__main__':
                 # hack for version 2.0 and 3.0 wallets
                 try:
                     decoded_data = json.loads(data.decode("utf-8"))
-                    if "version" in decoded_data and (str(decoded_data["version"]) == "2" or str(decoded_data["version"]) == "3"):
+                    if "version" in decoded_data and (str(decoded_data["version"]) == "2" or str(decoded_data["version"]) == "3" or str(decoded_data["version"]) == "4"):
                         payload = base64.b64decode(decoded_data["payload"])
                         iterations = decoded_data["pbkdf2_iterations"]
                         print("%s:$blockchain$v2$%s$%s$%s" % (

Then ./blockchain2john.py --json: produces:

$blockchain$v2$5000$1664$a9c6b0abad640bf23f1f9fff52b5c5c1c3f53d491881ce4c5ec327dfb150fdb7543e7f8b6ba50019d84f69a6531fccddedadde8b0d4e211e34adec73a4ac09838acfaa509c42a68b13c87378e918ead9144af90acba2da03c4b691470851c268c7087d4d6813438ca0a4dbb91a11401e0975db5b1f150ae8e84351fac51c91f28909b8965029f68041aefb17f9aa2d916b7233d6bdd4c35521739fe3474b49ad3ecf6455e626aae0bb0b34bb2945bf62c81f09fae1a5500bc397bed45e46b3c57af5009ed35c7e56187d00ef69d8961f68f39d6a897b9341c0f009ee99d415f3145ac526baf8fe659622b8b1bd8fc5032e3e46f4a7c2fcde234b0856b21debe84586ab6fcdf6e2f6f4cce9c7792d3976fd6b1b2ae38dc005a1ab38fbe01c40293c6db84bb8ff0add0911f9d6368f7f20ebf085f51523941c3b478705f99050123d97a0cef9465fa178dc22899d0b66d814c48cdb090672235478fb50df5f23417062a850341b5c661469e5f5024e895c82ca727f01c6ded0e42904f46ff06870e859a3522f274eda42149c852dfa2f242d4447bfdb261407f13a4bf9c3f17425876c771e9c9d1232f92b4624b9ed5988d10a5ab2e8ded7d2dff6a57df5856eb32376d3f3f1fc1cc7dc9c30bf52ee76380da718141fcfec494eb84a74528ad915129a2571826eb2fb726be6708530666224c34dd1eeb781fbd02cb4cdaae6a9915dab551e0057329fd832c246da50bfb4d33f06bef8fb2b154b03cb20757ac6d9029f8a812354f9789d07f4a13a4fbc67072effb8bed577cf191753b88af95f8a31e1a63b7ae76f7374836be726b1dd9914b220c756466b77b3adca42babb540283365e0bbf33234a132239258caf7bb743757022f49a5f6e21b5bfb1d6307a6b2cc0de0effab3722112d99219b4c40dd47269e8f334b9859a20481fdfd40bd6855ee6440fa2724c735b3e22375a744bcdda82f24a08634cb98a5103ad75eabf35780542228920696481326af883b0e2258ab7e236b229c239910589a48922ed1900868642d8409e1615523622306f10883b535e59da5c3a6e8b4d4b49ea240d5adfa3f116ab44d710ce6dad075ff7fcbf2a4e70a10457d7f27c71c0aef4cbd3a129d4d93c8cb56228f0d7c09c0b3f6f2e75c0951c61fe6565bbc039da5e7f3a5c1512f9431ce7573c268e2c30272624f5764374a33aded9ff609a21a8288de2048293f9513743680febc691b7fac6b8126f1ab07605ae83fdf58c6bfaf7366e6948dfe95bd720ee3748c3f1e2f0d19debc519d4524683d2db4e4ac45525eec03cbc8d13051acdf54486f9d4ebe7fbeedb094485645067cd7a510756984d27998031ffeb1ed8ec87e7e73025d69c3b120d9f4f12e20a77866f38eeae4311879814e3ecf628d3ebcb3f6d6877dd215fff9d8099ec94e18c36057bb6f2ebfe5337cd3f9102d6ece1f38fd0cd2be1485ee2f7288a10fda53e40891c6065d5a6ee5e70d0b19c89a4608481f82291c2b43694029b9bf73e57117dcf0c93c75e5df71857c0c33687258ff9047da60f988c714649c77f4f923a601003dc2e77cd820879d4e739bc0765ca656d028fe69ef0807e55f45f6c36ad77e330509512ddc7f570357ac540d99c28c9ab8696f8e79e909a0c2da7ac658b7a21c3f04240dbf6385afb5bec4566f692c39f97b33fe993be8db50b90006c9487a4c6db9caf4136d5462dea3ba503fe2a2340170523368c75947c3e276c138e3ff4583a40532a6f09329e0482d88f8f57075f7a74cb2fd5c7a096d01c65231167191457e5087b3f08c32127254e31ab53201c445ea90c6578329bef3daea50274d188da0ec952f7a55b9dde1805f174deefdc376f982c32ea1155f4c3e70e1ca4a51e4df5f081e8268e19d0f5bc66d1c837ec06c8baf75ff118d203135c2cc155284b3cbee9124f6a3d99360223a683192aa5474afc3f7647b7863fe2756e3b8aaa1f74f2477138fbeaba95de66dcd0e2830828fb1446210fb5b87ffa8f38ece193705d70674104839f6376603ddc3d7ee88163fcdc32c08a628125b0324564ba92cf83538a52dc8de8130aa9ca55ab92d2e06dd1c93ecba70c27e1290cc65dbb24f3ff51e0ebd729b988c717e783cb0f9fd26f588c72de775d5c72ab6d870dec6fa61c8ca7d088acad12cf035ce0b09576eb45d31d905e15d9e58b09e55d8d5318a4adf6139f4d1591e571c81c83eaa0ae277f3125a4137c3ec4bcc3120d5a9810a24790a4b930a47170eb4ac6feae66c7e0c470f1a66a1cc9a99b3d784800c0b07c6cc10d7d486b267077f3a13f0b223fdfd4c64f841050ffbf075dade309850c35ca791436f734447

However, john does not crack the above with btcr-test-password in the wordlist. I don't know if that's actually the correct password - has it been verified with btcrecover?

solardiz commented 2 years ago

Maybe relevant, btcrecover/btcrpass.py has this comment:

    # A bit fragile because it assumes that some specific text is in the first encrypted block,
    # This was "guid" as of 6/2014 (since 12/2011)
    # As of May 2020, guid no longer appears in the first block, but 'tx_notes' appears there instead
    # Also check to see if the first block starts with 'address_book'
    # first as was apparently the case with some wallets created around Jan 2014
    # (see https://github.com/gurnec/btcrecover/issues/ that start with "double_encryption"
    # as per this issue here: https://github.com/3rdIteration/btcrecover/issues/96

Our blockchain_common_plug.c checks guid and address_book, but not tx_notes.

isieditors commented 2 years ago

thank you for considering this issue here is the result I got from btcrecover for this json file

Find me on Reddit @ https://www.reddit.com/user/Crypto-Guide

You may also consider donating to Gurnec, who created and maintained this tool until late 2017 @ 3Au8ZodNHPei7MQiSVAWb7NB2yqsb48GW4

Password found: 'btcr-test-password'

I also checked this hash with john and you were right, john didn't crack it

solardiz commented 2 years ago

OK, this makes it crack the password:

+++ b/src/blockchain_common_plug.c
@@ -111,6 +111,10 @@ int blockchain_decrypt(unsigned char *derived_key, unsigned char *data)
                return 0;
        }

+       if (memmem(out, 16, "\"tx_notes\"", 10)) {
+               return 0;
+       }
+
        // "guid" will be found in the first block
        if (memmem(out, 16, "\"guid\"", 6)) {
                AES_cbc_encrypt(data + 32, out + 16, SAFETY_FACTOR - 16, &akey, iv,
isieditors commented 2 years ago

should I add this to this file blockchain_common_plug.c ?? and which part should I paste it?

solardiz commented 2 years ago

@isieditors This is a patch that you can apply using the patch command, then rebuild from source. I guess this might be tricky for you, if you're not used to that. If so, please just wait until we merge the fix, and if you're using a binary build then until there's a new one. Might not be soon, though.

isieditors commented 2 years ago

Ok thank you I will try to explore more to see what I can do thank you for your help and time you devoted to this issue

TCRetriever commented 2 years ago

(Edited by @magnumripper: ML formatting)

Kindly use this file to extract Blockchain Wallet V4 Hash Command - python blockchain2john.py --json wallet.aes.json

Code --

#!/usr/bin/env python

import sys
import os.path
import base64
import binascii
import argparse
import json
import traceback

PY3 = sys.version_info[0] == 3

if __name__ == '__main__':

    parser = argparse.ArgumentParser(
        prog=sys.argv[0],
        usage="%(prog)s [blockchain wallet files]")

    parser.add_argument('--json', action='store_true', default=False,
                        dest='json', help='is the wallet using v2 format?')
    parser.add_argument('--base64', action='store_true', default=False,
                        dest='base64', help='does the wallet contain only a base64 string?')

    args, unknown = parser.parse_known_args()

    if len(sys.argv) < 2:
        parser.print_help()
        sys.exit(1)

    for filename in unknown:
        with open(filename, "rb") as f:
            data = f.read()
            # try to detect the wallet format version, https://blockchain.info/wallet/wallet-format
            if b"guid" in data and args.json:  # v1
                sys.stderr.write("My Wallet Version 1 seems to be used, remove --json option!\n")
                continue
            if b"pbkdf2_iterations" in data and not args.json:  # v2/v3
                sys.stderr.write("My Wallet Version 2 or 3 seems to be used, adding --json option is required!\n")
                continue

            if args.json:
                # hack for version 2.0 and 3.0 wallets
                try:
                    decoded_data = json.loads(data.decode("utf-8"))
                    if "version" in decoded_data and (str(decoded_data["version"]) == "2" or str(decoded_data["version"]) == "3" or str(decoded_data["version"]) == "4"):
                        payload = base64.b64decode(decoded_data["payload"])
                        iterations = decoded_data["pbkdf2_iterations"]
                        print("%s:$blockchain$v2$%s$%s$%s" % (
                            os.path.basename(filename), iterations, len(payload),
                            binascii.hexlify(payload).decode(("ascii"))))
                except:
                    traceback.print_exc()
                    pass

            if args.base64:
                # handle blockchain version 1 wallet format files which contain
                # only a base64 encoded string
                try:
                    if PY3:
                        ddata = base64.decodebytes(data)
                    else:
                        ddata = base64.decodestring(data)
                    print("%s:$blockchain$%s$%s" % (
                        os.path.basename(filename), len(ddata),
                        binascii.hexlify(ddata).decode("ascii")))
                except:
                    pass

            if not (args.json or args.base64):  # version 1 wallet format
                print("%s:$blockchain$%s$%s" % (
                    os.path.basename(filename), len(data),
                    binascii.hexlify(data).decode("ascii")))
TCRetriever commented 2 years ago

V4hash

Here is the proof that V4 hash is working and Cracked

claudioandre-br commented 2 years ago

Thank you @witee-star.

Please, create a PR to add V4 samples to https://github.com/openwall/john-samples repository.

Solar will commit these changes in the john's main repository sooner or later.

magnumripper commented 2 years ago

Here's @witee-star's version in diff format:

diff --git a/run/blockchain2john.py b/run/blockchain2john.py
index c8fae4500..60f91f469 100755
--- a/run/blockchain2john.py
+++ b/run/blockchain2john.py
@@ -42,7 +42,7 @@ if __name__ == '__main__':
                 # hack for version 2.0 and 3.0 wallets
                 try:
                     decoded_data = json.loads(data.decode("utf-8"))
-                    if "version" in decoded_data and (str(decoded_data["version"]) == "2" or str(decoded_data["version"]) == "3"):
+                    if "version" in decoded_data and (str(decoded_data["version"]) == "2" or str(decoded_data["version"]) == "3" or str(decoded_data["version"]) == "4"):
                         payload = base64.b64decode(decoded_data["payload"])
                         iterations = decoded_data["pbkdf2_iterations"]
                         print("%s:$blockchain$v2$%s$%s$%s" % (
claudioandre-br commented 2 years ago

Solar added something else at https://github.com/openwall/john/issues/5078#issuecomment-1047177149

magnumripper commented 1 year ago

So to recap: Are the two patches enough to close this issue?

OK, this makes it crack the password:

+++ b/src/blockchain_common_plug.c
@@ -111,6 +111,10 @@ int blockchain_decrypt(unsigned char *derived_key, unsigned char *data)
                return 0;
        }

+       if (memmem(out, 16, "\"tx_notes\"", 10)) {
+               return 0;
+       }
+
        // "guid" will be found in the first block
        if (memmem(out, 16, "\"guid\"", 6)) {
                AES_cbc_encrypt(data + 32, out + 16, SAFETY_FACTOR - 16, &akey, iv,

Here's @witee-star's version in diff format:

diff --git a/run/blockchain2john.py b/run/blockchain2john.py
index c8fae4500..60f91f469 100755
--- a/run/blockchain2john.py
+++ b/run/blockchain2john.py
@@ -42,7 +42,7 @@ if __name__ == '__main__':
                 # hack for version 2.0 and 3.0 wallets
                 try:
                     decoded_data = json.loads(data.decode("utf-8"))
-                    if "version" in decoded_data and (str(decoded_data["version"]) == "2" or str(decoded_data["version"]) == "3"):
+                    if "version" in decoded_data and (str(decoded_data["version"]) == "2" or str(decoded_data["version"]) == "3" or str(decoded_data["version"]) == "4"):
                         payload = base64.b64decode(decoded_data["payload"])
                         iterations = decoded_data["pbkdf2_iterations"]
                         print("%s:$blockchain$v2$%s$%s$%s" % (
TCRetriever commented 1 year ago

@magnumripper i think soo

solardiz commented 1 year ago

@magnumripper What you call "@witee-star's version in diff format" is actually identical to what I had posted in https://github.com/openwall/john/issues/5078#issuecomment-1047165841

Ideally, we'd make more extensive changes to the script as it's still wrong in other ways as well (I think will often erroneously detect v1 for newer wallets, and the whole idea of needing command-line options along with auto-detection is wrong), but adding a version 4 check works as a first commit prior to the redesign.

magnumripper commented 1 year ago

@magnumripper What you call "@witee-star's version in diff format" is actually identical to what I had posted

Missed that, my bad. So should I toss the two band-aid fixes together with a PR for now? It's that or nothing, for me. No knowledge, no samples, no time.

solardiz commented 1 year ago

should I toss the two band-aid fixes together with a PR for now?

Please feel free. We might make more elaborate changes later. Thanks!

claudioandre-br commented 1 year ago

The merged PR does not handle the sample file provided in #5225.

I don't know:

Is the json file like https://github.com/openwall/john/issues/5078#issuecomment-1042748773 or like https://github.com/openwall/john/issues/5225#issue-1534343378 ?

As magnum said, no samples no knowledge.

TCRetriever commented 1 year ago

Json file is like #5225