Из сборника документаций ILINE(посвященные ICQ)

РЕЖИМ ЦВЕТОЧЕК II

[blue shift code of the red dump]

_/ \_/ \ / \>--o--<\_/ \_/             \I/C D A PROJECTbest regars from payhash [aolhackers.ru]

 Ну, вот, друзья мои, спустя, почти, два года, наконец, то у меня появилось время и желание на вторую часть этой эпопеи с разбором работы ICQ протокола. Этим мы должны быть благодарны K.SUN и William Wallace (WW) низкий им поклон и респект.

Согласно первой части статьи вы уже умеете подключаться и проходить авторизацию на сервере ICQ. Что бы закрепить материал из первой статьи попробуем кое-что решить практически. Хочу вас предупредить – я не сильный специалист в области программирования и поэтому сразу же прошу вас не ругать за некоторые формальности и недочеты, так как я уже устал от того что в мой адрес летят возмущения и указывания на мои ошибки в моем коде. Мне честно наплевать на то, что у меня что то не правильно и не так работает, каждый пишет код так как ему хочется да и вообще если вам что то не нравится, можете не читать эту статью и валить пить пиво.

Смысл этой статьи - не научить вас программировать, а показать вам как, работать с ICQ протоколом  (в противном случи вам прямая дорога к Кернигану и Ричи). Так же прошу не доставать всякими вопросами типа у меня, что-то не работает, помогите разобраться с кодом – честно у меня нет на это времени и желание разбираться в чих то дебрях (я лутче потрачу это время на TETRIS).  Многие вещи я не буду коментировать так как материал довольно сложный и все подписывать я просто не всилах. Поэтрому вам придется самостоятельно что то понимать.

            И так сразу приступим к делу. Возьмем исходные коды программы ICQKID (www.icqkid.com) и распотрошим его содержимое. Еще раз рассмотрим авторизацию на сервере ICQ:

1) Подключаемся к серверу ICQ

if((he = gethostbyname(loginserver)) == NULL)
{
return 10;
}
loginhost.sin_family = AF_INET;
loginhost.sin_port = htons(icqport);
loginhost.sin_addr = *((structin_addr*)he->h_addr);
//bzero(&(loginhost.sin_zero), 8);
if((icqhandle=socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
return 11;
}
if((connect(icqhandle, (struct sockaddr *)&loginhost, sizeof(struct sockaddr))) == -1)
{return 12;}
> //RECIVE FIRSTE FLAP FROM LOGIN SERVER
memset(buffer, 0, 1024);
//printf("RECEVING DATA FROM REMOTE HOST\n");
if(recv(icqhandle, buffer, 1024, 0) == -1)
{
return 13;
}
/*
здесь можно сделать проверку на наличие первого пакета с ICQ сервера
2A 01 7E BF 00 04 00 00 00 01
*/
buf=(char *)malloc(131 * sizeof(char ));
//LOGIN PACK
//В функцию логин передаем три аргумента указатель на буфер ICQ uin и ICQ пароль.
encode_login(buf, uin, passwd);

-----------------------------------------------------------------------------------------------------------------------------------------------------------

 

  

Функция для формирования пакета Login:

-----------------------------------------------------------------------------------------------------------------------------------------------------------

//PAK LOGIN

 

 //Encode Login

 static char *encode_login(char *buf, const char *uin, const char *passwd)

 {

  int uin_len = strlen(uin);                                                       // Подсчитываем длину ICQ номера

  char *tlv, *flap;                                                         // Объявляем указатели на TLV и FLAP пакеты

  buf = flap = flap_begin(buf, 1);                                // Начинаем заполнять FLAP заголовок

  buf = writel(buf, 0x0000001);                                    //Номер версии протокола

  buf = tlv_write(buf, 0x01, uin, uin_len);                  /* TLV 01: 00 01 говорит сервису, что идут   данные с  UIN,  перед самим uin идет размер uin */

  buf = tlv = tlv_begin(buf, 0x02);                                /* TLV 02 пароль */

  buf = encode_passwd(buf, passwd);                         // Криптуем парль от нашего UIN

  tlv_end(buf, tlv);                                                     // Записываем длину пароля

/* Дальше идут мусорные данные, можете их изменять на     свое усмотрение */

  buf = tlv_write(buf, 0x03, STR("icq"));

  buf = tlv_write(buf, 0x16, STR("\x01\x0a"));

  buf = tlv_write(buf, 0x17, STR("\x00\x04"));

  buf = tlv_write(buf, 0x18, STR("\x00\x3c"));

  buf = tlv_write(buf, 0x19, STR("\x00\x01"));

  buf = tlv_write(buf, 0x1A, STR("\x0c\x0e"));

  buf = tlv_write(buf, 0x14, STR("\x00\x00\x00\x55"));

  buf = tlv_write(buf, 0x0E, STR("us"));

  buf = tlv_write(buf, 0x0F, STR("en"));            

                                                                                          /* Заканчиваем запись мусорных данных */      

  tlv_end(buf, flap);                                                   // Подсчет количества байт в пакете Login

  return buf;

 }

-----------------------------------------------------------------------------------------------------------------------------------------------------------

Функция по шифрованию пароля от UIN:
-----------------------------------------------------------------------------------------------------------------------------------------------------------

i=*((WORD *)(buf+5));
//SEND LOGIN PACK
if(send(icqhandle, buf, i+6, 0) == -1){
return 14;
}
//Высвобождаем память выделенную под переменную buf
free(buf);

-----------------------------------------------------------------------------------------------------------------------------------------------------------

 Вот дамп пакета login:

дамп #1

2A 01 11 53 00 83 00 00 00 01 00 01 00 06 3X 3X3X 3X 3X 3X 00 02 00 08 XX XX XX XX XX XX XX XX00 03 00 33 49 43 51 20 49 6E 63 2E 20 2D 20 5072 6F 64 75 63 74 20 6F 66 20 49 43 51 20 28 544D 29 2E 32 30 30 33 61 2E 35 2E 34 37 2E 31 2E33 38 30 30 2E 38 35 00 16 00 02 01 0A 00 17 0002 00 05 00 18 00 02 00 2F 00 19 00 02 00 01 001A 00 02 0E D8 00 14 00 04 00 00 00 55 00 0F 0002 65 6E 00 0E 00 02 75 73

Согласно первой части статьи РЕЖИМ ЦВЕТОЧЕК при условии того, что вы правильно указали UIN и пароль (ну и с условием того что вы грамотно подделали пакет login), сервер авторизации ICQ вам должен вернуть FLAP -  результат которого должен содержать следующие данные: UIN, IPserver:PORT, COOKIE (256 байт случайных данных).

Дамп пакета должен выглядеть следующим образом:Дамп #22A 04 C6 B5 01 21 00 01 00 06 3X 3X 3X 3X 3X 3X00 05 00 0F 32 30 35 2E 31 38 38 2E 38 2E 31 383A 35 33 00 06 01 00 35 A3 D2 E6 D5 A2 75 F1 9F2E C0 78 8C 78 D8 AA 10 B7 60 42 10 44 27 9A 58E9 12 24 CD E9 4C F0 51 06 BD 86 2E A4 86 CF 1E9B 21 AC FE 8F EE BF 16 B6 94 8D 50 58 35 5F CD1E 8C C5 5B E1 ED 12 FD 93 48 31 1D C0 B2 A9 E7E0 00 F5 D4 9E 5C 6E BF BC BF 34 93 4A BD 4E 9455 97 4B 8F 9A A9 F0 14 1D 15 97 CB 1B 08 C3 D1E2 1E CA 8F 5A 10 7F 91 B7 AA 1A 8F 56 22 B2 2CAD 31 A2 73 4F A9 F9 8E 2A 5C A5 71 AD C1 4A 6E8A 65 CD 86 2C 6B 32 05 DA DC 3D C0 09 37 5A 1076 C2 55 C0 8D 7B 30 5C 53 C9 2F A2 B0 FA 26 4582 8D 58 D8 BF 2C 26 BD F0 5B 13 B4 B1 D3 00 8D90 A7 8F 18 91 AF C7 F7 3F 46 00 30 60 53 BF DE8C 4E 4E D4 28 D8 0D 17 3A AB 85 B2 49 E4 19 3ED4 73 6C 82 24 7C FB 16 94 50 88 4B 8E EE 08 6299 1D E1 BE 23 F2 98 15 17 D5 B4 FD 47 AF 9E 65CD EC 31 67 20 B9 D4
В противном случи мы получим следующий ответ с сервера:Дамп #32A 04 AE B0 00 56 00 01 00 09 32 34 30 37 39 3031 35 32 00 04 00 3F 68 74 74 70 3A 2F 2F 77 7777 2E 61 69 6D 2E 63 6F 6D 2F 65 72 72 6F 72 732F 4D 49 53 4D 41 54 43 48 5F 50 41 53 53 57 442E 68 74 6D 6C 3F 63 63 6F 64 65 3D 75 73 26 6C61 6E 67 3D 65 6E 00 08 00 02 00 05             Рассмотрев три выше перечисленных дампа - стоит еще раз отметить две характерные вещи присущие FLAP заголовку:
           
a) В любом FLAP пакете третий и четвертый байт (WORD TYPE) определяют номер пакета (Sequence Number) это число постоянно должно увеличиваться на единичку, тем самым, сохраняя последовательность пакетов.
            
b) Пятый и шестой байт (WORD TYPE) FLAP заголовка определяют размер данных которые идут после FLAP заголовка который в свою очередь имеет размер в 6 байт.

Фрагмент кода - где мы отделяем UIN, IPserver:PORT, COOKIE друг от друга.

-----------------------------------------------------------------------------------------------------------------------------------------------------------
//RECIVE BOSS:PORT AND COKIE
memset(buffer, 0, 1024);
if(recv(icqhandle, buffer, 1024, 0) == -1) {
return 15;
}

//FIND BOSS:PORT AND COOKIE
//u uin len
i = 0;
i = htons(*((WORD *)( ((buffer + 10) + htons( *( (WORD *)(buffer + 8)) ) ) )));

//printf("%x\n", i);
if(i == 0x0005)
{
i = ntohs(*((WORD *)((buffer+10) + (ntohs(*((WORD *)(buffer + 8)))) + 2)));

p = ((buffer+10) + (ntohs(*((WORD *)(buffer + 8)))) + 2);
bossport = (char *)malloc((i+2) * sizeof(char ));
memset(bossport, 0, (i+2) );
memcpy(bossport,p+2, i);

i = 0;
j = 0;
while(*((p+2)+i) != '\x3A'){i++;}
boss = (char *)malloc((i+2) * sizeof(char ));
memset(boss, 0, (i+2));
memcpy(boss,p+2, i);

//fprintf(stdout, "boss %s \n", boss);

j = i;
i = 0;

while(ntohs(*((WORD *)((p+2+j+1)+i))) != 0x0006)i++;
bport = (char *)malloc((i) * sizeof(char ));
memset(bport, 0, i+2);
memcpy(bport, p+2+j+1, i);

//fprintf(stdout, "boss port %s \n", bport);

memset(cokie, 0, 255);
memcpy(cokie, ((p+2+j+1)+i+4), 256);
-----------------------------------------------------------------------------------------------------------------------------------------------------------

Разобрав данные и раскидав их по переменным, организуем reconnect на сервер и порт которые содержатся в переменных  boss и bport.  После чего необходимо организовать FLAP пакет, который будет содержать куку(Cookie) которую мы получили с сервера авторизации ICQ. Дамп пакета приведен ниже:

Дамп #4

2A 01 28 E0 01 08 00 00 00 01 00 06 01 00 EC 9FD0 FB 60 5F 7C 66 D4 24 4F 87 83 E7 98 41 15 DFAB DA C5 AF D0 CD FD 52 45 57 99 EC 9F 6A 96 3DC4 1A D7 E2 93 88 5F 9F 77 78 8F DD FB 19 E0 D501 DA 0B 48 19 33 F6 95 B9 9E AF 01 D3 D0 9D 46D3 AD 4D 3C B3 0D 80 CC 2E 03 90 2C E2 77 B9 3AC8 F1 F5 6F 84 3B 33 97 F4 04 16 9B 84 FA 2B 2135 FC B7 97 60 E9 77 7A 81 3A 1F 50 6A E4 21 B6B0 FC 07 17 09 3A 2E 9D 2E 86 BD 30 06 20 FA 5CA9 F6 EE 55 63 26 A1 E5 CD C7 F6 91 FD 86 7D B93F DF 07 34 79 52 66 F8 F4 AE FB D5 BF 7B CB 2ED2 FA CB 64 68 EE 19 F1 47 D5 70 40 E3 22 65 4320 5E 1C 27 DA 81 5B 64 10 52 67 E9 8A 47 D5 8992 6E C8 EF A9 0D FB 40 96 AD DD 41 2F 0E A2 96B7 D0 12 CD D5 92 30 45 79 E6 DE 9A 70 5A 40 0B9D C3 23 D8 AB 51 4D 83 92 BA A3 0E 3C 82 9C F3EC 2B 7C 8A F1 F8 77 E3 C1 09 D4 8F 94 9A

Функция по формированию пакета дамп, которого приведен выше.

-----------------------------------------------------------------------------------------------------------------------------------------------------------
static char *encode_reconnect(char *buf, char *cokie, int cookie_len)
{
char *flap;
buf = flap = flap_begin(buf, 1);
//buf = writel(buf, 0x0000001);
buf = writel(buf, ++requestid);
buf = tlv_write(buf, 0x06, cokie, cookie_len);
tlv_end(buf, flap);
return buf;
}

-----------------------------------------------------------------------------------------------------------------------------------------------------------

 

С сервера ожидаем, ответ READY, этот пакет говорит клиенту, что он готов работать с ним - взглянем на дамп SNAC (01,03):

 

Дамп #5

2A 02 8F 2D 00 24 00 01 00 03 00 00 83 C8 13 D500 01 00 02 00 03 00 04 00 06 00 08 00 09 00 0A00 0B 00 0C 00 13 00 15 00 22

На этот пакет необходимо послать встречный пакет, который должен содержать SNAC( 01,17).

2A 02 67 E1 00 32 00 01 00 17 00 00 00 00 00 1700 01 00 04 00 13 00 04 00 02 00 01 00 03 00 0100 15 00 01 00 04 00 01 00 06 00 01 00 09 00 01

Запрос сервера о версии ICQ сервера (Request server services versions).

Ниже приведен код по организации работы с SNAC(01,03) и SNAC(01,17):

-----------------------------------------------------------------------------------------------------------------------------------------------------------
while(1)
{
buf=(char *)malloc(56 * sizeof(char ));
memset(buffer, 0, 1024);
if(recv(icqhandle, buffer, 1024, 0) == -1) {return 15;}
if( (*( (WORD *)&buffer[7] ) == 1) && ( *( (WORD *)&buffer[9] ) == 3 ) )
{
//send SNAC01,17
memset(buf, 0, 56);
buf=flap=flap_begin(buf, 2);
buf=writew(buf, 0x0001);
buf=writew(buf, 0x0017);
buf=writew(buf, 0x0000);
buf = writel(buf, ++requestid);
buf = writew(buf, 0x0001);
buf = writew(buf, 0x0003);
buf = writew(buf, 0x000B);
buf = writew(buf, 0x0001);
tlv_end(buf, flap);

buf=buf-24;

if(send(icqhandle, buf, 24,0) == -1){return 14;}
//free(buf);
break;
}
} //while

-----------------------------------------------------------------------------------------------------------------------------------------------------------

 

Ну вот, думаю, что на этом практическую часть первой части статьи можно считать закрытой. Если вам что-то, было, не понятным думаю, что вторую часть этого документа не имеет смысла читать. Так как механизм авторизации на сервисе ICQ является фундаментальным понятием работы ICQ/AIM протоколов. Без этого вы не сможете вообще написать ни одной ICQ программы, которая будет сама на прямую работать с ICQ протоколом.

   Все выше описанное можно представить в следующей схеме
СХЕМА АВТОРИЗАЦИИ НА СЕРВИСЕ ICQ.    |----------|                           |---------------|   |          |                           |               |   | CLIENT   |    Connect IPv4/TCP       | login.icq.com |    |          | LP ----------------->5190 |               |    |ICQ2003a  |                           |  ICQ SERVICE  |   |          |                           |               |   |----------|                           |---------------|    |----------|                           |---------------|   |          |                           |               |   | CLIENT   |    First FLAP from srv    | login.icq.com |    |          | LP<----------------- 5190 |               |    |ICQ2003a  |                           |  ICQ SERVICE  |   |          |                           |               |   |----------|                           |---------------|   |----------|                           |---------------|   |          |                           |               |   | CLIENT   |    CLI_IDENT (Login)      | login.icq.com |    |          | LP ----------------->5190 |               |    |ICQ2003a  |                           |  ICQ SERVICE  |   |          |                           |               |   |----------|                           |---------------|   |----------|                           |---------------|   |          |                           |               |   | CLIENT   |            SRV_COOKIE         | login.icq.com |    |          | LP<----------------- 5190 |               |    |ICQ2003a  |   (boss, port, cookie)    |  ICQ SERVICE  |   |          |                           |               |   |----------|                           |---------------|                    RECONNECT   |----------|                           |---------------|   |          |                           |               |   | CLIENT   |        CLI_COOKIE         | BOSS ICQ SERV |    |          | LP ----------------->5190 |               |    |ICQ2003a  |                           |  ICQ SERVICE  |   |          |                           |               |   |----------|                           |---------------|   |----------|                           |---------------|   |          |                           |               |   | CLIENT   |    READY SNAC(01, 03)     | login.icq.com |    |          | LP<----------------- 5190 |               |    |ICQ2003a  |                           |  ICQ SERVICE  |   |          |                           |               |   |----------|                           |---------------|   |----------|                           |---------------|   |          |                           |               |   | CLIENT   |     services versions     | BOSS ICQ SERV |    |          | LP ----------------->5190 |               |    |ICQ2003a  |        SNAC(01, 17)       |  ICQ SERVICE  |   |          |                           |               |   |----------|                           |---------------| 

В конце первой статьи РЕЖИМ ЦВЕТОЧЕК, я вам обещал рассказать, как происходит получение и отправка ICQ сообщений (меж клиентские взаимодействия между ICQ пользователями).  И опять я не собираюсь разводить дискуссий по этой теме и буду не многословен.  

Тем у кого действительно есть желание разобраться с OSCAR - этот документ не будет у него единственным источником для его изучения. Ибо при изучении чего-либо нужно пользоваться несколькими ресурсами, тем самым вы сможете делать свои выводы, так как - этот документ содержит много недочетов и ошибок. Поэтому формируйте всегда свое мнение. В этом труде описаны поверхностные аспекты практической части по работе с ICQ протоколом.

 

Для того, что бы отправить сообщение другому клиенту ICQ необходимо сформировать пакет SNAC (04, 06); и отправить его на сервер. Сервер получив такой пакет совершит трансформацию пакета из SNAC (04, 06) в SNAC(04, 07) и передаст его дальше клиенту.

 

Рассмотрим дамп пакета SNAC(04, 06) (я намеренно делаю пояснения на английском язык, что бы сохранить начальный смысл полей SNAC, причем их просто перевести на русский):2A 02 09 C5 00 3F 00 04 00 06 00 00 00 00 12 9F00 00 00 00 00 00 00 00 00 01 06 3X 3X 3X 3X 3X3X 00 02 00 1C 05 01 00 01 01 01 01 00 13 00 0300 00 48 65 6C 6C 6F 20 6D 79 20 66 72 69 65 6E64 00 06 00 00 THE PAYHASH ICQ DUMP TRANSLATE: BYTE: [2A]    - [*] AsterixBYTE: [02]    – ChanelWORD: [09 C5] – sequens number (FLAP ID)WORD: [00 3F] – THE SNAC PACKET LENGTH (63 bytes)WORD: [00 04] – THE SNAC FAMILYWORD: [00 06] – THE SNAC SUBTYPEWORD: [00 00] – THE SNAC FLAGDWORD:[00 00 12 9F] – THE SNAC REQUESTIDSTRING[8 bytes]: [00 00 00 00 00 00 00 00] – THE SNAC(04,06) QOOKIEWORD: [00 01] – CHANEL OF THE MESSAGE TYPEBYTE: [06] – THE UIN LENGTSTRING[UIN LENGTH BYTE]: [3X 3X 3X 3X 3X 3X] – THE RECEIVER ICQ UINWORD: [00 02] – NUMBER OF THE ICBM DATAWORD: [00 1C] – THE ICBM DATA LENGTH (28 bytes)STRING[6 bytes]: [05 01 00 01 01 01] – ICBM HEADERBYTE: [01] – TLV TYPEWORD: [00 13] – TLV LENGTH (19 bytes)DWORD:[00 03 00 00] – TLV INFOSTRING: [48 65 6C 6C 6F 20 6D 79 20 66 72 69 65 6E 64] – THE ICQ MESSAGE (Hellow my friend) STRING: [00 06 00 00] – THE END SYMBOLS OF THE SNACK (04, 06) PACKET DATA    

Ну, вот, называется,  что разложил  и в рот положил, посмотрим на функцию, которая формирует SNAC(04, 06):

-----------------------------------------------------------------------------------------------------------------------------------------------------------  static int icq_msg_put(char *duin, char *sendmsg, int putmsglen)  {  char *tlv;  BYTE uinlen;  WORD packlen;  uinlen=strlen(duin);  buf=(char *)malloc(44+(uinlen+putmsglen) * sizeof(char ));  //bugs for Delphi  memset(buf, 0,(44+(uinlen+putmsglen)));   buf=flap=flap_begin(buf, 2);  buf=writew(buf, 0x0004);        // Семейство SNAC   buf=writew(buf, 0x0006);        // Номер в семействе  buf=writew(buf, 0x0000);        // SNAC флаг  buf = writel(buf, ++requestid); // Номер запроса всегда увеличивается на 1  buf=writes(buf, "\x00\x00\x00\x00\x00\x00\x00\x00", 8); // Cookie сообщения  buf=writew(buf, 0x0001);        // Канал куда будет направленно сообщение  buf=writeb(buf, uinlen);        // Делена UIN получателя  buf=writes(buf, duin, uinlen);  // UIN получателя   buf=tlv=tlv_begin(buf, 0x02);     /* Начало TLV 02(icmb info) + пустое поле с дленной */  buf=writes(buf,"\x05\x01\x00\x01\x01\x01",6); //Передаем icbm и длину      buf=writeb(buf, 0x01);          // Начало TLV 0x01  buf=writew(buf, (putmsglen+4)); // Длена TLV (TLV с сообщением)  buf=writes(buf,"\x00\x03\x00\x00", 4); // TLV info  buf=writes(buf, sendmsg, putmsglen);   // Сообщении и его длена   tlv_end(buf, tlv);              // Записываем длену TLV с сообщением                            /* Завершающие символы */  buf=writes(buf,"\x00\x03\x00\x00\x00\x06\x00\x00",8);  tlv_end(buf, flap);   packlen=ntohs(*((WORD *)(flap-2)))+6;  // Подсчет длены пакета   buf=buf-packlen;     /* Отправка сообщения на сервер */  if(send(icqhandle, buf, packlen,0) == -1){return 14;}    memset(buffer, 0, 1024);  /* Получение ответа от сервера о судьбе SNAC(04, 06);  if(recv(icqhandle, buffer, 1024, 0) == -1) {return 15;}    free(buf);   return 0;  }  

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

 

            | Code/FPS

100%   |   х

          |    х

          |        х

          |            х

          |                х

          |                     х

          |                           х

          |                                !   х   х   х     x

       --|---|---|---|---|---|---|---|---|---|---|---|---|---|-----a

       0 |  0,1   0,2   0,3  0,4  0,5  0,6  0,7   0,5  0,6   0,7  0,8  0,9  1       Liter / (VODKA)Alcohol

 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    Давайте подумаем, что такое входящее сообщение? Входящее сообщение это частный случай исходящего сообщения только относительно сервера, подумаем, почему это так происходит. Допустим, вы сформировали SNAC(04,06) пакет с исходящим сообщением отправили его на сервер ICQ, сервер ICQ получив, такое, сообщение конвертирует его в SNAC (04, 07) пакет исходящего сообщения для сервера и пакет входящего сообщения для клиента. Задача вашей ICQ программы должна заключатся в том, что бы она могла разбирать SNAC(04, 07).

2A 02 C2 D3 00 66 00 04 00 07 00 00 8D 11 AF 6700 00 00 00 00 00 00 00 00 01 06 3X 3X 3X 3X 3X3X 00 00 00 04 00 01 00 02 00 50 00 06 00 04 2000 00 00 00 0F 00 04 00 00 00 4B 00 03 00 04 43F0 17 D3 00 13 00 01 07 00 02 00 1C 05 01 00 0101 01 01 00 13 00 03 00 00 48 65 6C 6C 6F 20 6D79 20 66 72 69 65 6E 64 00 0B 00 00       [2A 02 C2 D3 00 66] – FLAP WORD:  [00 04] – THE SNAC FAMILYWORD:  [00 06] – THE SNAC SUBTYPEWORD:  [00 00]             - SNAC FLAGDWORD: [8D 11 AF 67]       - THE SNAC REQUESTIDSTRING:[8 bytes]: [00 00 00 00 00 00 00 00] – THE SNAC(04,06) QOOKIEWORD:  [00 01]             - CHANEL OF THE MESSAGE TYPEBYTE:  [06]                - THE UIN LENGTSTRING:[3X 3X 3X 3X 3X 3X] - THE SENDER ICQ UINWORD:  [00 00]             - THE SENDER WARNING LEVELWORD:  [00 04]             - THE NUMBER OF TLVBYTE:  [00 01]             - THE TLV TYPE(0x01) USER CLASSBYTE:  [00 02]             - THE TLV LENGTH

WORD:  [00 50]             - THE USER CLASS

Фрагмент когда по определению класса пользователя (http://www.aolhackers.ru/download/showarn.c):

/*

TERMINAL ENVASION PRESSENT: SHOWARN OPENSOURCE CODE (GPL)

FOR

AOLHACKERS PRODJECTS

SIMPLE EXAMPLE ON THE C ;)

best regars from payhash [email protected]

SHOW USER CLASS AND WARN LEVEL BEFORE AOL

07.09.2004

*/

//USER CLASS (THE PAYHASH CODE)

i=0;

i=ntohs(*((u_int16_t *)(buffer + 16 + (*((u_int8_t *)(buffer + 16)) + 9))));

 

//printf("UIN CLASS %02x \n", i);

switch(i)

{

case 0x0001: printf("uin class: AOL UNCONFIRMED \n");       break;

case 0x0002: printf("uin class: AOL ADMINISTRATOR \n");     break;

case 0x0004: printf("uin class: AOL \n");                   break;

case 0x0008: printf("uin class: AOL COMMERCIAL USER \n");   break;

case 0x0010: printf("uin class: AOL FREE \n");              break;

case 0x0020: printf("uin class: AOL AWAY \n");              break;

case 0x0040: printf("uin class: AOL ICQ \n");               break;

case 0x0050: printf("uin class: AOL ICQ USER \n");          break;

case 0x0070: printf("uin class: AOL ICQ, FREE \n");       break; 

case 0x0080: printf("uin class: AOL WIRELESS \n");          break;

default:     printf("uin class: UNKNOWN \n");               break;

}

WORD:  [00 04]             - THE TLV TYPE(0x04) USER STATUSWORD:  [00 04]             - THE TLV LENGTH (4 BYTES)DWORD: [20 00 00 00]       - THE USER STATUSLOOK: Miscellaneous OSCAR protocol information  0x0001   STATUS_WEBAWARE   Status webaware flag 0x0002   STATUS_SHOWIP     Status show ip flag 0x0008   STATUS_BIRTHDAY   User birthday flag 0x0020   STATUS_WEBFRONT   User active webfront flag 0x0100   STATUS_DCDISABLED Direct connection not supported 0x1000   STATUS_DCAUTH     Direct connection upon authorization 0x2000   STATUS_DCCONT     DC only with contact users0x0000   STATUS_ONLINE     Status is online 0x0001   STATUS_AWAY       Status is away 0x0002   STATUS_DND        Status is no not disturb (DND) 0x0004   STATUS_NA         Status is not available (N/A) 0x0010   STATUS_OCCUPIED   Status is occupied (BISY) 0x0020   STATUS_FREE4CHAT  Status is free for chat 0x0100   STATUS_INVISIBLE  Status is invisible  WORD:  [00 0F]              - THE TLV TYPE(0x0F) THE ONLINE TIME WORD:  [00 04]              - TLV LENGTHDWORD: [00 00 00 4B]        - THE CLIENT ONLINE TIMEWORD:  [00 03]              - THE TLV TYPE(0x03) USER ACCOUNT(UIN) CREATION           TIMEWORD:  [00 04]              - TLV LENGTHDWORD: [43 F0 17 D3]        - USER ACCOUNT (UIN) CREATION TIME

Дальше идут ICMB данные с различными TLV типами, которые содержат различные

флаги и остальную служебную информацию. К примеру [00 13 00 01 07] [00 13]  - TLV тип, [00 01] - TLV длена, [07] – значение, честно говоря таких полей может быть много и все они определяются на сервере я описал лишь те которые мне известны. Ну, и наконец последнее поле TLV с сообщением =))). WORD:  [00 02]               - THE TLV TYPE(0x02) THE USER MESSAGE WORD:  [00 1C]               - TLV LENGTH (28 bytes)   [05 01 00 01 01 01 01 00 13 00 03 00 00] – Честно говоря, сам не знаю, что сие данные означают - просто не было необходимости в них разбираться (я догадываюсь, что это связанно с типом клиента, который вам отправил сообщение). После этих загадочных данных идет само сообщение, которое вам направили: [48 65 6C 6C 6F 20 6D 79 20 66 72 69 65 6E 64] ~ Hello my friend DWORD: [00 0B 00 00]         - THE END OF DATA


Посмотрите на функцию, которая умеет разбирать пакет входящего сообщения.  

  

void *icq_msg_get(char *ruin, char *msg)    {  DWORD snac;  WORD i,k;  BYTE j;  char icbm[512];    char *p;    memset(buffer, 0, 1024);  memset(icbm, 0, 512);  memset(ruin, 0, 9);  memset(msg, 0, 512);   //CRAZY rev2 ICQLITE 2003b  if(recv(icqhandle, buffer, 1024, 0) == -1){}              if( ( ntohl( *(DWORD *)(buffer+6) ) ) == 0x00040007)  {   i=ntohs((*((WORD *)(buffer+24))));  //printf("TLV01 = %02x\n",i);  if(i == 0x0001 || i == 0x004)  {  j=*((BYTE *)(buffer+26));  //printf("uin len = %x\n",j);  strncpy(ruin, (buffer+27), j);  //printf("message from %s\n", ruin);    i=ntohs(*((WORD *)(buffer + 27 + j + 34)));  if(i == 0x0002 || i == 0x0005) {  i=ntohs(*((WORD *)(buffer + 27 + j + 36)));  //printf("icbm len = %02x\n",i);  memcpy(icbm, (buffer + 27 + j + 38), i); /*  for(j=0; j<i; j++){  printf(" %02x", icbm[j]);  }  printf("\n");*/   j=*((BYTE *)(icbm));   if(j == 0x05){  i=ntohs(*((WORD *)(icbm+2)));  k=i;  i=ntohs(*((WORD *)(icbm+i+6)));  memcpy(msg, icbm+k+12, (i-4));  //printf("msg %s\n", msg);               }  if(j != 0x05)   {  i=ntohs(*((WORD *)(icbm+5)));  //k=i;  memcpy(msg, icbm+8, i);   } }  }   } Ну вот, пожалуй на этом все, думаю, что - этот материал вам чем то сможет помочь…                                    Удачи вам ICQ хакеры.     payhash [aolhackers.ru]          2006.02.16