Reputation: 17
I am working on scripting a player bot for my private AC server in python. I have worked my way through SRP6 authentication through the acore auth server and through the first couple of world server packets.
When I receive the SMSG_AUTH_RESPONSE packet I am correctly decrypting and receiving 0x1EE as the opcode. However, when I try to decrypt the header for SMSG_CHAR_ENUM it fails. I can see the username in the packet so I know that the packet is correct.
I have tried pushing extra bytes through the decryptor (up to 2024) to see if it was a sync issue but no luck. I have also tried re-initializing the ARC4 cipher with the same session key between decryptions and no luck. After looking through the documentation in the azerothcore repo I am unable to come to a conclusion for why this is failing.
Here is the function for reading the world packets and decrypting the header.
def data_received(self, data):
self.remaining = -1
if len(data) < self.HEADER_SIZE_INCOMING:
self.logger.debug(f"Received partial header: {data}")
# Not enough data for a header
return
header = data[:self.HEADER_SIZE_INCOMING]
data = data[self.HEADER_SIZE_INCOMING:]
if self.arc4_decryptor:
header = self.arc4_decryptor.decrypt(header)
self.remaining = int.from_bytes(header[:2], "big")
size = self.remaining
data_size = size - self.OPCODE_SIZE_INCOMING
# Check if we have enough data for the remaining packet
if self.remaining > 0 and len(data) >= data_size:
opcode = int.from_bytes(header[2:], "little")
if opcode in gameopcodes.values():
self.logger.debug(f"Received {opcode_names[opcode]}")
return data
elif self.remaining != 0:
self.logger.debug(f"couldn't decrypt: {header}")
Here is the ARC4 implementation:
# https://github.com/timelostprototype/wow-client/blob/92e45a4eeb9008b225d55568322056ac7908a275/src/common/crypto/arc4.ts
from Crypto.Cipher import ARC4
from Crypto.Hash import HMAC, SHA1
class Arc4:
ENCRYPTION_KEY = bytes.fromhex("C2B3723CC6AED9B5343C53EE2F4367CE")
DECRYPTION_KEY = bytes.fromhex("CC98AE04E897EACA12DDC09342915357")
def __init__(self, key):
# Assuming key is a bytes-like object
self.key = key
self.enc_key = self.hash_key(self.ENCRYPTION_KEY, key)
self.dec_key = self.hash_key(self.DECRYPTION_KEY, key)
self.enc_cipher = ARC4.new(self.enc_key)
self.dec_cipher = ARC4.new(self.dec_key)
# Arc4-drop1024 synchronization
sync_data = bytes([0] * 1024)
self.enc_cipher.encrypt(sync_data)
self.dec_cipher.encrypt(sync_data)
def encrypt(self, data):
return self.enc_cipher.encrypt(data)
def decrypt(self, data):
return self.dec_cipher.decrypt(data)
@staticmethod
def hash_key(key, data_key):
return HMAC.new(key, data_key, SHA1).digest()
I am expecting this function to return the packet data when it matches the opcode for SMSG_CHAR_ENUM (0x03B)
Upvotes: 0
Views: 125
Reputation: 17
The issue ended up being a few different things.
The solution ended up being to re-write the function to decrypt the header, check the length of the message, consume those bytes, and repeat until the entire packet is consumed.
Upvotes: 0