Skip to content

How Android backup hashes are extracted

Inside the adb backup text header: how PBKDF2 salts, round counts, and a master-key blob become a crackable $ab$ hash.

Published on 4 min read

When a user runs adb backup with a password, Android serialises the device data into a .ab file in which the tar payload is AES-256-encrypted. The encryption parameters needed to attack that password live in a short, human-readable text header at the very start of the file — everything else is ciphertext. Hash Extractor reads that header in the browser, assembles a $ab$ hash, and hands it to hashcat or John the Ripper without the backup ever leaving your machine.

The .ab file layout

An Android backup file is not a binary container from the first byte. It starts with a sequence of newline-delimited text lines, then the encrypted tar payload begins immediately after. The text header has exactly nine lines in this order:

  1. The literal string ANDROID BACKUP — the magic that identifies the format.
  2. A version number (1 through 5 in practice).
  3. A compression flag (0 or 1).
  4. The encryption algorithm — AES-256 for an encrypted backup, none for an unencrypted one.
  5. The user-password PBKDF2 salt, hex-encoded.
  6. The master-key checksum salt, hex-encoded.
  7. The PBKDF2 round count (an integer, typically 10000).
  8. The user-key IV, hex-encoded.
  9. The master-key blob, hex-encoded.

Every binary value is transmitted as a lowercase hex string, so the header is entirely ASCII. The extractor reads at most the first 4096 bytes and processes only these nine lines; it never touches the encrypted payload.

Detection and validation

Detection is a single prefix check on the raw bytes:

ANDROID BACKUP

If the first 14 bytes do not match that string, the file is rejected immediately. After confirming the magic, the parser reads the encryption algorithm line. A value of none returns NotEncrypted — there is nothing to crack. Any algorithm other than AES-256 returns Unsupported. Only a file that passes both checks proceeds to hash assembly.

Key derivation model

Android uses PBKDF2-HMAC-SHA1 to derive a 256-bit user key from the backup password and the user salt. That user key is then used to AES-decrypt the master-key blob. The blob contains the actual AES master key used to encrypt the tar payload, a copy of that master key's IV, and a HMAC that allows verification. The checksum salt feeds a second PBKDF2 derivation used to verify the master key after unwrapping.

A password cracker does not need to decrypt the payload at all. It re-derives the user key for each candidate password, decrypts the master-key blob, and checks the embedded HMAC against the checksum salt. A match means the password is correct. All the material needed for that loop — both salts, the round count, the IV, and the blob — is in the text header.

The $ab$ hash format

The extractor assembles the hash as:

$ab$<version>*0*<rounds>*<user_salt>*<ck_salt>*<user_iv>*<master_key_blob>

The 0 in the second field is a fixed flag (reserved for future use in the format specification). All hex strings are lowercased before insertion. The field order matches what hashcat mode 18900 and John's AndroidBackup format expect.

A concrete example

The extractor's test suite exercises a version-5 backup with these header values:

Header lineValue
Version5
Compression1
AlgorithmAES-256
User saltaaaaaaaaaaaaaaaa (8 bytes, hex)
Checksum saltbbbbbbbbbbbbbbbb (8 bytes, hex)
PBKDF2 rounds10000
User IVcccccccccccccccccccccccccccccccc (16 bytes, hex)
Master-key blobdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd (52 bytes, hex)

The assembled hash is:

$ab$5*0*10000*aaaaaaaaaaaaaaaa*bbbbbbbbbbbbbbbb*cccccccccccccccccccccccccccccccc*dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd

This mirrors the output of androidbackup2john exactly — the extractor was written to produce the same token layout.

Cracking with hashcat and John the Ripper

hashcat

echo '$ab$5*0*10000*aaaaaaaaaaaaaaaa*bbbbbbbbbbbbbbbb*cccccccccccccccccccccccccccccccc*dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd' > hash.txt
hashcat -m 18900 hash.txt /usr/share/wordlists/rockyou.txt

Mode 18900 is Android Backup. hashcat handles the PBKDF2 derivation, AES unwrap, and HMAC verification on GPU.

John the Ripper

john --format=AndroidBackup hash.txt --wordlist=/usr/share/wordlists/rockyou.txt

Both tools accept the same $ab$ token — no conversion is needed between them.

Why client-side extraction matters

The .ab file can contain SMS history, app data, contacts, and credentials. Uploading it to a remote service to extract the hash would expose that data to a third party before you have even started cracking. Hash Extractor runs the Rust parser compiled to WebAssembly entirely in the browser. The file is read locally, the hash is assembled in memory, and only the short $ab$ string — containing no user data, only cryptographic parameters — is shown on screen. The backup payload is never transmitted anywhere.

This is the same principle behind the classic androidbackup2john script, which likewise extracts only the header fields. The WASM implementation brings the same workflow to any browser without requiring a Python or Perl runtime.

Related articles

Why 7z is the trickiest archive to crack: LZMA-compressed headers, AES coder property encoding, and the full $7z$ hash format explained.
A technical walkthrough of how Hash Extractor parses Ansible Vault files to produce a crackable $ansible$ hash for hashcat and John the Ripper.
A technical walkthrough of how Hash Extractor parses Ethereum keystore v3 JSON files to produce a crackable $ethereum$ hash for hashcat and John the Ripper.