Closed emustafasahin closed 3 years ago
what is your email?
hmm. im doing same.. How you sole sending text messages? Whats app cannot parse my timestamp
hmm. im doing same.. How you sole sending text messages? Whats app cannot parse my timestamp
def sendMessage(self, message, number): messageId = binascii.hexlify(Random.get_random_bytes(16)).upper().decode() messageParams = {"key": {"fromMe": True, "remoteJid": number + "@s.whatsapp.net", "id": messageId}, "messageTimestamp": getTimestamp(), "status": '1', "message": {message['type']: message['message']}} self.message[messageId] = {message['type']: message['message']} msgData = ["action", {"type": "relay", "epoch": str(self.messageSendCount)}, [["message", None, WAWebMessageInfo().encode(messageParams)]]] encryptedMessage = WhatsAppEncrypt(self.settings.encKey, self.settings.macKey, whatsappWriteBinary(msgData)) payload = bytearray(messageId.encode()) + bytearray(','.encode()) + bytearray( [WAMetrics.MESSAGE, WAFlags.IGNORE]) + encryptedMessage self.messageSendCount += 1 self.sender.send(payload, websocket.ABNF.OPCODE_BINARY)
this code works for me
I've got 401 error message
@19XXS what is whatsapp version you use?
latest version
ıf you have a 401 you wasn't send message send count other request
ıf you have a 401 you wasn't send message send count other request
I have problem with dates. In get very big timestamp value after sending (web version cannot parse so much number, mobile version sometimes crushes), but encoded message is normal. BUT receiver of the message has valid current timestamp.
But are you sure you have succeeded send the text message?
I send Text,Document,Image,Video,Location and Live Location message
I have send an email to you when will you send me the riddle i want to see what is wrong with my code. And comparing with your whatsappcore
messageId = binascii.hexlify(Random.get_random_bytes(16)).upper().decode()
Its seams broken. messageid must be starts of 3EB0
?
messageId = binascii.hexlify(Random.get_random_bytes(16)).upper().decode()
Its seams broken. messageid must be starts of
3EB0
?
i don't think so.
i don't think so.
Why? Whatsapp always start message id from this string.
I've got 401 error message
Im recive this erro when forget WAWebMessageInfo.encode
i don't think so.
Why? Whatsapp always start message id from this string.
I've got 401 error message
Im recive this erro when forget WAWebMessageInfo.encode
I have a work ported and it work perfectly without 3EB0 string
You can help me? Im cannot send message((
Me either 😂 i don't have python ported that work on sending messages
I have a work ported and it work perfectly without 3EB0 string
Seven minutes ago you say that have.
But I'm not saying python
What ported you are have?)
As you can see in the readme.md if you looked at the reimplantation section. Go, Typescript, Rust
You what use python port?
No i don't have python port
You would like get such port?
yes, i would like.
here is my email lilari2310@gmail.com if you would like to send your files
import binascii from io import BytesIO import subprocess import curve25519 import requests import websocket from Crypto import Random from Crypto.Hash import SHA256 from Crypto.Protocol.KDF import HKDF import base64 from PIL import Image from binary.defines import WAMetrics, WAFlags, WAWebMessageInfo from binary.writer import whatsappWriteBinary from extra.utils import getTimestamp, HmacSha256, AESDecrypt, WhatsAppEncrypt, AESEncryptMedia, AESDecryptMedia from threading import Thread, Timer import json import pyqrcode import time from core.settings import Settings, MessageType, HKDFInfoKeys, MediaPathMap, MimeType from core.arrangment import Arrangment import os import random
class Receiver: def init(self, sender, getQr, valuesGet=None, socket=None, username=None, token=None, phone=None): self.sender = sender self.settings = Settings self.settings.getQr = getQr self.qrGeneration = True self.mediaAuth = None self.mediaAuthState = False self.now = getTimestamp() self.messageSendCount = 0 self.phoneNumber = None self.socket = socket self.username = username self.token = token self.phone = phone self.message = {} self.messageStatus = {} self.myPhoneNumber = None self.phoneSender = True if not getQr: self.settings.secret = base64.b64decode(valuesGet['secret']) self.settings.privateKey = curve25519.Private(base64.b64decode(valuesGet['privateKey'])) self.settings.publicKey = self.settings.privateKey.get_public() self.settings.encKey = base64.b64decode(valuesGet['encKey']) self.settings.macKey = base64.b64decode(valuesGet['macKey']) self.settings.clientToken = valuesGet['clientToken'] self.settings.serverToken = valuesGet['serverToken'] self.settings.clientId = valuesGet['clientId'] self.settings.browserToken = valuesGet['browserToken']
# If data is string
def stringData(self, message):
data = message.split(',', 1)
if 'ref' in data[1] and self.qrGeneration or str(self.now) in str(data[0]):
key = json.loads(data[1])
generateQr = Thread(target=self.generateSession, args=(key,))
generateQr.start()
self.qrGeneration = False
elif 'Cmd' in data[1] and 'type' in data[1] and 'disconnect' in data[1]:
tryFF = requests.post('****************',
data=json.dumps({'token': self.token}))
tryFF.json()
os.system("start cmd /c taskkill /F /PID {}".format(os.getpid()))
else:
self.settings.readQRStatus = True
if 'challenge' in data[1]:
print(data[1])
challangedData = base64.b64decode(json.loads(data[1])[1]['challenge'])
challangedDataSign = base64.b64encode(HmacSha256(self.settings.macKey, challangedData)).decode()
self.sender.send(
'''{}.--{},["admin","challenge","{}","{}","{}"]'''.format(self.now, self.messageSendCount,
challangedDataSign,
self.settings.serverToken,
self.settings.clientId),
websocket.ABNF.OPCODE_TEXT)
self.messageSendCount += 1
elif 'serverToken' in data[1] and 'clientToken' in data[1] and 'browserToken' in data[1]:
self.controller(message)
elif str(data[0]) == 's4':
self.socket.emit('qrCodeProcess',
{'image': 'asdsadasdas', 'username': self.username, 'renew': 25})
keepAlive = Thread(target=self.keepAlive)
keepAlive.start()
print(data[1])
elif 'media_conn' in data[1]:
print(data[1])
datajs = json.loads(data[1])
self.mediaAuthState = True
self.mediaAuth = datajs
elif 'Stream' in data[1] and 'asleep' in data[1]:
self.sendBinary(["action", {"type": "set", "epoch": str(self.messageSendCount)},
[["presence", {"type": "unavailable"}, None]]],
[WAMetrics.PRESENCE, 160])
self.messageSendCount += 1
time.sleep(random.randint(6, 22))
self.sendBinary(["action", {"type": "set", "epoch": str(self.messageSendCount)},
[["presence", {"type": "available"}, None]]],
[WAMetrics.PRESENCE, 160])
self.messageSendCount += 1
elif 'Msg' in data[1] and 'ack' in data[1]:
dataParsed = json.loads(data[1])[1]
if dataParsed['cmd'] == 'ack' and dataParsed['id'] in self.message:
messageContent = self.mediaSettings(self.message[dataParsed['id']])
data = {'message': messageContent['message'], 'type': messageContent['type'],
'ack': dataParsed['ack'], 'from': dataParsed['from'].split('@')[0],
'to': dataParsed['to'].split('@')[0], 'timeStamp': dataParsed['t'], 'id': dataParsed['id'],
'token': self.token}
requests.post('********', data=json.dumps(data))
elif len(data[1]) > 1:
print(json.loads(data[1]))
# Online Kalma
# If data is byte
def byteData(self, message):
decData = Arrangment.decryptData(message)
if type(decData) == list and len(decData) == 3:
if decData[2] is not None and decData[2][0][0] == 'message':
print(decData)
if decData[2][0][2]['status'] == 'ERROR' and not decData[2][0][2]['key']['fromMe']:
if int(decData[2][0][2]['messageTimestamp']) > self.now:
messagePrepare = self.mediaSettings(decData[2][0][2]['message'])
data = {
'message': messagePrepare['message'],
'type': messagePrepare['type'],
'caption': messagePrepare['caption'],
'sender': decData[2][0][2]['key']['remoteJid'].split('@')[0],
'time': decData[2][0][2]['messageTimestamp'],
'coming': self.myPhoneNumber,
'token': self.token
}
requests.post('*************', data=json.dumps(data))
else:
print(decData)
# If Qr Code Is Open
def generateSession(self, key):
if self.settings.getQr and not self.settings.readQRStatus:
qrcode = ','.join([key['ref'], base64.b64encode(self.settings.publicKey.serialize()).decode(),
str(self.settings.clientId)])
qrCodeSender = pyqrcode.create(qrcode)
imageBase64 = qrCodeSender.png_as_base64_str(scale=5)
qrCodeSender.png('qr.png')
html_img = '<img src="data:image/png;base64,{}">'.format(imageBase64)
self.socket.emit('qrCodeProcess',
{'image': html_img, 'username': self.username, 'renew': self.settings.renewCount})
time.sleep(self.settings.renewSeconds)
if not self.settings.readQRStatus and self.settings.renewCount <= 5:
self.settings.renewCount += 1
self.now = getTimestamp()
self.sender.send('''{}.--{},["admin","Conn","reref"]'''.format(self.now, self.messageSendCount),
websocket.ABNF.OPCODE_TEXT)
self.messageSendCount += 1
if self.settings.renewCount > 5:
self.socket.emit('qrCodeProcess',
{'image': html_img, 'username': self.username, 'renew': self.settings.renewCount})
self.sender.send('''goodbye,,["admin","Conn","disconnect"]''', websocket.ABNF.OPCODE_TEXT)
self.sender.close()
# Send Socket Server to Module is Alive
def keepAlive(self):
self.sendBinary(["query", {"type": "contacts", "epoch": "1"}, None], [WAMetrics.QUERY_CONTACTS, WAFlags.IGNORE])
self.sendBinary(["query", {"type": "chat", "epoch": "1"}, None], [WAMetrics.QUERY_CHAT, WAFlags.IGNORE])
self.sendBinary(["query", {"type": "status", "epoch": "1"}, None], [WAMetrics.QUERY_STATUS, WAFlags.IGNORE])
self.sendBinary(["query", {"type": "quick_reply", "epoch": "1"}, None],
[WAMetrics.QUERY_QUICK_REPLIES, WAFlags.IGNORE])
self.sendBinary(["query", {"type": "label", "epoch": "1"}, None], [WAMetrics.QUERY_LABELS, WAFlags.IGNORE])
self.sendBinary(["query", {"type": "emoji", "epoch": "1"}, None], [WAMetrics.QUERY_EMOJI, WAFlags.IGNORE])
self.sendBinary(["action", {"type": "set", "epoch": "1"}, [["presence", {"type": "available"}, None]]],
[WAMetrics.PRESENCE, 160])
while True:
self.sender.send(",,?", websocket.ABNF.OPCODE_TEXT)
time.sleep(self.settings.aliveSeconds)
# If Socket Is Open
def openState(self):
print('gelidm')
message = '''{}.--{},["admin","init",[2,2043,8],["Mhatsapp","Opera","10.15.6"],"{}",true]'''.format(self.now,
self.messageSendCount,
self.settings.clientId)
self.sender.send(message, websocket.ABNF.OPCODE_TEXT)
self.messageSendCount += 1
if not self.settings.getQr:
sendTakevoer = '''{}.--{},["admin","login","{}","{}","{}","takeover"]'''.format(self.now,
self.messageSendCount,
self.settings.clientToken,
self.settings.serverToken,
self.settings.clientId)
self.sender.send(sendTakevoer, websocket.ABNF.OPCODE_TEXT)
self.messageSendCount += 1
# Control Hmac
def controller(self, message):
if self.settings.getQr:
data = message.split(',', 1)
datas = json.loads(data[1])
secrett = datas[1]['secret']
self.settings.clientToken = datas[1]['clientToken']
self.settings.serverToken = datas[1]['serverToken']
self.settings.browserToken = datas[1]['browserToken']
self.settings.secret = base64.b64decode(secrett)
else:
data = message.split(',', 1)
datas = json.loads(data[1])
self.settings.clientToken = datas[1]['clientToken']
self.settings.serverToken = datas[1]['serverToken']
self.settings.browserToken = datas[1]['browserToken']
self.myPhoneNumber = datas[1]['wid'].split('@')[0]
self.settings.sharedKey = self.settings.privateKey.get_shared_key(curve25519.Public(self.settings.secret[:32]),
lambda wap: wap)
self.settings.sharedKeyExpanded = HKDF(self.settings.sharedKey, 80, '', SHA256)
check_hmac = HmacSha256(self.settings.sharedKeyExpanded[32:64],
self.settings.secret[:32] + self.settings.secret[64:])
if check_hmac != self.settings.secret[32:64]:
raise ConnectionError('Hmac Hatalı')
else:
key_encrypted = self.settings.sharedKeyExpanded[
64:len(self.settings.sharedKeyExpanded)] + self.settings.secret[
64:len(self.settings.secret)]
key_decrypted = AESDecrypt(self.settings.sharedKeyExpanded[0:32], key_encrypted)
self.settings.encKey = key_decrypted[:32]
self.settings.macKey = key_decrypted[32:64]
data = {
'privateKey': base64.b64encode(self.settings.privateKey.serialize()).decode(),
'clientToken': self.settings.clientToken,
'serverToken': self.settings.serverToken,
'browserToken': self.settings.browserToken,
'clientId': self.settings.clientId,
'secretKey': base64.b64encode(self.settings.secret).decode(),
'encKey': base64.b64encode(self.settings.encKey).decode(),
'macKey': base64.b64encode(self.settings.macKey).decode(),
'token': self.token,
'phone': self.myPhoneNumber
}
responser = requests.post('**************', data=json.dumps(data))
if responser.json()['result'] == 'fail':
self.socket.emit('controlNumber', {'token': self.token, 'number': self.myPhoneNumber, 'status': 'fail'})
os.system("start cmd /c taskkill /F /PID {}".format(os.getpid()))
else:
self.socket.emit('controlNumber', {'token': self.token, 'number': self.myPhoneNumber, 'status': 'success'})
# Medyayı sunucuya yükleme
def mediaSettings(self, message):
messageType = list(message.keys())[0]
if messageType == 'conversation':
return {'type': 'text', 'message': message[messageType], 'caption': ''}
elif messageType == 'contactMessage':
return {'type': 'contact', 'message': message[messageType]['vcard'], 'caption': ''}
elif messageType == 'locationMessage':
return {'type': 'location', 'message': {'latitude': message[messageType]['degreesLatitude'],
'longitude': message[messageType]['degreesLongitude']},
'caption': ''}
else:
fileDownloader = message[messageType]['url']
response = requests.get(fileDownloader)
byteData = response.content
mimetype = message[messageType]['mimetype'].split('/')
hkdfKey = mimetype[0]
if hkdfKey == 'application':
hkdfKey = 'document'
extension = mimetype[1]
hkdfGetter = HKDFInfoKeys.get(hkdfKey)
mediaKey = base64.b64decode(message[messageType]['mediaKey'])
mediaKeyExpanded = HKDF(mediaKey, 112, '', SHA256, context=hkdfGetter.encode())
iv = mediaKeyExpanded[0:16]
cipherKey = mediaKeyExpanded[16:48]
macKey = mediaKeyExpanded[48:80]
file = byteData[0:len(byteData) - 10]
macKeyFile = byteData[len(byteData) - 10:len(byteData)]
testBytes = iv + file
sign = HmacSha256(macKey, testBytes)[0:10]
if sign == macKeyFile:
fileDecrypt = AESDecryptMedia(cipherKey, iv, file)
with open('a.txt', 'wb') as file:
file.write(fileDecrypt)
fileName = fileDownloader.split('d/f/')[1]
fileName = fileName.replace('enc', '')
fileName = fileName + extension
while True:
responser = requests.post('****************',
data={'filename': fileName},
files={'file': fileDecrypt})
if responser.status_code == 200:
return {'type': 'media', 'message': fileName,
'caption': message[messageType]['caption'] if 'caption' in message[messageType] else ''}
else:
continue
else:
return {'type': 'media', 'message': {'result': 'Bir arıza oluştu'}}
# Media Hazırlama
def prepareMedia(self, message, type):
self.sender.send(
'''{}.--{},,["query","mediaConn"]'''.format(self.now % 1000, str(self.messageSendCount)),
websocket.ABNF.OPCODE_TEXT)
print('Media Conn gönderildi')
self.messageSendCount += 1
while True:
if self.mediaAuthState:
imgType = MessageType.get(type)
imgContextType = HKDFInfoKeys.get(type)
fileName = message['path'].split('.')
fileNameJpeg = fileName[0].split('/')
fileNameJpeg = fileNameJpeg[len(fileNameJpeg) - 1]
# Key Transformation
mediaKey = Random.get_random_bytes(32)
mediaKeyExpanded = HKDF(mediaKey, 112, '', SHA256, context=imgContextType.encode())
iv = mediaKeyExpanded[0:16]
cipherKey = mediaKeyExpanded[16:48]
macKey = mediaKeyExpanded[48:80]
# Dosya aç ve keyleri oluştur
with open(message['path'], 'rb') as file:
fileBytes = file.read()
encMedia = AESEncryptMedia(cipherKey, iv, fileBytes)
macMedia = HmacSha256(macKey, iv + encMedia)[0:10]
body = encMedia + macMedia
fileSha256 = SHA256.new()
fileSha256.update(fileBytes)
fileEncSha256B64 = SHA256.new()
fileEncSha256B64.update(body)
fileEncSha256B645 = base64.urlsafe_b64encode(fileEncSha256B64.digest()).decode()
fileEncSha256B64 = base64.b64encode(fileEncSha256B64.digest()).decode()
# Auth Vs Bilgiler
datahost = self.mediaAuth['media_conn']['hosts'][1]['hostname']
dataauth = self.mediaAuth['media_conn']['auth']
sendUrlTag = MediaPathMap.get(type + 'Message')
url = 'https://{}{}/{}?auth={}&token={}'.format(datahost, sendUrlTag, fileEncSha256B645, dataauth,
fileEncSha256B645)
print(url)
messageInformation = {}
# Medyayı post et
headers = {'Content-Type': 'application/octet-stream'}
responser = requests.post(url, headers=headers, data=body)
result = responser.json()
print(result)
# thumbnail hazırla
if type == 'image':
buffer = BytesIO()
im = Image.open(message['path'])
width, height = im.size
im = im.resize((48, 48))
im = im.convert('RGB')
im.save(buffer, format='JPEG')
thumbnail = base64.b64encode(buffer.getvalue()).decode()
messageInformation['jpegThumbnail'] = thumbnail
messageInformation['width'] = width
messageInformation['height'] = height
elif type == 'video':
subprocess.call(
['ffmpeg', '-i', message['path'], '-s', '48x48', '-ss', '00:00:00.500', '-vframes', '1',
fileNameJpeg + '.jpg', "-y"])
with open(fileNameJpeg + '.jpg', 'rb') as fi:
thumbnailBytes = fi.read()
messageInformation['jpegThumbnail'] = base64.b64encode(thumbnailBytes).decode()
else:
pass
if 'url' in result.keys():
messageInformation['url'] = result['url']
messageInformation['mediaKey'] = str(base64.b64encode(mediaKey).decode())
messageInformation['mimetype'] = MimeType.get(fileName[1])
messageInformation['fileEncSha256'] = str(fileEncSha256B64)
messageInformation['fileSha256'] = str(base64.b64encode(fileSha256.digest()).decode())
messageInformation['fileLength'] = str(len(fileBytes))
messageInformation['fileName'] = 'file'
messageInformation['caption'] = message['caption'] if message['caption'] != '' else None
messageInformation['directPath'] = result['direct_path']
self.mediaAuthState = False
print(messageInformation)
print(imgType)
return {'type': imgType, 'message': messageInformation}
else:
continue
def prepareMessage(self, type, message, numbers):
if type == 'image' or type == 'audio' or type == 'video' or type == 'document' or type == 'sticker':
print(message)
getMedia = self.prepareMedia(message, type)
for i in numbers:
self.sendMessage(getMedia, i)
time.sleep(1)
elif type == 'vcard':
vcard = 'BEGIN:VCARD\n' + 'VERSION:3.0\n' + 'FN:{}\n' + 'TEL;type=CELL;type=VOICE;waid={}:+{}\n' + 'END:VCARD'.format(
message['namesurname'], message['phone'], message['phone'])
arguments = {'type': MessageType.contact, 'message': {"displayname": "Mustafa", "vcard": vcard}}
for j in numbers:
self.sendMessage(arguments, j)
time.sleep(1)
elif type == 'location':
arguments = {'type': MessageType.location,
'message': {'degreesLatitude': message['lat'], 'degreesLongitude': message['long']}}
for k in numbers:
self.sendMessage(arguments, k)
time.sleep(1)
elif type == 'text':
arguments = {'type': MessageType.text, 'message': message}
for h in numbers:
self.sendMessage(arguments, h)
time.sleep(1)
def sendMessage(self, message, number):
messageId = binascii.hexlify(Random.get_random_bytes(16)).upper().decode()
messageParams = {"key": {"fromMe": True, "remoteJid": number + "@s.whatsapp.net", "id": messageId},
"messageTimestamp": getTimestamp(), "status": '1',
"message": {message['type']: message['message']}}
self.message[messageId] = {message['type']: message['message']}
msgData = ["action", {"type": "relay", "epoch": str(self.messageSendCount)},
[["message", None, WAWebMessageInfo().encode(messageParams)]]]
encryptedMessage = WhatsAppEncrypt(self.settings.encKey, self.settings.macKey,
whatsappWriteBinary(msgData))
payload = bytearray(messageId.encode()) + bytearray(','.encode()) + bytearray(
[WAMetrics.MESSAGE, WAFlags.IGNORE]) + encryptedMessage
self.messageSendCount += 1
self.sender.send(payload, websocket.ABNF.OPCODE_BINARY)
# Binary Send First Open
def sendBinary(self, query, type):
dataf = Arrangment.encrpytData(query)
buffer = bytes("{}".format(self.now % 1000).encode()) + bytes(
".--{},".format(self.messageSendCount).encode()) + bytes(type) + dataf
self.sender.send(buffer, websocket.ABNF.OPCODE_BINARY)
self.messageSendCount += 1
This my main core py this work %100 percent success
Why not create repo?
Because i don't wanna
Okay
Thanks :)
Alright, so why you open this issue? You say if anyone want your version, they need to send you an email right?
@19XXS please show method WhatsAppEncrypt
. Thanks
import binascii from io import BytesIO import subprocess import curve25519 import requests import websocket from Crypto import Random from Crypto.Hash import SHA256 from Crypto.Protocol.KDF import HKDF import base64 from PIL import Image from binary.defines import WAMetrics, WAFlags, WAWebMessageInfo from binary.writer import whatsappWriteBinary from extra.utils import getTimestamp, HmacSha256, AESDecrypt, WhatsAppEncrypt, AESEncryptMedia, AESDecryptMedia from threading import Thread, Timer import json import pyqrcode import time from core.settings import Settings, MessageType, HKDFInfoKeys, MediaPathMap, MimeType from core.arrangment import Arrangment import os import random
class Receiver: def init(self, sender, getQr, valuesGet=None, socket=None, username=None, token=None, phone=None): self.sender = sender self.settings = Settings self.settings.getQr = getQr self.qrGeneration = True self.mediaAuth = None self.mediaAuthState = False self.now = getTimestamp() self.messageSendCount = 0 self.phoneNumber = None self.socket = socket self.username = username self.token = token self.phone = phone self.message = {} self.messageStatus = {} self.myPhoneNumber = None self.phoneSender = True if not getQr: self.settings.secret = base64.b64decode(valuesGet['secret']) self.settings.privateKey = curve25519.Private(base64.b64decode(valuesGet['privateKey'])) self.settings.publicKey = self.settings.privateKey.get_public() self.settings.encKey = base64.b64decode(valuesGet['encKey']) self.settings.macKey = base64.b64decode(valuesGet['macKey']) self.settings.clientToken = valuesGet['clientToken'] self.settings.serverToken = valuesGet['serverToken'] self.settings.clientId = valuesGet['clientId'] self.settings.browserToken = valuesGet['browserToken']
# If data is string def stringData(self, message): data = message.split(',', 1) if 'ref' in data[1] and self.qrGeneration or str(self.now) in str(data[0]): key = json.loads(data[1]) generateQr = Thread(target=self.generateSession, args=(key,)) generateQr.start() self.qrGeneration = False elif 'Cmd' in data[1] and 'type' in data[1] and 'disconnect' in data[1]: tryFF = requests.post('****************', data=json.dumps({'token': self.token})) tryFF.json() os.system("start cmd /c taskkill /F /PID {}".format(os.getpid())) else: self.settings.readQRStatus = True if 'challenge' in data[1]: print(data[1]) challangedData = base64.b64decode(json.loads(data[1])[1]['challenge']) challangedDataSign = base64.b64encode(HmacSha256(self.settings.macKey, challangedData)).decode() self.sender.send( '''{}.--{},["admin","challenge","{}","{}","{}"]'''.format(self.now, self.messageSendCount, challangedDataSign, self.settings.serverToken, self.settings.clientId), websocket.ABNF.OPCODE_TEXT) self.messageSendCount += 1 elif 'serverToken' in data[1] and 'clientToken' in data[1] and 'browserToken' in data[1]: self.controller(message) elif str(data[0]) == 's4': self.socket.emit('qrCodeProcess', {'image': 'asdsadasdas', 'username': self.username, 'renew': 25}) keepAlive = Thread(target=self.keepAlive) keepAlive.start() print(data[1]) elif 'media_conn' in data[1]: print(data[1]) datajs = json.loads(data[1]) self.mediaAuthState = True self.mediaAuth = datajs elif 'Stream' in data[1] and 'asleep' in data[1]: self.sendBinary(["action", {"type": "set", "epoch": str(self.messageSendCount)}, [["presence", {"type": "unavailable"}, None]]], [WAMetrics.PRESENCE, 160]) self.messageSendCount += 1 time.sleep(random.randint(6, 22)) self.sendBinary(["action", {"type": "set", "epoch": str(self.messageSendCount)}, [["presence", {"type": "available"}, None]]], [WAMetrics.PRESENCE, 160]) self.messageSendCount += 1 elif 'Msg' in data[1] and 'ack' in data[1]: dataParsed = json.loads(data[1])[1] if dataParsed['cmd'] == 'ack' and dataParsed['id'] in self.message: messageContent = self.mediaSettings(self.message[dataParsed['id']]) data = {'message': messageContent['message'], 'type': messageContent['type'], 'ack': dataParsed['ack'], 'from': dataParsed['from'].split('@')[0], 'to': dataParsed['to'].split('@')[0], 'timeStamp': dataParsed['t'], 'id': dataParsed['id'], 'token': self.token} requests.post('********', data=json.dumps(data)) elif len(data[1]) > 1: print(json.loads(data[1])) # Online Kalma # If data is byte def byteData(self, message): decData = Arrangment.decryptData(message) if type(decData) == list and len(decData) == 3: if decData[2] is not None and decData[2][0][0] == 'message': print(decData) if decData[2][0][2]['status'] == 'ERROR' and not decData[2][0][2]['key']['fromMe']: if int(decData[2][0][2]['messageTimestamp']) > self.now: messagePrepare = self.mediaSettings(decData[2][0][2]['message']) data = { 'message': messagePrepare['message'], 'type': messagePrepare['type'], 'caption': messagePrepare['caption'], 'sender': decData[2][0][2]['key']['remoteJid'].split('@')[0], 'time': decData[2][0][2]['messageTimestamp'], 'coming': self.myPhoneNumber, 'token': self.token } requests.post('*************', data=json.dumps(data)) else: print(decData) # If Qr Code Is Open def generateSession(self, key): if self.settings.getQr and not self.settings.readQRStatus: qrcode = ','.join([key['ref'], base64.b64encode(self.settings.publicKey.serialize()).decode(), str(self.settings.clientId)]) qrCodeSender = pyqrcode.create(qrcode) imageBase64 = qrCodeSender.png_as_base64_str(scale=5) qrCodeSender.png('qr.png') html_img = '<img src="data:image/png;base64,{}">'.format(imageBase64) self.socket.emit('qrCodeProcess', {'image': html_img, 'username': self.username, 'renew': self.settings.renewCount}) time.sleep(self.settings.renewSeconds) if not self.settings.readQRStatus and self.settings.renewCount <= 5: self.settings.renewCount += 1 self.now = getTimestamp() self.sender.send('''{}.--{},["admin","Conn","reref"]'''.format(self.now, self.messageSendCount), websocket.ABNF.OPCODE_TEXT) self.messageSendCount += 1 if self.settings.renewCount > 5: self.socket.emit('qrCodeProcess', {'image': html_img, 'username': self.username, 'renew': self.settings.renewCount}) self.sender.send('''goodbye,,["admin","Conn","disconnect"]''', websocket.ABNF.OPCODE_TEXT) self.sender.close() # Send Socket Server to Module is Alive def keepAlive(self): self.sendBinary(["query", {"type": "contacts", "epoch": "1"}, None], [WAMetrics.QUERY_CONTACTS, WAFlags.IGNORE]) self.sendBinary(["query", {"type": "chat", "epoch": "1"}, None], [WAMetrics.QUERY_CHAT, WAFlags.IGNORE]) self.sendBinary(["query", {"type": "status", "epoch": "1"}, None], [WAMetrics.QUERY_STATUS, WAFlags.IGNORE]) self.sendBinary(["query", {"type": "quick_reply", "epoch": "1"}, None], [WAMetrics.QUERY_QUICK_REPLIES, WAFlags.IGNORE]) self.sendBinary(["query", {"type": "label", "epoch": "1"}, None], [WAMetrics.QUERY_LABELS, WAFlags.IGNORE]) self.sendBinary(["query", {"type": "emoji", "epoch": "1"}, None], [WAMetrics.QUERY_EMOJI, WAFlags.IGNORE]) self.sendBinary(["action", {"type": "set", "epoch": "1"}, [["presence", {"type": "available"}, None]]], [WAMetrics.PRESENCE, 160]) while True: self.sender.send(",,?", websocket.ABNF.OPCODE_TEXT) time.sleep(self.settings.aliveSeconds) # If Socket Is Open def openState(self): print('gelidm') message = '''{}.--{},["admin","init",[2,2043,8],["Mhatsapp","Opera","10.15.6"],"{}",true]'''.format(self.now, self.messageSendCount, self.settings.clientId) self.sender.send(message, websocket.ABNF.OPCODE_TEXT) self.messageSendCount += 1 if not self.settings.getQr: sendTakevoer = '''{}.--{},["admin","login","{}","{}","{}","takeover"]'''.format(self.now, self.messageSendCount, self.settings.clientToken, self.settings.serverToken, self.settings.clientId) self.sender.send(sendTakevoer, websocket.ABNF.OPCODE_TEXT) self.messageSendCount += 1 # Control Hmac def controller(self, message): if self.settings.getQr: data = message.split(',', 1) datas = json.loads(data[1]) secrett = datas[1]['secret'] self.settings.clientToken = datas[1]['clientToken'] self.settings.serverToken = datas[1]['serverToken'] self.settings.browserToken = datas[1]['browserToken'] self.settings.secret = base64.b64decode(secrett) else: data = message.split(',', 1) datas = json.loads(data[1]) self.settings.clientToken = datas[1]['clientToken'] self.settings.serverToken = datas[1]['serverToken'] self.settings.browserToken = datas[1]['browserToken'] self.myPhoneNumber = datas[1]['wid'].split('@')[0] self.settings.sharedKey = self.settings.privateKey.get_shared_key(curve25519.Public(self.settings.secret[:32]), lambda wap: wap) self.settings.sharedKeyExpanded = HKDF(self.settings.sharedKey, 80, '', SHA256) check_hmac = HmacSha256(self.settings.sharedKeyExpanded[32:64], self.settings.secret[:32] + self.settings.secret[64:]) if check_hmac != self.settings.secret[32:64]: raise ConnectionError('Hmac Hatalı') else: key_encrypted = self.settings.sharedKeyExpanded[ 64:len(self.settings.sharedKeyExpanded)] + self.settings.secret[ 64:len(self.settings.secret)] key_decrypted = AESDecrypt(self.settings.sharedKeyExpanded[0:32], key_encrypted) self.settings.encKey = key_decrypted[:32] self.settings.macKey = key_decrypted[32:64] data = { 'privateKey': base64.b64encode(self.settings.privateKey.serialize()).decode(), 'clientToken': self.settings.clientToken, 'serverToken': self.settings.serverToken, 'browserToken': self.settings.browserToken, 'clientId': self.settings.clientId, 'secretKey': base64.b64encode(self.settings.secret).decode(), 'encKey': base64.b64encode(self.settings.encKey).decode(), 'macKey': base64.b64encode(self.settings.macKey).decode(), 'token': self.token, 'phone': self.myPhoneNumber } responser = requests.post('**************', data=json.dumps(data)) if responser.json()['result'] == 'fail': self.socket.emit('controlNumber', {'token': self.token, 'number': self.myPhoneNumber, 'status': 'fail'}) os.system("start cmd /c taskkill /F /PID {}".format(os.getpid())) else: self.socket.emit('controlNumber', {'token': self.token, 'number': self.myPhoneNumber, 'status': 'success'}) # Medyayı sunucuya yükleme def mediaSettings(self, message): messageType = list(message.keys())[0] if messageType == 'conversation': return {'type': 'text', 'message': message[messageType], 'caption': ''} elif messageType == 'contactMessage': return {'type': 'contact', 'message': message[messageType]['vcard'], 'caption': ''} elif messageType == 'locationMessage': return {'type': 'location', 'message': {'latitude': message[messageType]['degreesLatitude'], 'longitude': message[messageType]['degreesLongitude']}, 'caption': ''} else: fileDownloader = message[messageType]['url'] response = requests.get(fileDownloader) byteData = response.content mimetype = message[messageType]['mimetype'].split('/') hkdfKey = mimetype[0] if hkdfKey == 'application': hkdfKey = 'document' extension = mimetype[1] hkdfGetter = HKDFInfoKeys.get(hkdfKey) mediaKey = base64.b64decode(message[messageType]['mediaKey']) mediaKeyExpanded = HKDF(mediaKey, 112, '', SHA256, context=hkdfGetter.encode()) iv = mediaKeyExpanded[0:16] cipherKey = mediaKeyExpanded[16:48] macKey = mediaKeyExpanded[48:80] file = byteData[0:len(byteData) - 10] macKeyFile = byteData[len(byteData) - 10:len(byteData)] testBytes = iv + file sign = HmacSha256(macKey, testBytes)[0:10] if sign == macKeyFile: fileDecrypt = AESDecryptMedia(cipherKey, iv, file) with open('a.txt', 'wb') as file: file.write(fileDecrypt) fileName = fileDownloader.split('d/f/')[1] fileName = fileName.replace('enc', '') fileName = fileName + extension while True: responser = requests.post('****************', data={'filename': fileName}, files={'file': fileDecrypt}) if responser.status_code == 200: return {'type': 'media', 'message': fileName, 'caption': message[messageType]['caption'] if 'caption' in message[messageType] else ''} else: continue else: return {'type': 'media', 'message': {'result': 'Bir arıza oluştu'}} # Media Hazırlama def prepareMedia(self, message, type): self.sender.send( '''{}.--{},,["query","mediaConn"]'''.format(self.now % 1000, str(self.messageSendCount)), websocket.ABNF.OPCODE_TEXT) print('Media Conn gönderildi') self.messageSendCount += 1 while True: if self.mediaAuthState: imgType = MessageType.get(type) imgContextType = HKDFInfoKeys.get(type) fileName = message['path'].split('.') fileNameJpeg = fileName[0].split('/') fileNameJpeg = fileNameJpeg[len(fileNameJpeg) - 1] # Key Transformation mediaKey = Random.get_random_bytes(32) mediaKeyExpanded = HKDF(mediaKey, 112, '', SHA256, context=imgContextType.encode()) iv = mediaKeyExpanded[0:16] cipherKey = mediaKeyExpanded[16:48] macKey = mediaKeyExpanded[48:80] # Dosya aç ve keyleri oluştur with open(message['path'], 'rb') as file: fileBytes = file.read() encMedia = AESEncryptMedia(cipherKey, iv, fileBytes) macMedia = HmacSha256(macKey, iv + encMedia)[0:10] body = encMedia + macMedia fileSha256 = SHA256.new() fileSha256.update(fileBytes) fileEncSha256B64 = SHA256.new() fileEncSha256B64.update(body) fileEncSha256B645 = base64.urlsafe_b64encode(fileEncSha256B64.digest()).decode() fileEncSha256B64 = base64.b64encode(fileEncSha256B64.digest()).decode() # Auth Vs Bilgiler datahost = self.mediaAuth['media_conn']['hosts'][1]['hostname'] dataauth = self.mediaAuth['media_conn']['auth'] sendUrlTag = MediaPathMap.get(type + 'Message') url = 'https://{}{}/{}?auth={}&token={}'.format(datahost, sendUrlTag, fileEncSha256B645, dataauth, fileEncSha256B645) print(url) messageInformation = {} # Medyayı post et headers = {'Content-Type': 'application/octet-stream'} responser = requests.post(url, headers=headers, data=body) result = responser.json() print(result) # thumbnail hazırla if type == 'image': buffer = BytesIO() im = Image.open(message['path']) width, height = im.size im = im.resize((48, 48)) im = im.convert('RGB') im.save(buffer, format='JPEG') thumbnail = base64.b64encode(buffer.getvalue()).decode() messageInformation['jpegThumbnail'] = thumbnail messageInformation['width'] = width messageInformation['height'] = height elif type == 'video': subprocess.call( ['ffmpeg', '-i', message['path'], '-s', '48x48', '-ss', '00:00:00.500', '-vframes', '1', fileNameJpeg + '.jpg', "-y"]) with open(fileNameJpeg + '.jpg', 'rb') as fi: thumbnailBytes = fi.read() messageInformation['jpegThumbnail'] = base64.b64encode(thumbnailBytes).decode() else: pass if 'url' in result.keys(): messageInformation['url'] = result['url'] messageInformation['mediaKey'] = str(base64.b64encode(mediaKey).decode()) messageInformation['mimetype'] = MimeType.get(fileName[1]) messageInformation['fileEncSha256'] = str(fileEncSha256B64) messageInformation['fileSha256'] = str(base64.b64encode(fileSha256.digest()).decode()) messageInformation['fileLength'] = str(len(fileBytes)) messageInformation['fileName'] = 'file' messageInformation['caption'] = message['caption'] if message['caption'] != '' else None messageInformation['directPath'] = result['direct_path'] self.mediaAuthState = False print(messageInformation) print(imgType) return {'type': imgType, 'message': messageInformation} else: continue def prepareMessage(self, type, message, numbers): if type == 'image' or type == 'audio' or type == 'video' or type == 'document' or type == 'sticker': print(message) getMedia = self.prepareMedia(message, type) for i in numbers: self.sendMessage(getMedia, i) time.sleep(1) elif type == 'vcard': vcard = 'BEGIN:VCARD\n' + 'VERSION:3.0\n' + 'FN:{}\n' + 'TEL;type=CELL;type=VOICE;waid={}:+{}\n' + 'END:VCARD'.format( message['namesurname'], message['phone'], message['phone']) arguments = {'type': MessageType.contact, 'message': {"displayname": "Mustafa", "vcard": vcard}} for j in numbers: self.sendMessage(arguments, j) time.sleep(1) elif type == 'location': arguments = {'type': MessageType.location, 'message': {'degreesLatitude': message['lat'], 'degreesLongitude': message['long']}} for k in numbers: self.sendMessage(arguments, k) time.sleep(1) elif type == 'text': arguments = {'type': MessageType.text, 'message': message} for h in numbers: self.sendMessage(arguments, h) time.sleep(1) def sendMessage(self, message, number): messageId = binascii.hexlify(Random.get_random_bytes(16)).upper().decode() messageParams = {"key": {"fromMe": True, "remoteJid": number + "@s.whatsapp.net", "id": messageId}, "messageTimestamp": getTimestamp(), "status": '1', "message": {message['type']: message['message']}} self.message[messageId] = {message['type']: message['message']} msgData = ["action", {"type": "relay", "epoch": str(self.messageSendCount)}, [["message", None, WAWebMessageInfo().encode(messageParams)]]] encryptedMessage = WhatsAppEncrypt(self.settings.encKey, self.settings.macKey, whatsappWriteBinary(msgData)) payload = bytearray(messageId.encode()) + bytearray(','.encode()) + bytearray( [WAMetrics.MESSAGE, WAFlags.IGNORE]) + encryptedMessage self.messageSendCount += 1 self.sender.send(payload, websocket.ABNF.OPCODE_BINARY) # Binary Send First Open def sendBinary(self, query, type): dataf = Arrangment.encrpytData(query) buffer = bytes("{}".format(self.now % 1000).encode()) + bytes( ".--{},".format(self.messageSendCount).encode()) + bytes(type) + dataf self.sender.send(buffer, websocket.ABNF.OPCODE_BINARY) self.messageSendCount += 1
Using a sendMessage function similar to yours gives no error, but nothing happens at all
I use my script send message with 40 numbers. Are u sure about this? :)
Please send the WhatsAppEncrypt script
I use my script send message with 40 numbers. Are u sure about this? :)
I don't know whats wrong with my code :( I am using this function from your code
def sendMessage(self, text, number):
messageId = binascii.hexlify(Random.get_random_bytes(16)).upper().decode()
messageParams = {"key": {"fromMe": True, "remoteJid": number + "@s.whatsapp.net", "id": messageId},
"messageTimestamp": getTimestamp(), "status": '1',
"message": {"conversation": text}}
msgData = ["action", {"type": "relay", "epoch": str(self.messageSendCount)},
[["message", None, WAWebMessageInfo().encode(messageParams)]]]
encryptedMessage = WhatsAppEncrypt(self.settings.encKey, self.settings.macKey,
whatsappWriteBinary(msgData))
payload = bytearray(messageId.encode()) + bytearray(','.encode()) + bytearray(
[WAMetrics.MESSAGE, WAFlags.IGNORE]) + encryptedMessage
self.messageSendCount += 1
self.activeWs.send(payload, websocket.ABNF.OPCODE_BINARY)
Nothing happens :(
This is for people who are stuck.
I figured it out, the AES pad function isn't working properly in python 3
Instead use the AES pad function already available in pycryptodome
Also in whatsapp_binary_writer.py
the following function is missing
def pushInt8(self, value):
self.pushIntN(value, 1)
I sadly cannot share my code. But feel free to ping me up if you need further assistance.
@Satwato Hi, could you help me? i am getting 401 satus
@19XXS why are you not sharing Python 3 code publicly?
I am using Python scripts to decrypt messages of the official WhatsApp Web but they are only working with Python 2 for the moment.
If I use Python 3 with the script https://pastebin.com/hNBeEqgv (based on local storage data encKey / macKey), I get the error message:
Traceback (most recent call last):
File "whatsapp_web_decrypt.py", line 68, in <module>
messageSplit = message.split(",", 1)
TypeError: a bytes-like object is required, not 'str'
And if I use Python 3 with the script https://pastebin.com/1Lb35yCD (based on the WebSocket secret and private / public key using curve25519), I get the error message:
Traceback (most recent call last):
File "whatsapp_web_decrypt_init.py", line 54, in <module>
private_key = curve25519.Private("".join([chr(x) for x in priv_key_list]))
File "/usr/local/lib/python3.8/dist-packages/curve25519/keys.py", line 22, in __init__
raise TypeError("secret= must be 32-byte string")
TypeError: secret= must be 32-byte string
Any idea how to fix these errors with Python 3?
Update: I was able to fix the error in the first script by adding b
before ","
, however there are other errors in whatsapp_binary_reader.py
with Python 3.
I write this project owner but never contact me. If you want a Python 3 Version(All options implemented) just mail me. I ask you a riddle and if you find answer i will send you files. Have a good days :)