WhatsApp uses a customised version of XMPP (Extensible Messaging and Presence Protocol) as the communication protocol. Upon installation, it creates a user account using one’s phone number (with country code prefix) as the username (Jabber ID: [phone number]@s.whatsapp.net
). A password is generated using an unknown algorithm on the server end and sent to the client. Previously the password was derived from the phone’s IMEI or the WiFi MAC address.
On Android, WhatsApp stores both the username and password in 2 separate files kept in the private storage area. The me
file stores the username or Jabber ID and the pw
file stores the password.
1 2 |
/data/data/com.whatsapp/files/me /data/data/com.whatsapp/files/pw |
The files are stored in a Java serialized object format. The password field is also encrypted (as usual!).
Extract WhatsApp Password File
There are two ways to extract this file. The first method requires a rooted phone. Using ADB shell, switch to root and copy the file to the SD card.
1 2 3 4 5 |
$ adb shell android$ su android# cp /data/data/com.whatsapp/files/pw /sdcard android# exit android$ exit |
Once the file has been copied to the SD card, use ADB again to copy it to your computer.
1 |
$ adb pull /sdcard/pw |
The second method is to use the ADB backup feature. This is your only option if your phone is not rooted. For more detailed information on performing backups using ADB, read this article – Android ADB Backup, Extract, Restore.
1 |
$ adb backup -f com.whatsapp.ab -noapk com.whatsapp |
Convert the Android Backup file into a TAR archive.
1 |
$ dd if=com.whatsapp.ab ibs=24 skip=1 | openssl zlib -d > com.whatsapp.tar |
Next, extract the password file and move it to the current working directory.
1 2 |
$ tar xf com.whatsapp.tar apps/com.whatsapp/f/pw $ mv apps/com.whatsapp/f/pw . |
The password file is 69 bytes in size. I guess it should be the same size for everyone.
Extract Decryption Keys
We will need to extract 3 keys from the password file: salt
, IV
and the encrypted key. The salt
is a 4 byte number found within offset 0x1D and 0x20. Offsets start from 0x00. Extract the salt
using dd
command.
1 |
$ dd if=pw bs=1 skip=29 count=4 > pw_salt |
The above will give a 4-byte or 32 bit salt
value. For a hex dump of the value, use hexdump
.
1 |
$ hexdump -e '2/1 "%02x"' pw_salt |
The IV or the initialisation vector is a 16-byte or 128-bit value found within offset 0x21 and 0x30. Let’s extract the IV
with dd
command.
1 |
$ dd if=pw bs=1 skip=33 count=16 > pw_iv |
Finally, extract the encrypted key. It’s a 20-byte or 160-bit number. Offset is between 0x31 and 0x44 (or end of file).
1 |
$ dd if=pw bs=1 skip=49 count=20 > pw_ekey |
Now you will have 3 files containing each of the 3 keys: pw_salt
, pw_iv
and pw_ekey
.
Decrypt WhatsApp Password
Decryption is done in 2 steps. First, we need to use the PBKDF2
key derivation function. This function needs a pass phrase that is derived from a known key and the WhatsApp username. First, create the pass phrase file pbkdf2_pass.bin
with the known key using xxd
– a tool to create a binary file from a hex dump.
1 |
$ echo c2991ec29b1d0cc2b8c3b7556458c298c29203c28b45c2973e78c386c395 | xxd -r -p > pbkdf2_pass.bin |
Next, append the username or your mobile number to the pass phrase. The number must be in international format but without the +
sign. So, if your country code is +65
and if your mobile number is 91234567
, the username becomes 6591234567
.
1 |
$ echo -n 6591234567 | hexdump -e '2/1 "%02x"' | xxd -r -p >> pbkdf2_pass.bin |
Now, we have the inputs for the PBKDF2
function. The PBKDF2
function needs a small C program as openssl
does not seem to support it from the command line.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
#include <stdio.h> #include <string.h> #include <openssl/x509.h> #include <openssl/evp.h> #include <openssl/hmac.h> int main(int argc, char *argv[]) { unsigned char pass[1024]; // passphrase read from stdin unsigned char salt[1024]; // salt int salt_len; // salt length int ic; // iteration unsigned char result[1024]; // result FILE *fp_salt; if ( argc != 3 ) { fprintf(stderr, "usage: %s salt_file iteration < passwd_file > binary_key_file \n", argv[0]); exit(1); } ic = atoi(argv[2]); fp_salt = fopen(argv[1], "r"); if(!fp_salt) { fprintf(stderr, "error opening salt file: %s\n", argv[1]); exit(2); } salt_len=0; int ch; while((ch = fgetc(fp_salt)) != EOF) { salt[salt_len++] = (unsigned char)ch; } fclose(fp_salt); fgets(pass, 1024, stdin); if ( pass[strlen(pass)-1] == '\n' ) pass[strlen(pass)-1] = '\0'; PKCS5_PBKDF2_HMAC_SHA1(pass, strlen(pass), salt, salt_len, ic, 16, result); fwrite(result, 1, 16, stdout); return(0); } |
Save the C program to a file called wa_pbkdf2.c
and compile it using gcc
.
1 |
$ gcc -o wa_pbkdf2 wa_pbkdf2.c -lssl |
If you get any errors like undefined reference to `PKCS5_PBKDF2_HMAC_SHA1'
, then try linking with the crypto
library instead of the ssl
library.
1 |
$ gcc -o wa_pbkdf2 wa_pbkdf2.c -lcrypto |
gcc
will create a binary called wa_pbkdf2
. Now, proceed to generate the output hash from the PBKDF2 function using the C program.
1 |
$ ./wa_pbkdf2 pw_salt 16 < pbkdf2_pass.bin > pbkdf2_key.bin |
We are done with step 1 of the decryption process. Step 2 involves AES OFB 128-bit decryption. We need two variables, K
and IV
. The input message is the encrypted key kept in the pw_ekey
file. K
can be found from the output of the wa_pbkdf2
program. IV
is kept in the pw_iv
file. For K
and IV
we need the values in hex dump format. Extract the values and initialise the variables $k
and $iv
.
1 2 |
$ k=$(hexdump -e '2/1 "%02x"' pbkdf2_key.bin) $ iv=$(hexdump -e '2/1 "%02x"' pw_iv) |
Now, we can decrypt using openssl
.
1 |
$ openssl enc -aes-128-ofb -d -nosalt -in pw_ekey -K $k -iv $iv -out wa_password.key |
The output will be saved to the file wa_password.key
. To view the actual password, encode the output using base64
.
1 |
$ base64 wa_password.key |
The WhatsApp passsword will be printed out.
Updated (22-Dec-2014): Added gcc
command to compile with crypto
library.
Updated (14-Feb–2015): Extracting password file using ADB Backup feature is no longer applicable.
Related: How to Decrypt WhatsApp crypt7 Database Messages