Support crypt14 WhatsApp Backup

This commit is contained in:
KnugiHK
2021-07-10 21:08:52 +08:00
parent 620e89a185
commit 18ee152688
2 changed files with 51 additions and 1 deletions

View File

@@ -40,7 +40,7 @@ def main():
"--backup",
dest="backup",
default=None,
help="Path to iPhone backup")
help="Path to Android (must be used together with -k)/iPhone WhatsApp backup")
parser.add_option(
"-o",
"--output",
@@ -60,6 +60,13 @@ def main():
dest='db',
default=None,
help="Path to database file")
parser.add_option(
'-k',
'--key',
dest='key',
default=None,
help="Path to key file"
)
(options, args) = parser.parse_args()
if options.android and options.iphone:
@@ -80,6 +87,16 @@ def main():
msg_db = "msgstore.db"
else:
msg_db = options.db
if options.key is not None:
if options.backup is None:
print("You must specify the backup file with -b")
return False
print("Decryption key specified, decrypting WhatsApp backup...")
key = open(options.key, "rb").read()
db = open(options.backup, "rb").read()
if not extract.decrypt_backup(db, key, msg_db):
print("Dependencies of decrypt_backup are not present. For details, see README.md")
return False
if options.wa is None:
contact_db = "wa.db"
else:

View File

@@ -10,6 +10,13 @@ import re
import pkgutil
from datetime import datetime
from mimetypes import MimeTypes
try:
import zlib
from Crypto.Cipher import AES
except ModuleNotFoundError:
support_backup = False
else:
support_backup = True
def determine_day(last, current):
@@ -21,6 +28,32 @@ def determine_day(last, current):
return current
def decrypt_backup(database, key, output):
if not support_backup:
return False
if len(key) != 158:
raise ValueError("The key file must be 158 bytes")
if len(database) < 191:
raise ValueError("The database file must be at least 191 bytes")
t1 = key[30:62]
t2 = database[15:47]
if t1 != t2:
raise ValueError("The signature of key file and backup file mismatch")
iv = database[67:83]
db_ciphertext = database[191:]
main_key = key[126:]
cipher = AES.new(main_key, AES.MODE_GCM, iv)
db_compressed = cipher.decrypt(db_ciphertext)
db = zlib.decompress(db_compressed)
if db[0:6].upper() == b"SQLITE":
with open(output, "wb") as f:
f.write(db)
return True
else:
raise ValueError("The plaintext is not a SQLite database. Did you use the key to encrypt something...")
def contacts(db, data):
# Get contacts
c = db.cursor()