Breaking Down Whatsapp encryption EXPOIT.
In this article am going to explain in depth how you can decrypt Whatsapp messages.
First let’s talk about how Whatsapp store messages into your mobile device:
Your chats are being saved on your phone and not on the Whatsapp server. The only moment Whatsapp saves your message is the moment you send it. The message is being saved on Whatsapp servers until it can be delivered to the recieving phone. This might take a while when that phone is out reach of internet or is turned off.
If the message is on the Whatsapp server for more than 30 days it will be deleted from the server.
And Whatsapp store the messages inside (SD card>Whatsapp>Database folder)
msgstore.db.crypt12 -> this file contains all of your messages but it’s encrypted 🙂
Let’s get started into the fun stuff:
You can decrypt WhatsApp message backup file i.e. msgstore.db.crypt12. You can also decrypt the previous backup file with format crypt7, crypt5 etc….
Database file with name msgstore.db.crypt12. You can find this file in your Device storage.
Path: Device Storage/WhatsApp/Databases/msgstore.db.crypt12
It is required to root your phone to find key otherwise you will get empty folder.
Key: Key file contains a decryption key which is essential to decrypt an encrypted file. Since WhatsApp saves this key in your system storage so you can find that file on following location. To open system folder you can use ES File Explorer. ES File Explorer File Manager – Android Apps on Google Play
WhatsApp backup conversation files are now saved with the .crypt12 extension. From crypt9, they seem to be using a modified version of Spongy Castle – a cryptography API library for Android.
All the findings below are based on reverse engineering work done on WhatCrypt and Omni-Crypt. I would like to highlight that IGLogger proved to be a very useful tool when it came to smali code debugging.
Extract Key File
To decrypt the crypt12 files, you will first need the key file. The key file stores the encryption key, K. WhatsApp stores the key file in a secure location: /data/data/com.whatsapp/files/key.
If your phone is rooted, extracting this file is easy. If your phone is not rooted, refer to instructions from WhatCrypt and Omni-Crypt for details on extracting the key file. The idea is to install an older version of WhatsApp, where Android ADB backup was still working and extract the key file from the backup.
Extract crypt12 Backup File
Pull the encrypted WhatsApp messages file from your phone using ADB.
$ adb pull /sdcard/WhatsApp/Databases/msgstore.db.crypt12
This section is just for your information and you can skip this section.
The encryption method being used is AES with a key (K) length of 256 bits and an initialization vector (IV) size of 128 bits. The 256-bit AES key is saved from offset 0x7E till 0x9D in the file. Offsets start from 0x00. You can extract the AES key with hexdump and assign the value to variable $k.
$ k=$(hexdump -ve '2/1 "%02x"' key | cut -b 253-316)
The $k variable will hold a 64-digit hexadecimal value in ASCII that is actually 256 bits in length.
The IV or the initialisation vector is saved from offset 0x33 till 0x42 in the crypt12 file. The IV value will be different for every crypt12 file.
$ iv=$(hexdump -n 67 -ve '2/1 "%02x"' msgstore.db.crypt12 | cut -b 103-134)
The K and IV extraction method is similar to what we have done for crypt8 files before.
Strip Header / Footer in crypt12 File
Again, this section is just for your information and you can skip this section.
Before we start the decryption process, we will need to strip the 67 byte header and 20 byte footer from the crypt12 file.
$ dd if=msgstore.db.crypt12 of=msgstore.db.crypt12.enc ibs=67 skip=1
$ truncate -s -20 msgstore.db.crypt12.enc
The above dd command will strip the the first 67 bytes from the crypt12 file and save it to a file with extension crypt12.enc. The truncate command will strip the last 20 bytes from the crypt12 file.
Decrypt THE crypt12 File
As the WhatsApp AES cryptography API library seems to be a modified version, we will no longer be able to use openssl to decrypt the crypt12 file. I have yet to determine what has been modified.
To decrypt crypt12 files, I have written a simple Java program that will use the modified cryptography API library instead. For the cryptography API library, I have extracted the modified Spongy Castle cryptography class files from the Omni-Crypt APK file using dex2jar. You can find the Java program and crypto library over here at GitHub.
The Java program will create 3 output files:
- msgstore.db.crypt12.enc – encrypted file with header and footer stripped.
- msgstore.db.zlib – decrypted file in zlib format.
- msgstore.db – decrypted sqlite3 database file.
Below is how you can compile and run the Java program.
$ git clone https://github.com/JameelNabbo/WhatsappDecryption.git
$ cd WhatsappDecryption/
$ javac -classpath "lib/whatsapp_spongycastle.jar:." crypt12.java
$ cp ../whatsapp.data/key .
$ cp ../whatsapp.data/msgstore.db.crypt12 .
$ java -cp "lib/whatsapp_spongycastle.jar:." WTDecrypt
creating encrypted file with header/footer stripped: msgstore.db.crypt12.enc
creating zlib output file: msgstore.db.zlib
creating sqlite3 output file: msgstore.db
$ ls -l total 136724 -rw-r--r-- 1 Jameel ************* WTDecrypt.class -rw-r--r-- 1 Jameel ************* WTDecrypt.java -rw-r--r-- 1 Jameel ************* key drwxr-xr-x 2 Jameel ************* lib -rw-r--r-- 1 Jameel ************* LICENSE -rw-r--r-- 1 Jameel ************* msgstore.db -rw-r--r-- 1 Jameel ************* msgstore.db.crypt12 -rw-r--r-- 1 Jameel ************* msgstore.db.crypt12.enc -rw-r--r-- 1 Jameel ************* msgstore.db.zlib -rw-r--r-- 1 Jameel ************* README.md
$ file * WTDecrypt.class: compiled Java class data, version 52.0 (Java 1.8) WTDecrypt.java: C source, ASCII text key: Java serialization data, version 5 lib: directory msgstore.db: SQLite 3.x database, user version 1 msgstore.db.crypt12: raw G3 data, byte-padded msgstore.db.crypt12.enc: data msgstore.db.zlib: zlib compressed data
To use the Java decryption tool, you will need to use OpenJDK. Oracle require JCE Provider libraries to be signed. OpenJDK does not have this requirement. If you try running the Java program on Oracle JDK, you will most likely get the following exception.
Have fun 🙂