Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python
- #coding=utf-8
- # Decrypt sent and received WebSocket messages from WhatsApp Web
- # To use this version, you need to get data before QR code generation (less convenient than the other script whatsapp_web_decrypt_encrypt.py)
- # Only works with Python 2 (you need to install missing packages with a command like python2 -m pip install packagename)
- # Remember when sharing scripts / hacks or findings: "the quieter you become, the more you are able to hear"
- # https://i.blackhat.com/USA-19/Wednesday/us-19-Zaikin-Reverse-Engineering-WhatsApp-Encryption-For-Chat-Manipulation-And-More.pdf
- # https://github.com/romanzaikin/BurpExtension-WhatsApp-Decryption-CheckPoint
- # https://stackoverflow.com/questions/66905708/how-to-decrypt-sent-binary-message-by-whatsapp-web/67226952
- # Dependencies: https://github.com/sigalor/whatsapp-web-reveng/tree/master/backend
- import base64
- import curve25519
- import hmac
- import hashlib
- from Crypto.Cipher import AES
- from whatsapp_binary_reader import whatsappReadBinary
- # JSON key "secret" found with the WebSocket inspector in the network monitor of a web browser after QR code scan
- qr_code_secret = "XXX"
- # found with a breakpoint on the line "keyPair: t" (without quotes) in the file bootstrap_qr.*.js and a watcher "new Uint8Array(t.privKey)" (without quotes)
- priv_key_list = [X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X]
- # found with a breakpoint on the line "keyPair: t" (without quotes) in the file bootstrap_qr.*.js and a watcher "new Uint8Array(t.pubKey)" (without quotes)
- pub_key_list = [X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X]
- # Replace with a WebSocket message copied using a tool like mitmdump from mitmproxy (copying the message with the WebSocket inspector in the network monitor of a web browser like Firefox will fail)
- message = b'XXX'
- def hmac_sha256(key, sign):
- return hmac.new(key, sign, hashlib.sha256).digest()
- def HKDF(key, length, app_info=""):
- key = hmac_sha256("\0" * 32, key)
- key_stream = ""
- key_block = ""
- block_index = 1
- while len(key_stream) < length:
- key_block = hmac.new(key, msg=key_block + app_info + chr(block_index), digestmod=hashlib.sha256).digest()
- block_index += 1
- key_stream += key_block
- return key_stream[:length]
- def aes_decrypt(key, ciphertext):
- iv = ciphertext[:AES.block_size]
- cipher = AES.new(key, AES.MODE_CBC, iv)
- plaintext = cipher.decrypt(ciphertext[AES.block_size:])
- return aes_unpad(plaintext)
- def aes_unpad(s):
- return s[:-ord(s[len(s) - 1:])]
- secret = base64.b64decode(qr_code_secret)
- private_key = curve25519.Private("".join([chr(x) for x in priv_key_list]))
- public_key = private_key.get_public()
- assert (public_key.serialize() == "".join([chr(x) for x in pub_key_list]))
- shared_secret = private_key.get_shared_key(curve25519.Public(secret[:32]), lambda key: key)
- shared_secret_ex = HKDF(shared_secret, 80)
- check_hmac = hmac_sha256(shared_secret_ex[32:64], secret[:32] + secret[64:])
- if check_hmac != secret[32:64]:
- raise ValueError("hmac mismatch")
- key_decrypted = aes_decrypt(shared_secret_ex[:32], shared_secret_ex[64:] + secret[64:])
- aes_key = key_decrypted[:32]
- mac_key = key_decrypted[32:64]
- message_parts = message.split(",", 1)
- content = message_parts[1]
- decrypted_content = aes_decrypt(aes_key, content[32:])
- processedData = whatsappReadBinary(decrypted_content, True)
- print(processedData)
Add Comment
Please, Sign In to add comment