Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions docs/Extract_Scripts.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,15 @@ Without access to the rest of your wallet file, it is impossible the decrypted p

## Usage for Blockchain.com ##

[Firstly you download the wallet file as per the documentation here:](./TUTORIAL.md#downloading-blockchaincom-wallet-files)
The first step is to download your Blockchain.com wallet backup file.

When prompted, enter your wallet ID and then approve the login request on the email account associated with the wallet. Once the login is approved, your wallet.aes.json file will be saved to you PC.
You can download it by navigating to the `extract-scripts` folder of this package and running:

python3 download-blockchain-wallet.py

When prompted, enter your wallet ID and then approve the login request on the email account associated with the wallet. Once the login is approved, your wallet.aes.json file will be saved to your PC.

Alternatively, you can [download the wallet file manually via browser Developer Tools.](./TUTORIAL.md#downloading-blockchaincom-wallet-files)

Next you'll need to open a Command Prompt window and type something like this :

Expand Down
15 changes: 13 additions & 2 deletions docs/TUTORIAL.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ As you can see, the Windows command prompt was incapable of rendering some of th
* Bitcoin Core - `%appdata%\Bitcoin` (it's named `wallet.dat`)
* Bitcoin Wallet for Android/BlackBerry, lost spending PINs - Please see the [Bitcoin Wallet for Android/BlackBerry Spending PINs](#bitcoin-wallet-for-androidblackberry-spending-pins) section below.
* Bither - `%appdata%\Bither` (it's named `address.db`)
* Blockchain.com - it's usually named `wallet.aes.json`; if you don't have a backup of your wallet file, you can download one by running the `download-blockchain-wallet.py` tool in the `extract-scripts` directory if you know your wallet ID (and 2FA if enabled)
* Blockchain.com - it's usually named `wallet.aes.json`; if you don't have a backup of your wallet file, you can download one by running the `download-blockchain-wallet.py` tool in the `extract-scripts` directory if you know your wallet ID (and 2FA if enabled). See [Downloading Blockchain.com wallet files](#downloading-blockchaincom-wallet-files) for details.
* Coinomi - Please see the [Finding Coinomi Wallet Files](#finding-coinomi-wallet-files) section below.
* Electrum - `%appdata%\Electrum\wallets`
* imToken - Please see the [Finding imToken Wallet Files](#finding-imtoken-wallet-files) section below.
Expand Down Expand Up @@ -285,7 +285,18 @@ How to get root access on your particular phone is beyond the scope of this docu
For iOS users, the file that you are looking for should have the same name and be in a similar location, but you will need a Jailbroken device to be able to access it.

### Downloading Blockchain.com wallet files ###
Downloading these kinds of wallet files id done via your browser, through the "Developer Tools" feature.

**Option 1: Using the download script (Recommended)**

You can download your wallet file by running the `download-blockchain-wallet.py` tool in the `extract-scripts` directory:

python3 download-blockchain-wallet.py

You will be prompted for your wallet ID, will need to confirm the request via email and enter any required 2FA code. Once the login is approved, your `wallet.aes.json` file will be saved to your PC.

**Option 2: Using browser Developer Tools**

Alternatively, you can download the wallet file manually via your browser, through the "Developer Tools" feature.

Basically you need to attempt to log in to your wallet (even with the wrong password) and save the wallet file that is downloaded as part of this process.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
**Note:** The YouTube video and examples were made before OpenCL acceleration was added to Blockchain.com wallets and can give at least a 10x performance improvement. (See [GPU Accleration](../../GPU_Acceleration.md) for more info)

## Overview
[Firstly you download the wallet file as per the process here:](../../TUTORIAL.md#downloading-blockchaincom-wallet-files)
You will first need to download the wallet file. You can either:

* **Use the download script:** Navigate to the `extract-scripts` folder and run `python3 download-blockchain-wallet.py`. You will be prompted for your wallet ID and will need to approve the login via email.
* **Use browser Developer Tools:** [Follow the manual download process here.](../../TUTORIAL.md#downloading-blockchaincom-wallet-files)

Once you have that file, there are three ways that blockchain.com wallets can be recovered.

Expand All @@ -31,9 +34,16 @@ Once you recover your seed phrase it will reveal your password, the password can

### Download the wallet file...

[Download the wallet file as per the process here:](../../TUTORIAL.md#downloading-blockchaincom-wallet-files)
Navigate to the BTCRecover folder and run:
**Command**

`python ./extract-scripts/download-blockchain-wallet.py`

You will then be prompted for your wallet ID, will need to confirm the request via email and enter any required 2fa code.

Alternatively, you can [download the wallet file using browser Developer Tools.](../../TUTORIAL.md#downloading-blockchaincom-wallet-files)

After doing the process above, we will save the wallet data in a file called wallet.aes.json (Which can just be left in your BTCRecover folder be used instead of the wallet file in any of the examples below)
This will then create a file wallet.aes.json (Which can just be left in your BTCRecover folder be used instead of the wallet file in any of the examples below)

### Create the TokenList File
**Example Tokenlist - tokenListTest.txt**
Expand Down
185 changes: 185 additions & 0 deletions extract-scripts/download-blockchain-wallet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
#!/usr/bin/env python

# download-blockchain-wallet.py -- Blockchain.com wallet file downloader
# Copyright (C) 2016, 2017 Christopher Gurnee
# Copyright (C) 2021-2026 Stephen Rothery
#
# This file is part of btcrecover.
#
# btcrecover is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version
# 2 of the License, or (at your option) any later version.
#
# btcrecover is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see http://www.gnu.org/licenses/

import sys, os.path, atexit, uuid, json, time

try:
import requests
except ImportError:
sys.exit("The 'requests' library is required. Install it with: pip3 install requests")

# The api_code (as of Feb 2 2017)
API_CODE = "1770d5d9-bcea-4d28-ad21-6cbd5be018a8"

prog = os.path.basename(sys.argv[0])

if len(sys.argv) > 1 and sys.argv[1] in ("-h", "--help"):
print("usage: {} [NEW_BLOCKCHAIN_WALLET_FILE]".format(prog))
print()
print("Downloads a Blockchain.com wallet file (wallet.aes.json).")
print("You will be prompted to enter your wallet ID and approve")
print("the login via email. If 2FA is enabled, you will also be")
print("prompted for the 2FA code.")
sys.exit(0)

if len(sys.argv) < 2:
atexit.register(lambda: input("\nPress Enter to exit ..."))
filename = "wallet.aes.json"
elif len(sys.argv) == 2 and not sys.argv[1].startswith("-"):
filename = sys.argv[1]
else:
print("usage:", prog, "[NEW_BLOCKCHAIN_WALLET_FILE]", file=sys.stderr)
sys.exit(2)

# Refuse to overwrite an existing file
if os.path.exists(filename):
print("Error: {} already exists, won't overwrite".format(filename), file=sys.stderr)
sys.exit(1)

print("Please enter your wallet's ID (e.g. 9bb4c672-563e-4806-9012-a3e8f86a0eca)")
wallet_id = str(uuid.UUID(input("> ").strip()))

# Base URLs to attempt (login.blockchain.com first, blockchain.info as fallback)
BASE_URLS = [
"https://login.blockchain.com/",
"https://blockchain.info/",
]

# Browser-like headers to avoid Cloudflare blocks
# Note: Update the Chrome version periodically to match current browser releases
HEADERS = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36",
"Accept": "application/json, text/plain, */*",
"Accept-Language": "en-US,en;q=0.9",
"Origin": "https://login.blockchain.com",
"Referer": "https://login.blockchain.com/",
}


def try_download_wallet(base_url, session, wallet_id):
"""Attempt to download the wallet from the given base URL.

Returns the wallet payload data on success, or raises on failure.
"""

auth_token = None

# Get an auth_token
resp = session.post(base_url + "sessions", data="api_code=" + API_CODE)
resp.raise_for_status()
auth_token = resp.json()["token"]
session.headers["Authorization"] = "Bearer " + auth_token

# Try to download the wallet
try:
resp = session.get(
base_url + "wallet/{}?format=json&api_code={}".format(wallet_id, API_CODE)
)
resp.raise_for_status()
wallet_data = resp.json().get("payload")
except requests.HTTPError as e:
error_msg = ""
try:
error_msg = e.response.json().get("initial_error", e.response.text)
except Exception:
error_msg = e.response.text if e.response is not None else str(e)

print(error_msg)

if "unknown wallet identifier" in str(error_msg).lower():
sys.exit(1)

# Wait for the user to complete the requested authorization (email)
time.sleep(5)
print("Waiting for authorization (press Ctrl-C to give up)...")
while True:
poll_resp = session.get(
base_url + "wallet/poll-for-session-guid?format=json&api_code=" + API_CODE
)
poll_data = poll_resp.json()
if "guid" in poll_data:
break
time.sleep(5)
print()

# Try again to download the wallet (this shouldn't fail)
resp = session.get(
base_url + "wallet/{}?format=json&api_code={}".format(wallet_id, API_CODE)
)
resp.raise_for_status()
wallet_data = resp.json().get("payload")

# If there was no payload data, then 2FA is enabled
while not wallet_data:
print("This wallet has two-factor authentication enabled, please enter your 2FA code")
two_factor = input("> ").strip()

try:
resp = session.post(
base_url + "wallet",
data="method=get-wallet&guid={}&payload={}&length={}&api_code={}".format(
wallet_id, two_factor, len(two_factor), API_CODE
),
)
resp.raise_for_status()
wallet_data = resp.text
except requests.HTTPError as e:
error_text = ""
try:
error_text = e.response.text
except Exception:
error_text = str(e)
print(error_text + "\n", file=sys.stderr)

return wallet_data if isinstance(wallet_data, bytes) else wallet_data.encode("utf-8")


# Try each base URL
session = requests.Session()
session.headers.update(HEADERS)

wallet_data = None

for i, base_url in enumerate(BASE_URLS):
try:
wallet_data = try_download_wallet(base_url, session, wallet_id)
break
except (requests.RequestException, KeyError, ValueError) as e:
if i < len(BASE_URLS) - 1:
print("Download from {} failed ({}), trying next...".format(
base_url.rstrip("/"), e
))
# Reset session for next attempt
session = requests.Session()
session.headers.update(HEADERS)
else:
print("Error: Failed to download wallet from all endpoints.", file=sys.stderr)
print("Last error: {}".format(e), file=sys.stderr)
print("\nYou can still download your wallet manually using the browser method.", file=sys.stderr)
print("See: https://btcrecover.readthedocs.io/en/latest/TUTORIAL/#downloading-blockchaincom-wallet-files", file=sys.stderr)
sys.exit(1)

# Save the wallet
with open(filename, "wb") as wallet_file:
wallet_file.write(wallet_data)

print("Wallet file saved as " + filename)