Last active
May 19, 2025 07:11
-
-
Save azazar/8a40efa63df1bd01f9c560d902aaa0b3 to your computer and use it in GitHub Desktop.
Scans directories for Bitcoin wallet.dat files with private keys and dumps all identified keys
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
import hashlib | |
import base58 # pip install base58 | |
import os | |
import sys | |
def hash256(data): | |
"""Perform SHA-256 hash twice.""" | |
return hashlib.sha256(hashlib.sha256(data).digest()).digest() | |
def to_wif(private_key_hex): | |
"""Convert the hex private key to WIF format.""" | |
# Add the version byte (0x80 for Bitcoin mainnet, 0xEF for testnet) | |
version_byte = b'\x80' | |
priv_key_bytes = bytes.fromhex(private_key_hex) | |
# Add version byte in front of the private key | |
versioned_private_key = version_byte + priv_key_bytes | |
# Add compression flag (optional, here it's considered) | |
versioned_private_key += b'\x01' | |
# Perform double SHA-256 hash on the versioned private key | |
checksum = hash256(versioned_private_key)[:4] | |
# Add the checksum at the end of the versioned private key | |
payload = versioned_private_key + checksum | |
# Convert to Base58 | |
wif = base58.b58encode(payload).decode('utf-8') | |
return wif | |
def salvage(priv_hex, filename): | |
wif_key = to_wif(priv_hex) | |
print(f"{wif_key} # {filename}") | |
# Save the WIF key to a file | |
filename_sanitized = re.sub(r'[^a-zA-Z0-9]', '_', filename) # Sanitize filename | |
filename_sanitized = filename_sanitized.strip('_')[:255] # Limit filename length to 255 characters | |
try: | |
os.makedirs("salvaged_keys", exist_ok=True) # Create directory if it doesn't exist | |
with open(f"salvaged_keys/{filename_sanitized}.txt", "a") as f: | |
f.write(f"# {filename}\n{wif_key}\n") | |
except OSError as e: | |
print(f"Error saving {filename}: {e}", file=sys.stderr) | |
# New helper to handle any single file | |
def process_file(path, salvaged_keys): | |
try: | |
with open(path, "rb") as f: | |
matches = re.findall(b'\x01\x01\x04\x20(.{32})', f.read()) | |
except OSError as e: | |
print(f"Error reading {path}: {e}", file=sys.stderr) | |
return | |
for priv in matches: | |
priv_hex = priv.hex() | |
if priv_hex not in salvaged_keys: | |
salvage(priv_hex, path) | |
salvaged_keys.add(priv_hex) | |
def scan_path(arg, salvaged_keys): | |
if os.path.isfile(arg): | |
process_file(arg, salvaged_keys) | |
elif os.path.isdir(arg): | |
for root, dirs, files in os.walk(arg): | |
for file in files: | |
if file.endswith(".dat"): | |
process_file(os.path.join(root, file), salvaged_keys) | |
if len(sys.argv) > 1: | |
salvaged_keys = set() # Set to store salvaged keys | |
for arg in sys.argv[1:]: | |
scan_path(arg, salvaged_keys) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment