Saturday, July 13, 2013

Dark Age of Camelot : Connection

Today I wanted to understand the protocol for sending credentials to Dark Age of Camelot server.
Here is the schema :

When a client connect on a DAOC server, he will receive the following packet :
 [  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.

Creating library signatures for IDA

 C:\ida\flair61\bin\win>pcf tomcrypt.lib  
 tomcrypt.lib: skipped 25, total 566  
 C:\ida\flair61\bin\win>sigmake.exe tomcrypt.pat tomcrypt  
 tomcrypt.sig: modules/leaves: 541/485, COLLISIONS: 3  
 See the documentation to learn how to resolve collisions.  
Resolve collisions and it's ok (collisions problems can be found in file *.exc)

Thursday, July 11, 2013

IDA : Add structur

Declaring field of structure when they are big is a pain in the ass into IDA, idapython to the rescue !
 name = "WHATEVERYOUWANT"  
 size = 4242  
 struc_id = GetStrucIdByName(name)  
 DelStruc(struc_id)  
 struct = AddStrucEx(-1, name, 0)  
 for i in xrange(0, size / 4):  
      AddStrucMember(struct, "field_" + str(i), i * 4, 0x20000400, -1, 4)  
 if (size % 4) != 0:  
      AddStrucMember(struct,"field_" + str(size / 4),(size / 4) * 4,0x000400,-1,size % 4)  

Wednesday, July 10, 2013

Age Of Empires III : Resources anti-cheat

If one day, you try to scan the memory of age3.exe for finding your resources like wood, or food, you will not find them in memory, because they use a lame "anti-cheat" technique.
All the value are xored with those different "secret" dword :
 .data:00BBE74C Key_XOR_Resources dd 2848AC4Fh            ; // GOLD  
 .data:00BBE750         dd 94F83A35h      ; // WOOD  
 .data:00BBE754         dd 8BD84C3Fh      ; // meat  
 .data:00BBE758         dd 0AB12FBAFh     ; ??
 .data:00BBE75C         dd 20B35BCAh      ; ??
 .data:00BBE760         dd 0F9ABC42Ah     ; // XP  
 .data:00BBE764         dd 0B1A1CFDAh     ; // LEVEL  
 .data:00BBE768         dd 0F2E48210h