Ok, people who are interested in getting the job done, this is the thread to ask questions. I will assist with code problems in any language provided they're on this topic, but if you can't code, don't bother.
Any code I post here will be generic, and not based on any specific source releases, so don't expect to just plug it in and run it. You'll need to modify, or encapsulate the code into something that works with your server.
I'll explain the process, with some sample code, then answer any questions you have.
Ok, so firstly, you have an account server that is largely unmodified, except the recent clients use a new login packet, which I'm not going to go into detail with, you can figure it out yourself. The encryption of packets to the login server remains unchanged from before client V5018.
The main change is the protocol when connecting to the game server, where packets are received in a different order, and the encryption is no longer the same. The encryption now used is Blowfish, with an initial key of
"DR654dt34trg4UI6", and initialization vectors with all bits initially
unset. This setup is used to decrypt both the first packet received from the server, and the first from the client. Afterwards, blowfish then uses a different key and different initialization vectors.
So in C#, something like this (I've not tested it)
To use this code, you need to have the
[Only registered and activated users can see links. Click Here To Register...] wrapper. In your project, you can add a reference to
openssl-net/bin/release/ManagedOpenSsl.dll
Edit: C# Code updated on Pg 2 [Only registered and activated users can see links. Click Here To Register...] - Now tested and confirmed working
C++ code (Tested and working)
Code:
#include <stdint.h>
#include <openssl/blowfish.h>
class game_crypt
{
private:
BF_KEY* m_bf_schedule;
uint8_t m_enc_ivec[8];
uint8_t m_dec_ivec[8];
int m_enc_num;
int m_dec_num;
protected:
public:
game_crypt();
virtual ~game_crypt();
void set_key(const uint8_t* key, int len);
void set_enc_ivec(const uint8_t* data, int);
void set_dec_ivec(const uint8_t* data, int);
void encrypt(byte_buffer* in, byte_buffer* out);
void decrypt(byte_buffer* in, byte_buffer* out);
};
game_crypt::game_crypt()
{
m_bf_schedule = new BF_KEY;
BF_set_key(m_bf_schedule, 16, (uint8_t*)"DR654dt34trg4UI6");
m_enc_num = 0; m_dec_num = 0;
memset(m_enc_ivec, '\0', 8);
memset(m_dec_ivec, '\0', 8);
}
game_crypt::~game_crypt()
{
delete m_bf_schedule;
}
void game_crypt::set_key(const uint8_t* key, int len)
{
BF_set_key(m_bf_schedule, len, key);
m_enc_num=0; m_dec_num=0;
}
void game_crypt::set_enc_ivec(const uint8_t* data, int len)
{
memcpy(m_enc_ivec, data, 8);
}
void game_crypt::set_dec_ivec(const uint8_t* data, int len)
{
memcpy(m_dec_ivec, data, 8);
}
void game_crypt::encrypt(byte_buffer* in, byte_buffer* out)
{
BF_cfb64_encrypt(in->buffer(), out->buffer(), in->length(), m_bf_schedule, m_enc_ivec, &m_enc_num, 1);
}
void game_crypt::decrypt(byte_buffer* in, byte_buffer* out)
{
BF_cfb64_encrypt(in->buffer(), out->buffer(), in->length(), m_bf_schedule, m_dec_ivec, &m_dec_num, 0);
}
Instantiate the GameProtocolCrypto Class, as you would've done previously for the crypto classes on older client versions. Decrypt and Encrypt are used in the same way on received packets.
I'll post more when people manage to get this much working. You'll know when it's working if you can successfully decrypt the first server and client packets, which will be noticable by the long hex strings they contain.
Note though, that these two packets follow a different format compared to all the other packets on CO. There is no 16bit length, 16bit type.