# Recover MetaMask Seed Phrase Without Backup (Firefox Forensic Guide)
Advanced method using browser extension storage analysis and Snappy decompression
[Quick Solution] To recover MetaMask seed phrase from Firefox: 1. Extract vault data: `grep -oba "vault" ~/.mozilla/firefox/*default/storage/default/moz-extension*/idb/*.sqlite` 2. Decompress Snappy: `snappy-fox -d vault.snappy vault.txt` 3. Decrypt with password: `python3 metamask-vault-decryptor.py vault.txt your_password` ⚠️ Requires original Firefox profile and MetaMask password. Test on cloned system image.
## Prerequisites
- Firefox Profile: Original installation where MetaMask was active
- MetaMask Password: Essential for vault decryption
- Linux/MacOS: Guide optimized for Unix-like systems (WSL2 works for Windows)
- Tools Installed:
git clone https://github.com/mozilla/snappy-fox # Snappy decompressor
pip3 install pycryptodomex # For AES-GCM decryption
## Step-by-Step Recovery
### 1. Locate Firefox Profile Data
Terminal Command:
# Find active profile (look for 'default-release'):
ls -l ~/.mozilla/firefox/ | grep 'default.*'
Critical Path:
~/.mozilla/firefox/<profile>/storage/default/moz-extension+++<metamask-id>
### 2. Identify MetaMask Extension ID
Method:
# List all extensions matching MetaMask's pattern:
find ~/.mozilla/firefox/*default*/storage/default -name "moz-extension*" | grep -i "metamask"
Verification:
True MetaMask folders contain:
idb/*.sqlite
filesls -lh
shows ~2-50MB size (contains encrypted vault)
### 3. Extract Encrypted Vault
Hex Search:
# Search SQLite DB for vault marker (offset critical):
grep -Ubao "vault" *.sqlite | awk -F: '{print "Offset: " $2 " | File: " $1}'
Output Example:
Offset: 0x1A3F | File: 34234234DEBEFEEE.sqlite
Extraction Command:
dd if=34234234DEBEFEEE.sqlite of=vault.snappy bs=1 skip=$((0x1A3F)) count=1200
Adjust count based on vault size (typically 800-2000 bytes)
### 4. Handle Snappy Compression
Decompress:
cd snappy-fox && make
./snappy-fox -d ../vault.snappy ../vault.json
Validation:
file vault.json # Should show "JSON data" or "ASCII text"
### 5. Decrypt Seed Phrase
Python Script:
from Cryptodome.Cipher import AES import json, base64 def decrypt_vault(encrypted_data, password): salt = base64.b64decode(encrypted_data['salt']) iv = base64.b64decode(encrypted_data['iv']) ciphertext = base64.b64decode(encrypted_data['data']) # MetaMask's key derivation (PBKDF2-HMAC-SHA512, 10000 iterations) key = PBKDF2(password, salt, 64, 10000, hmac_hash_module=SHA512) cipher = AES.new(key[:32], AES.MODE_GCM, nonce=iv) return cipher.decrypt(ciphertext)
Run:
python3 decrypt_vault.py vault.json your_password
## Critical Errors & Fixes
Error | Cause | Solution |
---|---|---|
InvalidTag |
Wrong password | Verify password with echo -n "pass" | sha256sum against known hashes |
MalformedSnappy |
Partial extraction | Re-run dd with adjusted skip/count |
SQLite Corrupt |
Profile damage | Use sqlite3 .dump to extract raw data |
## Security Protocol
- Work on Cloned Disk:
dd if=/dev/sda of=~/metamask_recovery.img bs=4M # Create disk image
sudo mount -o ro,noload ~/metamask_recovery.img /mnt # Mount read-only - Memory-Only Processing:
mount -t tmpfs -o size=512M tmpfs /mnt/ramdisk
cp vault.snappy /mnt/ramdisk/ && cd /mnt/ramdisk - Post-Recovery Sanitization:
shred -u -z -n 7 vault.* # 7-pass overwrite
## FAQs
Q: Chrome/Edge recovery possible?
A: Yes – paths differ (~/.config/chromium/Default/Local Extension Settings/nkbihfbeogaeaoehlefnkodbefgpgknn
)
Q: No password but have profile?
A: Impossible – seed encrypted via AES-GCM with 10000 PBKDF2 iterations. Brute-force impractical.
Q: Verify decrypted seed validity?
# Derive address from seed:
pip install bip32utils
python3 -c "from bip32utils import BIP32Key; print(BIP32Key.fromEntropy(bytes.fromhex('SEED_HEX')).Address()"