Here is the schema :
[ 0000] 1B 1B 00 08 00 65 00 00 00 11 00 00
Format
[ 0000] 1B 1B : Version
[ 0002] 00 08 : Size
[ 0004] 00 65 : Message Type
[ 0006] 00 00 : Unknow
[ 0008] 00 11 : Version Client ?(0x11)
[ 000A] 00 00 : Unknow_02
All the further communications will be encrypted using a rc4 key generated by the client :
v0 = 0;
do
key[v0++] = rand();
while ( v0 < 59 );
This key is then RSA encrypted and exchanged with the server.DAOC client (client.dll), use a old version of libtomcrypt, here is an implementation of the code used for generating the buffer used to send the rc4 key to the server.
unsigned char daoc_pub[] =
{
0x91, 0x00, 0x00, 0x00, 0x01, 0xC1, 0x00, 0x00, 0x00, 0x02, 0x15, 0xB3,
0x4E, 0xAF, 0x3A, 0x93, 0xA3, 0xC7, 0x4A, 0x6A, 0xFD, 0x69, 0x55, 0x45,
0x1D, 0x38, 0x6A, 0x8D, 0xA1, 0xDF, 0x70, 0x1F, 0x84, 0x93, 0x23, 0xE7,
0x95, 0x7F, 0xFD, 0xC5, 0x78, 0xCD, 0x42, 0x58, 0x71, 0x6B, 0xA4, 0xB5,
0x4D, 0xDD, 0xF1, 0xC6, 0xB9, 0xAE, 0xF2, 0x41, 0x65, 0xF7, 0xD9, 0x4D,
0x9C, 0xC5, 0xD6, 0xEE, 0x0D, 0x98, 0xFC, 0x23, 0x7E, 0x94, 0x84, 0xE2,
0xD1, 0x27, 0x8C, 0x67, 0xFC, 0xB6, 0x2C, 0x5D, 0xD6, 0x60, 0xA6, 0xA9,
0xC3, 0xA5, 0x04, 0x11, 0xFF, 0xFE, 0x9B, 0x90, 0x27, 0x69, 0x6A, 0x60,
0x1D, 0x89, 0x6F, 0xFD, 0x55, 0x96, 0x4A, 0xEA, 0x97, 0x34, 0x8F, 0x69,
0x79, 0xBF, 0x93, 0x26, 0x18, 0xB4, 0x7C, 0x7C, 0xD5, 0xAD, 0x0B, 0xC9,
0xC5, 0xB7, 0x8F, 0x06, 0xB4, 0x37, 0x67, 0x94, 0xE0, 0x2A, 0x7E, 0x38,
0x2F, 0x28, 0x60, 0x8A, 0xDC, 0x89, 0x7D, 0x08, 0xDD, 0xBE, 0x38, 0x34,
0xF5, 0x78, 0xD8, 0x81, 0x58, 0x9C, 0x2B, 0x03, 0x1A, 0xE0, 0xE3, 0xF3,
0x19, 0xE3, 0x63, 0x81, 0xE3, 0x7C, 0xE0, 0x5D, 0xBC, 0x8E, 0x9C, 0xDC,
0x93, 0x74, 0x24, 0xE0, 0xF4, 0x96, 0x65, 0xFA, 0x90, 0x21, 0x06, 0x03,
0xD2, 0x5A, 0xC3, 0x51, 0xBF, 0x5D, 0x03, 0xB2, 0xCD, 0xD3, 0xF1, 0x6E,
0xCB, 0xB0, 0x25, 0x71, 0x4B, 0xC6, 0x00, 0x44, 0x7A, 0xE7, 0x03, 0x00,
0x00, 0x00, 0x01, 0x00, 0x01
};
void daoc_rsa_encrypt_key(unsigned char *buf, int inlen,
unsigned char *output, unsigned long *outlen)
{
rsa_key key;
int prng_idx;
prng_state statesprng;
int res;
unsigned char rsa_in[196];
unsigned long y, rsa_size;
if (rsa_import(daoc_pub, sizeof (daoc_pub), &key) != CRYPT_OK)
{
fprintf(stderr, "[-] rsa_import() failed\n");
exit(EXIT_FAILURE);
}
prng_idx = find_prng("sprng");
if (prng_idx == -1)
{
fprintf(stderr, "[-] find_prng() failed\n");
exit(EXIT_FAILURE);
}
y = 193;
res = rsa_pad(buf, inlen, rsa_in, &y, prng_idx, &statesprng);
if (res != CRYPT_OK)
{
fprintf(stderr, "[-] rsa_pad() failed : %d\n", res);
exit(EXIT_FAILURE);
}
rsa_size = *outlen - 2;
res = rsa_exptmod(rsa_in, y, output + 2, &rsa_size, PK_PUBLIC, &key);
if (res != CRYPT_OK)
{
fprintf(stderr, "[-] rsa_exptmod() failed : %d\n", res);
exit(EXIT_FAILURE);
}
*output = 0;
*(output + 1) = rsa_size;
*outlen = rsa_size + 2;
}
The client will send the rc4 key block encrypted with rsa, with the following type of packet :
[ 0000] 1B 1B : Version
[ 0002] 00 C7 : Size
[ 0004] 01 54 : Message Type (ROL8(340))
[ 0006] 00 : Checksum (NULL because sym key is not yet set)
[ 0007] 00 : Sequence number of the paquet
[ 0008] 00 C1 : Size encrypted RSA key
[ 000A] XX XX : RSA encrypted key
...
Then the client can communicate the credentials of the user using the following paquet : [ 0000] 1B 1B : Version
[ 0002] 00 1D : Size
[ 0004] 01 2C : Message Type (ROL8(300))
[ 0006] 21 : Checksum
[ 0007] 01 : Sequence number of the paquet
[ 0008] 00 06 : Name Size
[ 000A] XX XX : Str_Name[Name Size]
[ 00XX] 00 02 : Password Size
[ 00XX] XX XX : Str_Password[Password Size]
[ 00XX] 00 09 : Unknow
[ 00XX] 00 : Unknow_02
This paquet will be encrypted using rc4 algorithm and the key generated, but not on all paquet ! It will start at position 0x0006.