Skip to content

Commit

Permalink
try to fix LegacyServerPacketHeader
Browse files Browse the repository at this point in the history
  • Loading branch information
zz committed Dec 5, 2023
1 parent 68e99d4 commit a7b3e7b
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 36 deletions.
147 changes: 118 additions & 29 deletions HermesProxy/World/Client/LegacyWorldCrypt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,17 @@ public class TbcWorldCrypt : LegacyWorldCrypt

public void Initialize(byte[] sessionKey)
{
/*
case BUILD_243:
{
_send_i = _send_j = _recv_i = _recv_j = 0;
static uint8 seed[SEED_KEY_SIZE] = { 0x38, 0xA7, 0x83, 0x15, 0xF8, 0x92, 0x25, 0x30, 0x71, 0x98, 0x67, 0xB1, 0x8C, 0x4, 0xE2, 0xAA };
_key = Trinity::Crypto::HMAC_SHA1::GetDigestOf(seed, K);
break;
}
*/
byte[] recvSeed = new byte[16] { 0x38, 0xA7, 0x83, 0x15, 0xF8, 0x92, 0x25, 0x30, 0x71, 0x98, 0x67, 0xB1, 0x8C, 0x4, 0xE2, 0xAA };
HmacHash recvHash = new HmacHash(recvSeed);
recvHash.Finish(sessionKey, sessionKey.Count());
Expand Down Expand Up @@ -130,49 +141,127 @@ public class WlkWorldCrypt : LegacyWorldCrypt

public void Initialize(byte[] sessionKey)
{
byte[] recvSeed = new byte[16] { 0xBA, 0xA3, 0x1E, 0x99, 0xA0, 0x0B, 0x21, 0x57, 0xFC, 0x37, 0x3F, 0xB3, 0x69, 0xCD, 0xD2, 0xF1 };
HmacHash recvHash = new HmacHash(recvSeed);
recvHash.Finish(sessionKey, sessionKey.Count());
m_key = recvHash.Digest.ToArray();

m_send_i = m_send_j = m_recv_i = m_recv_j = 0;
/*
AuthCrypt::AuthCrypt(ClientBuild build) :
_initialized(false), clientBuild(build)
{ }
void AuthCrypt::Init(SessionKey const& K)
{
switch(clientBuild)
{
#ifdef LICH_KING_CLIENT
case BUILD_335:
{
_serverEncrypt = std::make_unique<Trinity::Crypto::ARC4>();
_clientDecrypt = std::make_unique<Trinity::Crypto::ARC4>();
static uint8 ServerEncryptionKey[SEED_KEY_SIZE] = { 0xCC, 0x98, 0xAE, 0x04, 0xE8, 0x97, 0xEA, 0xCA, 0x12, 0xDD, 0xC0, 0x93, 0x42, 0x91, 0x53, 0x57 };
_serverEncrypt->Init(Trinity::Crypto::HMAC_SHA1::GetDigestOf(ServerEncryptionKey, K));
static uint8 ServerDecryptionKey[SEED_KEY_SIZE] = { 0xC2, 0xB3, 0x72, 0x3C, 0xC6, 0xAE, 0xD9, 0xB5, 0x34, 0x3C, 0x53, 0xEE, 0x2F, 0x43, 0x67, 0xCE };
_clientDecrypt->Init(Trinity::Crypto::HMAC_SHA1::GetDigestOf(ServerDecryptionKey, K));
// Drop first 1024 bytes, as WoW uses ARC4-drop1024.
std::array<uint8, 1024> syncBuf;
_serverEncrypt->UpdateData(syncBuf);
_clientDecrypt->UpdateData(syncBuf);
_initialized = true;
break;
}
#else
case BUILD_243:
{
_send_i = _send_j = _recv_i = _recv_j = 0;
static uint8 seed[SEED_KEY_SIZE] = { 0x38, 0xA7, 0x83, 0x15, 0xF8, 0x92, 0x25, 0x30, 0x71, 0x98, 0x67, 0xB1, 0x8C, 0x4, 0xE2, 0xAA };
_key = Trinity::Crypto::HMAC_SHA1::GetDigestOf(seed, K);
break;
}
#endif
default:
TC_LOG_ERROR("network", "AuthCrypt::Init, wrong build %u given, cannot initialize", uint32(clientBuild));
return;
}
_initialized = true;
}
void AuthCrypt::DecryptRecv(uint8* data, size_t len)
{
ASSERT(_initialized);
#ifdef LICH_KING_CLIENT
_clientDecrypt->UpdateData(data, len);
#else
if (len < CRYPTED_SEND_LEN)
return;
for (size_t t = 0; t < CRYPTED_RECV_LEN; t++)
{
_recv_i %= _key.size();
uint8 x = uint8((data[t] - _recv_j) ^ _key[_recv_i]); // calc can overflow uint8, seems to work though
++_recv_i;
_recv_j = data[t];
data[t] = x;
}
#endif
}
void AuthCrypt::EncryptSend(uint8 *data, size_t len)
{
ASSERT(_initialized);
#ifdef LICH_KING_CLIENT
_serverEncrypt->UpdateData(data, len);
#else
if (len < CRYPTED_SEND_LEN)
return;
for (size_t t = 0; t < CRYPTED_SEND_LEN; t++)
{
_send_i %= _key.size();
uint8 x = uint8((data[t] ^ _key[_send_i]) + _send_j); // calc can overflow uint8, seems to work though
++_send_i;
data[t] = _send_j = x;
}
#endif
}
*/

byte[] ServerEncryptionKey = new byte[16] { 0xCC, 0x98, 0xAE, 0x04, 0xE8, 0x97, 0xEA, 0xCA, 0x12, 0xDD, 0xC0, 0x93, 0x42, 0x91, 0x53, 0x57 };
_serverEncrypt = new SARC4();
_serverEncrypt.PrepareKey(ServerEncryptionKey);
byte[] ServerDecryptionKey = new byte[16] { 0xC2, 0xB3, 0x72, 0x3C, 0xC6, 0xAE, 0xD9, 0xB5, 0x34, 0x3C, 0x53, 0xEE, 0x2F, 0x43, 0x67, 0xCE };
_clientDecrypt = new SARC4();
_clientDecrypt.PrepareKey(ServerDecryptionKey);

byte[] syncBuf = new byte[1024];
_serverEncrypt.ProcessBuffer(syncBuf,1024);
_clientDecrypt.ProcessBuffer(syncBuf, 1024);


m_isInitialized = true;
}

public void Decrypt(byte[] data, int len)
{
if (len < CRYPTED_RECV_LEN)
return;

for (byte t = 0; t < CRYPTED_RECV_LEN; t++)
{
m_recv_i %= (byte)m_key.Count();
byte x = (byte)((data[t] - m_recv_j) ^ m_key[m_recv_i]);
++m_recv_i;
m_recv_j = data[t];
data[t] = x;
}
_clientDecrypt.ProcessBuffer(data, len);
}

public void Encrypt(byte[] data, int len)
{
if (!m_isInitialized)
return;

if (len < CRYPTED_SEND_LEN)
return;

for (byte t = 0; t < CRYPTED_SEND_LEN; t++)
{
m_send_i %= (byte)m_key.Count();
byte x = (byte)((data[t] ^ m_key[m_send_i]) + m_send_j);
++m_send_i;
data[t] = m_send_j = x;
}
_serverEncrypt.ProcessBuffer(data, len);
}

byte[] m_key;
byte m_send_i, m_send_j, m_recv_i, m_recv_j;
bool m_isInitialized;

SARC4 _clientDecrypt;
SARC4 _serverEncrypt;
}
}
4 changes: 2 additions & 2 deletions HermesProxy/World/Client/WorldClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ private async Task ReceiveLoop()

LegacyServerPacketHeader header = new LegacyServerPacketHeader();
header.Read(headerBuffer);
ushort packetSize = header.Size;
uint packetSize = header.Size;

if (packetSize != 0)
{
Expand Down Expand Up @@ -444,7 +444,7 @@ public void SendAuthResponse(uint clientSeed, uint serverSeed)
if (Settings.ServerBuild >= ClientVersionBuild.V3_0_2_9056)
packet.WriteUInt32(zero); // LoginServerType

packet.WriteUInt32(clientSeed);
packet.WriteUInt32(clientSeed); //recvPacket.read(authSession->LocalChallenge); std::array<uint8, 4>

if (Settings.ServerBuild >= ClientVersionBuild.V3_3_5_12340)
{
Expand Down
57 changes: 52 additions & 5 deletions HermesProxy/World/Packet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -338,22 +338,69 @@ public void Write(ByteBuffer byteBuffer)
public bool IsValidSize() { return Size < 0x40000; }
}

/*
struct ServerPktHeader
* size is the length of the payload _plus_ the length of the opcode
ServerPktHeader(uint32 size, uint16 cmd) : size(size)
{
uint8 headerIndex = 0;
if (isLargePacket())
{
LOG_DEBUG("network", "initializing large server to client packet. Size: {}, cmd: {}", size, cmd);
header[headerIndex++] = 0x80 | (0xFF & (size >> 16));
}
header[headerIndex++] = 0xFF & (size >> 8);
header[headerIndex++] = 0xFF & size;
header[headerIndex++] = 0xFF & cmd;
header[headerIndex++] = 0xFF & (cmd >> 8);
}
uint8 getHeaderLength()
{
// cmd = 2 bytes, size= 2||3bytes
return 2 + (isLargePacket() ? 3 : 2);
}
bool isLargePacket() const
{
return size > 0x7FFF;
}
const uint32 size;
uint8 header[5];
};
*/
public class LegacyServerPacketHeader
{
public const int StructSize = sizeof(ushort) + sizeof(ushort);
public ushort Size;
public const int StructSize = sizeof(uint) + sizeof(ushort);
public uint Size;
public ushort Opcode;
public void Read(byte[] buffer)
{
Size = Framework.Util.NetworkUtility.EndianConvert(BitConverter.ToUInt16(buffer, 0));
Size = Framework.Util.NetworkUtility.EndianConvert(BitConverter.ToUInt32(buffer, 0));
Opcode = BitConverter.ToUInt16(buffer, sizeof(ushort));
}
public void Write(ByteBuffer byteBuffer)
{
byteBuffer.WriteUInt16(Size);
byteBuffer.WriteUInt32(Size);
byteBuffer.WriteUInt16(Opcode);
}
};

int getHeaderLength()
{
// cmd = 2 bytes, size= 2||3bytes
return 2 + (isLargePacket() ? 3 : 2);
}

bool isLargePacket()
{
return Size > 0x7FFF;
}
};

public class LegacyClientPacketHeader
{
Expand Down
1 change: 1 addition & 0 deletions HermesProxy/World/Server/WorldSocket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,7 @@ void HandleAuthSessionCallback(AuthSession authSession)

_realmId = new RealmId((byte)authSession.RegionID, (byte)authSession.BattlegroupID, authSession.RealmID);
GetSession().WorldClient = new Client.WorldClient();

if (!GetSession().WorldClient.ConnectToWorldServer(GetSession().RealmManager.GetRealm(_realmId), GetSession()))
{
SendAuthResponseError(BattlenetRpcErrorCode.BadServer);
Expand Down

0 comments on commit a7b3e7b

Please sign in to comment.