可惜,我每次问问题总是很少有答复,:(,个人魅力不够
我自己找到了,大家看看吧!
Version 5 of the ICQ Protocol
Copyright ©2001 Henrik Isaksson Last update 22 April 2001
Contents
About this document
Document history
Disclaimer
Client to Server Packets
CMD_ACK (10)
CMD_SEND_MESSAGE (270)
CMD_LOGIN (1000)
CMD_REG_NEW_USER (1020)
CMD_CONTACT_LIST (1030)
CMD_SEARCH_UIN (1050)
CMD_SEARCH_USER (1060)
CMD_KEEP_ALIVE (1070)
CMD_SEND_TEXT_CODE (1080)
CMD_ACK_MESSAGES (1090)
CMD_LOGIN_1 (1100)
CMD_MSG_TO_NEW_USER (1110)
CMD_INFO_REQ (1120)
CMD_EXT_INFO_REQ (1130)
CMD_CHANGE_PW (1180)
CMD_NEW_USER_INFO (1190)
CMD_UPDATE_EXT_INFO (1200)
CMD_QUERY_SERVERS (1210)
CMD_QUERY_ADDONS (1220)
CMD_STATUS_CHANGE (1240)
CMD_NEW_USER_1 (1260)
CMD_UPDATE_INFO (1290)
CMD_AUTH_UPDATE (1300)
CMD_KEEP_ALIVE2 (1310)
CMD_LOGIN_2 (1320)
CMD_ADD_TO_LIST (1340)
CMD_RAND_SET (1380)
CMD_RAND_SEARCH (1390)
CMD_META_USER (1610)
CMD_INVIS_LIST (1700)
CMD_VIS_LIST (1710)
CMD_UPDATE_LIST (1720)
Server to Client Packets
SRV_ACK (10)
SRV_GO_AWAY (40)
SRV_NEW_UIN (70)
SRV_LOGIN_REPLY (90)
SRV_BAD_PASS (100)
SRV_USER_ONLINE (110)
SRV_USER_OFFLINE (120)
SRV_QUERY (130)
SRV_USER_FOUND (140)
SRV_END_OF_SEARCH (160)
SRV_NEW_USER (180)
SRV_UPDATE_EXT (200)
SRV_RECV_MESSAGE (220)
SRV_X2 (230)
SRV_NOT_CONNECTED (240)
SRV_TRY_AGAIN (250)
SRV_SYS_DELIVERED_MESS (260)
SRV_INFO_REPLY (280)
SRV_EXT_INFO_REPLY (290)
SRV_STATUS_UPDATE (420)
SRV_SYSTEM_MESSAGE (450)
SRV_UPDATE_SUCCESS (480)
SRV_UPDATE_FAIL (490)
SRV_AUTH_UPDATE (500)
SRV_MULTI_PACKET (530)
SRV_X1 (540)
SRV_RAND_USER (590)
SRV_META_USER (990)
Client to Client Communication
Introduction
Starting with UDP
Switch to TCP
The TCP Init Packet
The TCP Message Packet
The Message Ack Packet
TCP Message Related #define's
Reverse TCP Connections
File Direct Protocol
Chat Mode Protocol
Calculating the checkcode
Encryption
1. About this document
This is an unofficial specification, based on Magnus Ihses specification for
version 2 of the ICQ protocol, Mattew Smith's MICQ, Sebastien Dault's description of the encryption and on the discussions on the icq-devel mailing list.
The Client-to-client section is written by Douglas F. McLaughlin, the author of StrICQ.
Andreas Rasmussen has provided information about the LOGIN command.
David Phillips has corrected errors in the encryption algorithm.
Alberto Treves has provided information about CMD_META_USER.
Alexandr Shutko has provided information about the login sequence.
David Yu wrote about CMD_MSG_TO_NEW_USER.
If you have any comments on the contents of this document, send them to mailto:hki@hem1.passagen.se.
To read the V2 document or join the mailing list, go to
http://www.student.nada.kth.se/~d95-mih/icq/
Any trademarks mentioned in this text belongs to their respective owner.
Number convention
0x12345678 Real value in hexadecimal.
78 56 34 12 Hex dump value.
(1234) Decimal number.
2. Document history
2001-01-10 Updated CMD_META_USER and SRV_LOGIN_REPLY.
2000-12-28 Updated CMD_META_USER.
2000-12-10 Updated the encryption and checkcode section.
2000-04-30 Updated CMD_LOGIN and CMD_CHANGE_STATUS.
2000-01-22 Updated CMD_LOGIN.
1999-12-12 Added TCP protocol information.
1999-10-24 Updated CMD_NEW_USER_INFO, CMD_REG_NEW_USER and SRV_NEW_USER.
1999-07-30 Added this version history.
Added links from the table of contents.
3. Disclaimer
LICENSE AGREEMENT
This document and the information present herein is provided by the Author for
your personal use only. You agree to the full responsibility for the results of
your use of this document or the information present herein.
By using this document or the information present herein, you accept the terms
of this license agreement.
THIS INFORMATION IS PROVIDED ON AN "AS IS" BASIS. THE AUTHOR MAKES NO
WARRANTIES, EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THOSE OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, WITH RESPECT TO THIS
DOCUMENT AND THE INFORMATION PRESENT HEREIN. THE AUTHOR DOES NOT WARRANT,
GUARANTEE OR MAKE ANY REPRESENTATIONS REGARDING THE USE OR THE RESULTS OF THE
USE OF THIS DOCUMENT OR THE INFORMATION PRESENT HEREIN, IN TERMS OF THE
ACCURACY, RELIABILITY, QUALITY, VALIDITY, STABILITY, COMPLETENESS, CURRENTNESS,
OR OTHERWISE. THE ENTIRE RISK OF USING THE INFORMATION PRESENT IN THIS DOCUMENT
IS ASSUMED BY THE USER.
IN NO EVENT WILL THE AUTHOR BE LIABLE TO ANY PARTY (i) FOR ANY DIRECT, INDIRECT,
SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF
PROGRAMS OR INFORMATION, AND THE LIKE), OR ANY OTHER DAMAGES ARISING IN ANY WAY
OUT OF THE AVAILABILITY, USE, RELIANCE ON, OR INABILITY TO USE THIS DOCUMENT OR
THE INFORMATION PRESENT HEREIN, EVEN IF THE AUTHOR HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES, AND REGARDLESS OF THE FORM OF ACTION, WHETHER IN
CONTRACT, TORT, OR OTHERWISE; OR (ii) FOR ANY CLAIM ATTRIBUTABLE TO ERRORS,
OMISSIONS, OR OTHER INACCURACIES IN, OR DESTRUCTIVE PROPERTIES OF ANY
INFORMATION.
4. Client to server packets
The Client-to-server packets are sent using UDP to the ICQ server. Every UDP
packet begins with a header as follows:
ICQ Packet Header (client side)
Length Content (if fixed) Designation Description
2 bytes 05 00 VERSION Protocol version
4 bytes 00 00 00 00 ZERO Just zeros, purpouse unknown
4 bytes xx xx xx xx UIN Your (the client's) UIN
4 bytes xx xx xx xx SESSION_ID Used to prevent 'spoofing'. See below.
2 bytes xx xx COMMAND
2 bytes xx xx SEQ_NUM1 Starts at a random number
2 bytes xx xx SEQ_NUM2 Starts at 1
4 bytes xx xx xx xx CHECKCODE
variable xx ... PARAMETERS Parameters for the command being sent
The packets sent from the client to the server are encrypted before they are
sent, unlike the packets sent from the server which are not encrypted. For more
information on encryption/decryption, see Sebastien Dault's document.
SESSION_ID is a random number, chosen when the login packet is sent, and kept
until you log out. This number must be the same for every packet you send, or
the server will ignore them. The session id will also be sent back to you in
every packet sent by the server, and this way you can tell if the packet comes
from the server or is a 'spoofed' packet. (compare the number in the recieved
packet to the one you've sent)
The sequence numbers are used to make sure the packets really arrive at the
recipent, and only do so once. When you send a packet to the server you should
recieve an acknowledgement (SRV_ACK) from the server, if you don't, you should
send the packet again. If you recieve two or more packets with the same sequence
number, you should ignore all but one. Likewise the server excpects you to send
an acknowledgement for every packet you recieve from the server, except for the
SRV_ACK packet. See SRV_ACK and CMD_ACK.
SEQ_NUM1 is set to a random number in the login packet, and then increased by
one everytime you send a packet. (e.g. if the login packet has SEQ_NUM1 = 123,
the next packet you send should have SEQ_NUM1 = 124.)
SEQ_NUM2 is set to 1 in the login packet, and increased by one for most (but not
all) of the packets you send. (e.g. CMD_KEEP_ALIVE should always have SEQ_NUM2 = 0)
CMD_ACK 0A 00 (10)
This command is sent to acknowledge reciption of a packet you have recieved
from the server.
Parameters
Length Content (if fixed) Designation Description
4 bytes xx xx xx xx RANDOM Random number.
Note! The sequence number in the header contains the sequence number of the
(server) packet to acknowledge.
CMD_SEND_MESSAGE 0E 01 (270)
This command is used to send messages through the server to offline or
invisible users ('Offline message'). Parameters
Length Content (if fixed) Designation Description
4 bytes xx xx xx xx RECIEVER_UIN UIN of the user the message is sent to
2 bytes (see below) MESSAGE_TYPE Type of message being sent
2 bytes xx xx MESSAGE_LENGTH Message text including terminating NULL-byte
variable xx ... 00 MESSAGE_TEXT NULL terminated string
MESSAGE_TYPE can be one of the following: Message types
Designation Value Description
MSG_TEXT 01 00 Normal text message
MSG_URL 04 00 URL message
This message consists of two parts, separated by 0xFE. First the description of
the URL followed by the URL itself.
MSG_AUTH_REQ 06 00 Request authorization to add user to contact list
This message consists of five parts, separated by 0xFE. Nickname, first name, last name,
email address and reason.
MSG_AUTH 08 00 Grant request to add user to contact list
MSG_USER_ADDED 0C 00 User (the recipent) has been added to contact list
This message consists of four parts, separated by 0xFE. Nickname, first name, last name and email address, in that order.
MSG_CONTACTS 13 00 Send contacts
This message consists of a number of nicknames and UINs separated by a 0xFE
byte. The first part of the message is the number of contacts (nickname/UIN
pairs) in the message. This number is stored in ASCII-code, and it is terminated
in the same way as the other parts, with 0xFE.
CMD_LOGIN E8 03 (1000)
This packet is used to log in to the server, which must be done before any of
the other commands can be used, except for the ones used to register a new user.
Parameters
Length Content (if fixed) Designation Description
4 bytes xx xx xx xx TIME time(NULL), number of seconds since 1 January 1970
4 bytes xx xx xx xx PORT The port you will be listening for TCP connections on
2 bytes xx xx PASS_LENGTH Length of password, including NULL
variable xx ... 00 PASSWORD NULL terminated string containing the password
4 bytes xx xx xx xx X1 Unknown, usually d5 00 00 00
4 bytes xx xx xx xx IP Our IP
1 bytes xx FLAGS_1 See below for definitions.
4 bytes xx xx xx xx STATUS Status, see CMD_CHANGE_STATUS for definitions
2 bytes xx xx TCP_VER TCP version, 06 00 (V6) is currently used
2 bytes xx xx X2 Unknown, usually 00 00
4 bytes xx xx xx xx X3 Unknown, usually 00 00 00 00
4 bytes xx xx xx xx X4 Unknown, usually 08 00 d5 00
4 bytes xx xx xx xx X5 Unknown, usually 50 00 00 00
4 bytes xx xx xx xx X6 Unknown, usually 03 00 00 00
4 bytes xx xx xx xx BUILD_DATE Build date of the client. (seconds since 1970)
When the login packet has arrived at the server, assuming it is correct, you
will recieve an acknowledgement (SRV_ACK) and a login reply (SRV_LOGIN_REPLY).
These are the known flags of the FLAGS_1 field:
Value Description
0x01 Firewall (with dynamic TCP-port)
0x02 Proxy. (SOCKS5/SOCKS4)
0x04 Enable communication over TCP
CMD_REG_NEW_USER FC 03 (1020)
This command is sent to the server without logging in. The UIN field of header
is set to NULL. The server will acknowledge this packet and reply with a
SRV_NEW_USER packet. This packet contains your new UIN, which you must log in
with immediately (send a CMD_LOGIN with your new UIN and the password you have
chosen). When you have logged in successfully (SRV_LOGIN_REPLY) you should use
the CMD_NEW_USER_INFO command to set up basic info such as your nickname. Parameters
Length Content (if fixed) Designation Description
2 bytes xx xx PASS_LENGTH Length of password. (9 chars is max for Mirabilis ICQ)
variable xx ... 00 PASS A password you want to use for the new account.
4 bytes A0 00 00 00 UNKNOWN1 Unknown.
4 bytes 61 24 00 00 UNKNOWN2 Unknown.
4 bytes 00 00 A0 00 UNKNOWN3 Unknown.
4 bytes 00 00 00 00 UNKNOWN4 Unknown.
CMD_CONTACT_LIST 06 04 (1030)
This command is used to inform the server of which users you wish to recieve
online/offline events for. Parameters
Length Content (if fixed) Designation Description
1 byte xx NUM_CONTACTS Number of UINs in this packet
4 bytes xx xx xx xx UIN_1 1st UIN in your contact list.
... ... ... ...
4 bytes xx xx xx xx UIN_n Last UIN in your contact list.
Note! The maximum number of users is limited to about 120 because of ICQ's
maximum packet length of 450 bytes, if your contact list consists of more users,
you have to send this packet multiple times.
CMD_SEARCH_UIN 1A 04 (1050)
This command is used to search for a user using his/her UIN. Parameters
Length Content (if fixed) Designation Description
2 bytes xx xx SEARCH_SEQ See below.
4 bytes xx xx xx xx SEARCH_UIN The UIN to search for.
CMD_SEARCH_USER 24 04 (1060)
Search for a user. The server responds with SRV_USER_FOUND for every user it
finds and SRV_END_OF_SEARCH.
Parameters
Length Content (if fixed) Designation Description
2 bytes xx xx NICK_LENGTH Length of nickname, including NULL
variable xx ... 00 NICK Nickname, NULL terminated
2 bytes xx xx FIRST_LENGTH Length of first name, including NULL
variable xx ... 00 FIRST First name, NULL terminated
2 bytes xx xx LAST_LENGTH Length of last name, including NULL
variable xx ... 00 LAST Last name, NULL terminated
2 bytes xx xx EMAIL_LENGTH Length of email address, including NULL
variable xx ... 00 EMAIL Email address, NULL terminated
CMD_KEEP_ALIVE 2E 04 (1070)
This command has to be sent to the server every two minutes. If has not been
sent within two minutes, the server will assume that you are offline. Parameters
Length Content (if fixed) Designation Description
4 bytes xx xx xx xx RANDOM Random number.
Note! SEQ_NUM2 in the header should be set to zero when sending this command.
CMD_SEND_TEXT_CODE 38 04 (1080)
This packet is used to send special commands to the server as text. Parameters
Length Content (if fixed) Designation Description
2 bytes xx xx LENGTH Length of the text command, including NULL-byte.
variable xx ... TEXT_CODE NULL terminated string containing of the codes below.
2 bytes 05 00 X1 Unknown, usually 05 00
Theese are the different TEXT_CODEs available:
Text code Description
B_USER_DISCONNECTED Disconnect from the server
B_MESSAGE_ACK Tells the server to respond immediately, used when you have trouble connecting.
B_KEEPALIVE_ACK Unknown, probably similar to B_MESSAGE_ACK
Note! SEQ_NUM2 in the header should be set to zero when sending this command.
CMD_ACK_MESSAGES 42 04 (1090)
Remove old messages from server. Usually sent when SRV_X2 is recieved.
Parameters Length Content (if fixed) Designation Description
4 bytes xx xx xx xx RANDOM Random number.
CMD_LOGIN_1 4C 04 (1100)
Unknown packet sent during login. Does not appear to be used by ICQ99.
Parameters Length Content (if fixed) Designation Description
4 bytes xx xx xx xx RANDOM Random number.
CMD_MSG_TO_NEW_USER 56 04 (1110)
Send a message to a user who is not in your contact list. Parameters
Length Content (if fixed) Designation Description
2 bytes xx xx MESSAGE_TYPE See below.
2 bytes xx xx MESSAGE_LENGTH Message text including terminating NULL-byte.
Variable xx xx ... 00 DATA NULL-terminated string.
MESSAGE_TYPE can have one of these values: Message types
Name Value Description
MSG_TEXT 01 00 Normal text message
MSG_URL 04 00 URL message
This message consists of two parts, separated by 0xFE. First the description of
the URL followed by the URL itself.
MSG_AUTH_REQ 06 00 Request authorization to add user to contact list
This message consists of five parts, separated by 0xFE. Nickname, first name,
last name, email address and reason.
MSG_DENY 07 00 Deny the request to add user to contact list
MSG_AUTH 08 00 Grant request to add user to contact list
CMD_INFO_REQ 60 04 (1120)
Request basic information about a user. Parameters
Length Content (if fixed) Designation Description
4 bytes xx xx xx xx UIN The UIN of the user you are requesting info about.
The server will respond with SRV_INFO_REPLY.
CMD_EXT_INFO_REQ 6A 04 (1130)
Request extended information about a user. Parameters
Length Content (if fixed) Designation Description
4 bytes xx xx xx xx UIN The UIN of the user you are requesting info about.
The server will respond with SRV_EXT_INFO_REPLY.
CMD_CHANGE_PW 9C 04 (1180)
Change login password. This command is obsolete. Use CMD_META_USER instead.
CMD_NEW_USER_INFO A6 04 (1190)
Send basic information about a new user being registered. This command is sent
when you log in the first time using a newly obtained UIN. See CMD_REG_NEW_USER.
Parameters
Length Content (if fixed) Designation Description
2 bytes xx xx NICK_LENGTH Length of nickname, including NULL
variable xx ... 00 NICK Nickname, NULL terminated
2 bytes xx xx FIRST_LENGTH Length of first name, including NULL
variable xx ... 00 FIRST First name, NULL terminated
2 bytes xx xx LAST_LENGTH Length of last name, including NULL
variable xx ... 00 LAST Last name, NULL terminated
2 bytes xx xx EMAIL_LENGTH Length of email address, including NULL
variable xx ... 00 EMAIL Email address, NULL terminated
1 byte 01 UNKNOWN1 Unknown
1 byte 01 UNKNOWN2 Unknown
1 byte 01 UNKNOWN3 Unknown
CMD_UPDATE_EXT_INFO B0 04 (1200)
CMD_QUERY_SERVERS BA 04 (1210)
Query the server about adresses to other servers.
CMD_QUERY_ADDONS C4 04 (1220)
Query the server about globally defined add-ons.
CMD_STATUS_CHANGE D8 04 (1240)
Change users online status. (Away, invisible etc.) Parameters
Length Content (if fixed) Designation Description
4 bytes xx xx xx xx STATUS The new status. See below
Statuses
Designation Value Description
STATUS_ONLINE 00 00 00 00 User is online
STATUS_AWAY 01 00 00 00 User is away
STATUS_DND 13 00 00 00 Do Not Disturb
STATUS_INVISIBLE 00 01 00 00 User is invisible
STATUS_OCCUPIED 10 00 00 00 Occupied
STATUS_NA 04 00 00 00 Not Available
STATUS_CHAT 20 00 00 00 Free for chat
STATUS_DND and STATUS_NA may or may not be combined (ORed) with STATUS_AWAY,
depending on which version of the ICQ client you are using.
The following flags can also be ORed with the staus to control if your client is
WebAware or if your IP will be displayed. Status flags
Designation Value Description
STATUSF_WEBAWARE 00 00 01 00 Your online status can be seen from the web.
STATUSF_SHOWIP 00 00 02 00 Your IP will be displayable by other clients.
CMD_NEW_USER_1 EC 04 (1260)
Ask for permission to add a new user.
CMD_UPDATE_INFO 0A 05 (1290)
Update your info in the servers user database.
Parameters
Length Content (if fixed) Designation Description
2 bytes xx xx NICK_LENGTH Length of nickname, including NULL
variable xx ... 00 NICK Nickname, NULL terminated
2 bytes xx xx FIRST_LENGTH Length of first name, including NULL
variable xx ... 00 FIRST First name, NULL terminated
2 bytes xx xx LAST_LENGTH Length of last name, including NULL
variable xx ... 00 LAST Last name, NULL terminated
2 bytes xx xx EMAIL_LENGTH Length of email address, including NULL
variable xx ... 00 EMAIL Email address, NULL terminated
CMD_AUTH_UPDATE 14 05 (1300)
Update you authorization status. (i.e. do you want users to require your
permission to add you to their contact lists?) Note that this does only concern
the Mirabilis client, most clones allow their users to override this setting.
Parameters
Length Content (if fixed) Designation Description
4 bytes xx xx xx xx AUTHORIZE TRUE => no authorization required, FALSE => authorization required.
CMD_KEEP_ALIVE2 1E 05 (1310)
In earlier versions this command was sent to the server along with the
CMD_KEEP_ALIVE message. Does not appear to be used by ICQ99. Parameters
Length Content (if fixed) Designation Description
4 bytes xx xx xx xx RANDOM Random number.
CMD_LOGIN_2 28 05 (1320)
This command was used during login in earlier versions. (Obsolete now). It was
used to inform the server of the client's state, wheter it was maximized or
minimized. This command was sent right after login and after each status change.
The data consisted of one byte:
0x00 - Status disabled (?)
0x01 - Client is maximized.
0xFF - Client is minimized.
CMD_ADD_TO_LIST 3C 05 (1340)
Add a user to contact list. After issuing this command you will recieve user
status changes for this user in addition to those on your contact list.
Parameters
Length Content (if fixed) Designation Description
4 bytes xx xx xx xx UIN User to add
CMD_RAND_SET 64 05 (1380)
Specify in which group you want to be available for random chat. Parameters
Length Content (if fixed) Designation Description
4 bytes xx xx xx xx RAND_GROUP See CMD_RAND_SEARCH
Note! Your online status must be Free for Chat for others to find you.
CMD_RAND_SEARCH 6E 05 (1390)
Find a random user. Parameters Length Content (if fixed) Designation
Description
2 bytes xx xx RAND_GROUP See below.
RAND_GROUP can have one of the following values: Name Value
General 1
Romance 2
Games 3
Students 4
20 something 6
30 something 7
40 something 8
50+ 9
Man chat requesting women 10
Woman chat requesting men 11
CMD_META_USER 4A 06 (1610)
Set or get user information. Parameters
Length Content (if fixed) Designation Description
2 bytes xx xx SUBCMD See below.
variable xx xx ... DATA See below.
SUBCMD can have one of these values: Name Value
SET_WORK_INFO 1011
SET_MORE_INFO 1021
SET_GENERAL_INFO 1001
SET_ABOUT_INFO 1030
SET_WEB_PRESENCE 2000
Depending on this value, DATA should contain parameters for the SUBCMD.
SET_GENERAL_INFO (name, phone, address etc) has the following parameters:
Parameters
Length Content (if fixed) Designation Description
2 bytes xx xx NICK_LENGTH Length of nickname
variable xx ... 00 NICK Nickname
2 bytes xx xx FIRST_LENGTH Length of first name
variable xx ... 00 FIRST First name
2 bytes xx xx LAST_LENGTH Length of last name
variable xx ... 00 LAST Last name
2 bytes xx xx PRIMARY_LENGTH Length of primary email address
variable xx ... 00 PRIMARY_EMAIL Primary email address
2 bytes xx xx SECONDARY_LENGTH Length of secondary email address
variable xx ... 00 SECONDARY_EMAIL Secondary email address
2 bytes xx xx OLD_LENGTH Length of old email address
variable xx ... 00 OLD_EMAIL Old email address
2 bytes xx xx CITY_LENGTH Length of city
variable xx ... 00 CITY City
2 bytes xx xx STATE_LENGTH Length of state
variable xx ... 00 STATE State
2 bytes xx xx PHONE_LENGTH Length of phone number
variable xx ... 00 PHONE Phone number
2 bytes xx xx FAX_LENGTH Length of fax number
variable xx ... 00 FAX Fax number
2 bytes xx xx STREET_LENGTH Length of street address
variable xx ... 00 STREET Street address
2 bytes xx xx CELL_LENGTH Length of cell phone number
variable xx ... 00 CELLULAR Cellular phone number
4 bytes xx xx xx xx ZIPCODE Zip (postal) code.
2 bytes xx xx COUNTRY Country code
1 byte xx TIMEZONE Time zone
1 byte xx AUTHORIZE Authorization status
1 byte xx WEBAWARE Show the user's online status on the web
1 byte xx HIDEIP Don't show the user's IP
SET_MORE_INFO (age, gender etc) has the following parameters: Parameters
Length Content (if fixed) Designation Description
2 bytes xx xx AGE Age, ff ff = not entered.
1 byte xx GENDER 1 = female, 2 = male
2 bytes xx xx URL_LENGTH Length of URL, including NULL
variable xx ... 00 URL URL to personal homepage, NULL terminated
1 byte xx YEAR Year of birth (from 1900).
1 byte xx MONTH Month of birth (13 here would be fun...
).
1 byte xx DAY Day of birth.
1 byte xx LANGUAGE1 Spoken language #1.
1 byte xx LANGUAGE2 Spoken language #2.
1 byte xx LANGUAGE3 Spoken language #3.
SET_WORK_INFO (info about where the user work) has the following parameters:
Parameters
Length Content (if fixed) Designation Description
2 bytes xx xx CITY_LENGTH Length of city, including NULL
variable xx ... 00 CITY City, NULL terminated
2 bytes xx xx STATE_LENGTH Length of state, including NULL
variable xx ... 00 STATE State, NULL terminated
2 bytes xx xx PHONE_LENGTH Length of phone number, including NULL
variable xx ... 00 PHONE Phone number, NULL terminated
2 bytes xx xx FAX_LENGTH Length of fax number, including NULL
variable xx ... 00 FAX Fax number, NULL terminated
2 bytes xx xx ADDR_LENGTH Length of address, including NULL
variable xx ... 00 ADDR Address, NULL terminated
2 bytes 00 01 UNKNOWN1 Unknown
2 bytes ff ff UNKNOWN2 Unknown
2 bytes xx xx COMPANY_LENGTH Length of company name, including NULL
variable xx ... 00 COMPANY Name of the company, NULL terminated
2 bytes xx xx DEPT_LENGTH Length of departement, including NULL
variable xx ... 00 DEPT Name of departement, NULL terminated
2 bytes xx xx POS_LENGTH Length of position, including NULL
variable xx ... 00 POS Position, NULL terminated
2 bytes 04 00 UNKNOWN3 Unknown
2 bytes xx xx URL_LENGTH Length of URL, including NULL
variable xx ... 00 URL URL to corporate homepage, NULL terminated
SET_ABOUT (other optional info) has the following parameters: 2 bytes xx xx
ABOUT_LENGTH Length of text, including NULL
variable xx ... 00 ABOUT Text string, NULL terminated
SET_WEB_PRESENCE is used to activate the web presence indicator.
CMD_INVIS_LIST A4 06 (1700)
This command is used to inform the server of which users you want to be
invisible to, even when you are not in invisible mode. Parameters
Length Content (if fixed) Designation Description
1 byte xx NUM_USERS Number of UINs in this packet
4 bytes xx xx xx xx UIN_1 1st UIN in your list.
... ... ... ...
4 bytes xx xx xx xx UIN_n Last UIN in your list.
Note! The maximum number of users is limited to about 120 because of ICQ's
maximum packet length of 450 bytes, if your invisible list consists of more
users, you have to send this packet multiple times.
CMD_VIS_LIST AE 06 (1710)
This command is used to inform the server of which users you want to be able
to see you when you are in invisible mode. Parameters
Length Content (if fixed) Designation Description
1 byte xx NUM_USERS Number of UINs in this packet
4 bytes xx xx xx xx UIN_1 1st UIN in your list.
... ... ... ...
4 bytes xx xx xx xx UIN_n Last UIN in your list.
Note! The maximum number of users is limited to about 120 because of ICQ's
maximum packet length of 450 bytes, if your visible list consists of more users,
you have to send this packet multiple times.
CMD_UPDATE_LIST B8 06 (1720)
This command is used to inform the server of changes in your visible/invisible
user lists. Parameters
Length Content (if fixed) Designation Description
4 bytes xx xx xx xx UIN UIN of user to add or remove
1 byte xx LIST List affected by the change, 01 - invisible, 02 - visible
1 bytes xx REMADD 00 - Remove user, 01 - Add user to list
5. Server to Client Packets
Every server-to-client UDP packet begins with a header as follows:
ICQ Packet Header (server side)
Length Content (if fixed) Designation Description
2 bytes 05 00 VERSION Protocol version
1 byte 00 ZERO Unknown
4 bytes xx xx xx xx SESSION_ID Same as in your login packet.
2 bytes xx xx COMMAND
2 bytes xx xx SEQ_NUM1 Sequence 1
2 bytes xx xx SEQ_NUM2 Sequence 2
4 bytes xx xx xx xx UIN Your (the client's) UIN
4 bytes xx xx xx xx CHECKCODE
variable xx ... PARAMETERS Parameters for the command being sent
Theese packets are not encrypted in any way.
See the Client to server section for further description of the fields.
SRV_ACK 0A 00 (10)
Acknowledgement for a command sent to the server. Until this is recieved you
should keep resending your command to the server, with a reasonable delay to
avoid wasting bandwidth. The Mirabilis client resends 6 times with an interval
of 10 seconds. After 6 resends a CMD_SEND_TEXT_CODE with B_MESSAGE_ACK i sent.
No parameters
The sequence numbers in the header contains the sequence numbers of the (client)
packet that is being acknowledged.
SRV_GO_AWAY 28 00 (40)
Error message from the server. You have to disconnect and reconnect in order
to continue.
No parameters
SRV_NEW_UIN 46 00 (70)
A new UIN, requested by CMD_REG_NEW_USER, has been reserved for you. The UIN
is in the UIN field of the header. After reciption of this responce you have to
log in to the server with the new UIN to complete the registration (a normal
login procedure).
No parameters
SRV_LOGIN_REPLY 5A 00 (90)
This is sent from the server when it has recieved a CMD_LOGIN command
correctly. When you recieve this command, send over your contact list and
visible/invisible lists.
Parameters
Length Content (if fixed) Designation Description
4 bytes 8C 00 00 00 X1 Suggested KEEP_ALIVE interval.
2 bytes F0 00 X2 Unknown (dec: 240)
2 bytes 0A 00 X3 Timeout for resends.
2 bytes 0A 00 X4 Timeout for connection attempts. (?)
2 bytes 05 00 X5 Suggested number of resends.
4 bytes xx xx xx xx IP Your IP
4 bytes xx xx xx xx X6 Unknown
SRV_BAD_PASS 64 00 (100)
m
The password in the login packet was invalid. If you're certain it is corrent,
check the length of the password and make sure it's NULL terminated.
No parameters
SRV_USER_ONLINE 6E 00 (110)
A user on your contact list has changed his/her status so that he/she has
became visible to you. (i.e. changed from offline or invisible to something
different.)
Parameters
Length Content (if fixed) Designation Description
4 bytes xx xx xx xx UIN UIN of the user who changed status
4 bytes xx xx xx xx IP The user's IP address
4 bytes xx xx xx xx PORT The port the user is listening for connections on
4 bytes xx xx xx xx REAL_IP User's real IP address
1 byte xx X1 Unknown, usually 04
4 bytes xx xx xx xx STATUS User's new status, see CMD_STATUS_CHANGE
4 bytes xx xx xx xx X2 Unknown, possible the user's version
4 bytes xx xx xx xx X3 Unknown
4 bytes xx xx xx xx X4 Unknown
4 bytes xx xx xx xx X5 Unknown
4 bytes xx xx xx xx X6 Unknown
4 bytes xx xx xx xx X7 Unknown
SRV_USER_OFFLINE 78 00 (120)
A user on your contact list has changed his/her status to offline.
Parameters
Length Content (if fixed) Designation Description
4 bytes xx xx xx xx UIN UIN of the user who changed status
SRV_QUERY 82 00 (130)
Response to CMD_QUERY_SERVES and CMD_QUERY_ADDONS.
SRV_USER_FOUND 8C 00 (140)
A user matching the search criteria in a previously sent CMD_SEARCH_USER or
CMD_SEARCH_UIN command has been found. If several users were found, you will
recieve a packet for every one of them.
Parameters
Length Content (if fixed) Designation Description
4 bytes xx xx xx xx UIN UIN of the user found
2 bytes xx xx NICK_LENGTH Length of user's nickname
variable xx ... 00 NICK User's nickname
2 bytes xx xx FIRST_LENGTH Length of user's first name
variable xx ... 00 FIRST User's first name
2 bytes xx xx LAST_LENGTH Length of user's last name
variable xx ... 00 LAST User's last name
2 bytes xx xx EMAIL_LENGTH Length of the user's email address
variable xx ... 00 EMAIL User's email address
1 byte xx AUTHORIZE User's authorization status, see below
AUTHORIZE can contain either 00 or 01.
00 means that your client should request authorization before adding this user
to the contact list.
01 means that authorization is not required to add him/her to your contact list.
SRV_END_OF_SEARCH A0 00 (160)
No more users could be found, or too many user was found.
Parameters
Length Content (if fixed) Designation Description
1 byte xx TOO_MANY The search genarated too many hits
If TOO_MANY is 00, you have recieved all matching users in the database. If it
is 01, there are more users matching your query, but theese are not sent.
Currently the limit is at 40 users.
SRV_RECV_MESSAGE DC 00 (220)
This is sent during login, if there are messages for you at the server. (often
referred to as 'offline messages') Parameters
Length Content (if fixed) Designation Description
4 bytes xx xx xx xx UIN UIN of the sender
2 bytes xx xx YEAR The year the message was sent
1 byte xx MONTH The month the message was sent
1 byte xx DAY Day of month
1 byte xx HOUR Hour the message was sent
1 byte xx MINUTE Minutes
2 bytes xx xx MESSAGE_TYPE What kind of message it is (see below)
2 bytes xx xx MESSAGE_LENGTH Length of the text (including NULL)
variable xx ... 00 MESSAGE_TEXT Message text
MESSAGE_TYPE can have one of the following values: Message types
Designation Value Description
MSG_TEXT 01 00 Normal text message
MSG_URL 04 00 URL message
This message consists of two parts, separated by 0xFE. First the description of
the URL followed by the URL itself.
MSG_AUTH_REQ 06 00 Request authorization to add user to contact list
This message consists of five parts, separated by 0xFE. Nickname, first name, last name, email address and reason.
MSG_AUTH 08 00 Grant request to add user to contact list
MSG_USER_ADDED 0C 00 User (the recipent) has been added to contact list
This message consists of four parts, separated by 0xFE. Nickname, first name, last name and email address, in that order.
MSG_CONTACTS 13 00 Send contacts
This message consists of a number of nicknames and UINs separated by a 0xFE
byte. The first part of the message is the number of contacts (nickname/UIN
pairs) in the message. This number is stored in ASCII-code, and it is terminated
in the same way as the other parts, with 0xFE.
Sample URL message dump:
0000: 78 56 34 12 CF 07 04 0E 0D 07 04 00 16 00 4D 69 xV4...........Mi
0010: 72 61 62 69 6C 69 73 FE 77 77 77 2E 69 63 71 2E rabilis.www.icq.
0020: 63 6F 6D 00 com.
The coloured parts belong is the MESSAGE_TEXT. The green numbers shows the URL
description ('Mirabilis'). Blue numbers belongs to the URL is self. The red byte
(FE) separates theese two strings, and finally the yellow byte (00) is the NULL
termination.
The black part of the message contains this information:
UIN: 0x12345678
Date: 1999-04-14
Time: 13:07
Type: MSG_URL
Length: 22 bytes
SRV_UPDATE_SUCCESS E0 01 (480)
CMD_UPDATE_INFO successfully changed your user info.
SRV_UPDATE_FAIL EA 01 (490)
CMD_UPDATE_INFO has failed.
SRV_MULTI 12 02 (530)
Several packets sent at once. The server seems to use this packet whenever it
has more than one packet to send to you.
Parameters
Length Content (if fixed) Designation Description
1 byte xx NUM_PACKETS Number of packets
2 bytes xx xx SIZE_1 Size of the first packet
variable 05 00 ... PKT_1 The first packet
2 bytes xx xx SIZE_2 Size of the second packet
variable 05 00 ... PKT_2 The second packet
... ... ... ...
2 bytes xx xx SIZE_N Size of last packet
variable 05 00 ... PKT_N The last packet
The CHECK fields of the included packets are all set to NULL. Acknowledgement
needs to be done only to the SRV_MULTI, not to the encapsulated packets.
SRV_META_USER DE 03 (990)
Reply to CMD_META_USER.
Parameters
Length Content (if fixed) Designation Description
2 bytes xx xx SUBCMD Subcommand, see below for explanation
1 byte xx RESULT Result of the function, success or failure. See below
variable xx ... DATA The data you requested, See below.
RESULT
0x0A - Success
0x32 - Failure
SUBCMD and DATA
META_USER_FOUND - 9A 01 (xx) DATA for subcommand META_USER_FOUND
Length Content (if fixed) Designation Description
4 bytes xx xx xx xx UIN The user's UIN
2 bytes xx xx NICK_LENGTH Length of nickname
variable xx ... 00 NICK Nickname
2 bytes xx xx FIRST_LENGTH Length of first name
variable xx ... 00 FIRST First name
2 bytes xx xx LAST_LENGTH Length of last name
variable xx ... 00 LAST Last name
2 bytes xx xx EMAIL_LENGTH Length of email address
variable xx ... 00 EMAIL Email
1 byte xx AUTHORIZE Authorization status
2 bytes xx xx X2 Unknown
4 bytes xx xx xx xx X3 Unknown
AUTHORIZE can be either 0x00 or 0x01:
0x00 - This user wants you to request his/her authorization before adding to the
list.
0x01 - This user does not want you to ask him/her for permission before adding
him/her to your list.
META_ABOUT - E6 00 (xx) DATA for subcommand META_ABOUT
Length Content (if fixed) Designation Description
2 bytes xx xx ABOUT_LENGTH Length of about string
variable xx ... 00 ABOUT About string
META_USER_INFO - C8 00 (xx) DATA for subcommand META_USER_INFO
Length Content (if fixed) Designation Description
4 bytes xx xx xx xx UIN The user's UIN
2 bytes xx xx NICK_LENGTH Length of nickname
variable xx ... 00 NICK Nickname
2 bytes xx xx FIRST_LENGTH Length of first name
variable xx ... 00 FIRST First name
2 bytes xx xx LAST_LENGTH Length of last name
variable xx ... 00 LAST Last name
2 bytes xx xx PRIMARY_LENGTH Length of primary email address
variable xx ... 00 PRIMARY_EMAIL Primary email address
2 bytes xx xx SECONDARY_LENGTH Length of secondary email address
variable xx ... 00 SECONDARY_EMAIL Secondary email address
2 bytes xx xx OLD_LENGTH Length of old email address
variable xx ... 00 OLD_EMAIL Old email address
2 bytes xx xx CITY_LENGTH Length of city
variable xx ... 00 CITY City
2 bytes xx xx STATE_LENGTH Length of state
variable xx ... 00 STATE State
2 bytes xx xx PHONE_LENGTH Length of phone number
variable xx ... 00 PHONE Phone number
2 bytes xx xx FAX_LENGTH Length of fax number
variable xx ... 00 FAX Fax number
2 bytes xx xx STREET_LENGTH Length of street address
variable xx ... 00 STREET Street address
2 bytes xx xx CELL_LENGTH Length of cell phone number
variable xx ... 00 CELLULAR Cellular phone number
4 bytes xx xx xx xx ZIPCODE Zip (postal) code.
2 bytes xx xx COUNTRY Country code
1 byte xx TIMEZONE Time zone
1 byte xx AUTHORIZE Authorization status
1 byte xx WEBAWARE Show the user's online status on the web
1 byte xx HIDEIP Don't show the user's IP
AUTHORIZE can be either 0x00 or 0x01:
0x00 - This user wants you to request his/her authorization before adding to the
list.
0x01 - This user does not want you to ask him/her for permission before adding him/her to your list.
6. Client to Client Communication
Written By: Douglas F. McLaughlin
Introduction
This text will hopefully help explain
a lot of the details of ICQ's TCP
protocol version 2 (v2). Not all
available codes and packets have been
completely deciphered, however, these
packets are VERY rare and therefore hard
to intuit a specific meaning.
First of all, this text would not be possible
were it not for the help and hard work of a
few other people. A small portion of the
DEFINEs are based upon work done by Matt Smith
author of micq. Most of the basic format of
the TCP Message and Chat packets were worked
out by the author of Licq (whose name I can't
remember right now.) The basis for the TCP
File Direct packets comes from the source
code icqfile.cpp. This document and the final meshing of all this
information into one protocol was done by Douglas F. McLaughlin
author of STRICQ for the Amiga computer. (And Mirabilis said it
couldn't be done!) Please do not spread this text without applying
full credit to its author and the author's sources as mentioned
in the paragraph.
Finally, this document assumes a good working knowledge of opening and using
TCP sockets and how to manage multiple open sockets at once. This includes how
to use listen() sockets.
Starting with UDP
To begin working with TCP, you must start before your client ever logs into the ICQ server. At the
same time as the UDP socket is created, you need to also create a listen()ing TCP socket and obtain
its IP and port for sending with the initial login packet sent via UDP. Your initial IP can be
obtained by using gethostname() and then gethostbyname(). The PC ICQ clients always provide the client's
LAN IP in favor of any ISP provided IP. Also be sure to set the client
to client flag to 0x04 in the login packet so that other clients will know that your client is TCP capable.
ULONG TCP_MsgPort; /* Port your client will accept TCP connections on. */
char Password[8]; /* Password, max 8 characters, case sensitive. */
ULONG X1; /* Unknown. Use 0x00000000 for v2. */
ULONG TCP_MsgIP; /* IP Address your client will accept TCP connections on. */
UBYTE TCP_Flag; /* Is your client TCP capable? 0x04 = Yes, 0x06 = No. */
ULONG Status; /* Your client's status at login. See defines. */
ULONG TCP_Ver; /* The version of the TCP protocol used by the client. */
UWORD Seq_Login; /* One up for each login packet sent. */
ULONG X4; /* Unknown. Use 0x00000000 for v2. */
ULONG X5; /* Unknown. For best results use 0x007300D9 with v2. */
Before moving too far along, it must be noted that each type of connection
creates its own listen()ing socket. i.e. Message, Chat, and File connections
will each have their own dedicated listener. STRICQ follows the same convention
as the PC client in that the Message socket is created at 'go online' time and
the other two types are only created when that event occurs. A chat listen
socket is created only when someone requests a chat, the same for a file
send/receive.
Next we move to the S_USER_ONLINE (0x006E) packet. The important information
contained in this packet are the IP, Port, and TCP flag fields. The IP and
Port are obviously necessary for making a direct TCP connection. The IP address
is the IP that the ICQ server has extracted from the initial login UDP packet
header NOT the IP in the login packet itself. The Real IP is the IP provided
by the client in the login packet, most often this is just a copy of the first
IP, however, if the client found a LAN address, this will be the client's LAN
IP. Use the one byte TCP flag to determine whether a message packet should be
sent via TCP or UDP. If the flag is 0x04, attempt a TCP connect, otherwise
send the message via UDP to the server for final delivery as an online message.
Usually, if the client is not TCP capable, then some kind of firewall/proxy is
involved that blocks TCP connections.
ULONG UIN; /* The UIN of the user that is online. */
ULONG IP; /* The IP address of the client (LAN External.) */
ULONG Port; /* The Port to connect() with for sending messages. */
ULONG RealIP; /* The actual IP of the client machine (LAN Internal.) */
UBYTE TCP_Flag; /* TCP Flag, 0x04 = TCP Capable, 0x06 = Do not use TCP. */
ULONG Status; /* The status of the user at login. */
ULONG TCP_Ver; /* The version of the TCP protocol used by the client. */
Switch to TCP
Once the user has entered a message to be sent to another person and the client
determines the receiver is TCP capable and this is the first message sent to
the receiver, a TCP connection is to be initiated. The first order of business
is to use the IP
ort from the online packet and attempt a connect().
The TCP Init Packet
After a successful connect(), the TCP Init packet is sent that sends some needed information and basically just says, "Hello." Since we are assuming it is our client sending the first message and performed the connect(), it falls upon our end to start the ball rolling. The following packet is a general TCP Init packet and is sent for ALL types of sockets, Message, Chat, and File.
UBYTE Ident; /* Always 0xFF. */
UWORD Version; /* Version of the TCP protocol used. */
UWORD Revision; /* Revision of the TCP protocol version (Mac clients.) */
ULONG TCP_MsgPort; /* Port of the client's message listen() socket. This is
/* sent ONLY for message connects, otherwise NULL. */
ULONG UIN; /* User's UIN. */
ULONG TCP_MsgIP; /* IP address (LAN External.) */
ULONG TCP_RealIP; /* IP address (LAN Internal.) */
UBYTE TCP_Flag; /* TCP capable flag again, 0x04 = Yes, 0x06 = No. */
ULONG TCP_ChatFilePort; /* Port of the client's chat/port listen() socket. This
/* is sent only for chat/file connects, otherwise NULL. */
After any TCP packet is built, the length of the packet is sent first followed
by a second send() of the packet itself. The easiest way to read this from the
socket is to first read with a two-byte buffer, then perform a second read
with a buffer size equal to the value retrieved in the first read. Don't
forget that TCP is 'sizeless', you could only receive half of your packet,
or more than one packet at one time, this is why sending the actual packet
size first is so important. I leave it as an exercise of the reader how best
to read the packets from the socket.
The TCP Message Packet
No reply will be sent from the remote end to a TCP Init packet. Now, assuming
we are sending a simple message, the following message packet is sent
containing the actual message typed by our user.
ULONG UIN; /* Local UIN. */
UWORD Version; /* TCP protocol version being used. */
UWORD Command; /* Command. Always 0x07EE. See #DEFINEs. */
UWORD X1; /* Always 0x0000. */
ULONG UIN; /* Local UIN. Just in case you missed it the first time. */
UWORD Type; /* Message type. See #DEFINEs. */
UWORD MsgLen; /* Length of message. Be prepared to accept any size. */
char Message[]; /* The message text. */
ULONG TCP_MsgIP; /* LAN External IP. */
ULONG TCP_RealIP; /* LAN Internal IP. */
ULONG TCP_MsgPort; /* Port of the current message socket. */
UBYTE TCP_Flag; /* TCP Capable flag again. */
UWORD TCP_Status; /* The client's status. See #DEFINEs. */
UWORD MsgCommand; /* Message command. Usually 0x0010. See #DEFINEs. */
For a Chat Request packet ONLY, also add the following:
UWORD SessionLen; /* Length of the Chat_Session text. */
char Chat_Session[]; /* See the Chat Mode section for description. */
UWORD Chat_RevPort; /* See the Chat Mode section for description. */
UWORD Chat_X2; /* Always 0x0000, padding for port. */
ULONG Chat_Port; /* See the Chat Mode section for description. */
For a FileDirect Request packet ONLY, also add the following:
UWORD File_RevPort; /* Always 0x0000 in the message packet. */
UWORD File_X3; /* Always 0x0000, padding for the port. */
UWORD FileNameLen; /* Length of the filename text. */
char File_Name[] /* Name of the file being sent or a file count, '5 files,' if
/* more than one file is being sent. */
ULONG File_Size; /* The total size in bytes of all files being sent. */
ULONG File_Port; /* Always 0x00000000 in the message packet. */
Finally, for all packets add the following:
ULONG TCP_Sequence; /* The first TCP packet sent after program startup will have
the sequence 0xFFFFFFFE. The sequence is then decremented
by one for EVERY TCP packet sent AND received regardless of
who the sender or receiver is and does not include ACK
packets. */
The Message Ack Packet
Once the remote client receives the TCP Message packet and the packet was correctly
formatted, an ACK packet will be sent. The PC client's message window will not
go away and the little face window will continue to spin until this ACK packet
is received back from the remote client. The ACK packet is almost exactly the
same as the received packet with several important changes.
ULONG UIN; /* Local UIN. */
UWORD Version; /* TCP protocol version being used. */
UWORD Command; /* Commands. Always 0x07DA. See #DEFINEs. */
UWORD X1; /* Always 0x0000. */
ULONG UIN; /* Local UIN. Just in case you missed it the first time. */
UWORD Type; /* Message type being ACK'd. See #DEFINEs. */
UWORD MsgLen; /* Length of auto-reply. Be prepared to accept any size. */
char Message[]; /* The auto-reply text. */
ULONG TCP_MsgIP; /* LAN External IP. */
ULONG TCP_RealIP; /* LAN Internal IP. */
ULONG TCP_MsgPort; /* Port of the current message socket. */
UBYTE TCP_Flag; /* TCP Capable flag again. */
UWORD TCP_Status; /* The client's status. See #DEFINEs. */
UWORD MsgCommand; /* Message command. Usually 0x0000. See #DEFINEs. */
For a Chat Request ACK packet ONLY, also add the following:
UWORD SessionLen; /* Length of the Chat_Session text. */
char Chat_Session[]; /* See the Chat Mode section for description. */
UWORD Chat_RevPort; /* See the Chat Mode section for description. */
UWORD Chat_X2; /* Always 0x0000, padding for port. */
ULONG Chat_Port; /* See the Chat Mode section for description. */
For a FileDirect Request ACK packet ONLY, also add the following:
UWORD File_RevPort; /* Port of the FileDirect listen() socket in network order. */
UWORD File_X3; /* Always 0x0000, padding for the port. */
UWORD FileNameLen; /* Always 0x0001. */
char File_Name[] /* Always 0x00. */
ULONG File_Size; /* Always 0x00000000. */
ULONG File_Port; /* Port of the FileDirect listen() socket in intel order. */
Finally, for all packets add the following:
ULONG TCP_Sequence; /* The TCP Sequence of the message being ACK'd. */
Here is a list of changes or items to copy while creating the ACK packet:
The Message Command changes from 0x07EE to 0x07DA.
The Message Type is copied from the original message packet.
Any configured Auto-Reply will be sent with this packet.
The Message Command Type changes from 0x0010 to 0x0000.
If the receiver refuses the request (Chat or File) the TCP_Status field will be set to 0x0001.
The File ports are sent as NULL in the original packet and actually filled in to the ACK packet
by the receiver. For Chat port handling, see the Chat Mode description.
The Filename of a file send packet is set to NULL for the ACK.
The Filesize of a file send packet is set to NULL for the ACK.
The TCP Message Sequence is copied from the original message packet.
TCP Message Packet Related #defines
/* TCP Commands */
#define TCP_CANCEL 0x07D0 /* 2000 TCP cancel previous file/chat request */
#define TCP_ACK 0x07DA /* 2010 TCP acknowledge message packet */
#define TCP_MESSAGE 0x07EE /* 2030 TCP message */
/* TCP Message Types */
#define MSG_MSG 0x0001 /* 0001 Used to send a normal message */
#define MSG_CHAT 0x0002 /* 0002 Used to initiate a Chat session */
#define MSG_FILE 0x0003 /* 0003 Used to initiate a FileDirect session */
#define MSG_URL 0x0004 /* 0004 Used to send a URL message */
#define MSG_REQ_AUTH 0x0006 /* 0006 Used to request authorization to add to contact list */
#define MSG_DENY_AUTH 0x0007 /* 0007 Used to deny authorization to add to contact list */
#define MSG_GIVE_AUTH 0x0008 /* 0008 Used to grant authorization to add to contact list */
#define MSG_ADDED 0x000C /* 0012 Used to notify that your UIN was added to a contact list */
#define MSG_WEB_PAGER 0x000D /* 0013 Used to receive a web pager message from the white page */
#define MSG_EMAIL_PAGER 0x000E /* 0014 Used to receive an EMail message from UIN@pager.mirabilis.com */
#define MSG_ADDUIN 0x0013 /* 0019 Used to send UINs from one client to another */
#define MSG_GREETING 0x001A /* 0026 Used to send a greeting card */
#define MSG_READAWAY 0x03E8 /* 1000 Used to retrieve a clients Away message */
#define MSG_READOCCUPIED 0x03E9 /* 1001 Used to retrieve a clients Occupied message */
#define MSG_READNA 0x03EA /* 1002 Used to retrieve a clients Not Available msg */
#define MSG_READDND 0x03EB /* 1003 Used to retrieve a clients Do Not Disturb msg*/
#define MSG_READFFC 0x03EC /* 1004 Used to retrieve a clients Free For Chat msg */
#define MSGF_MASS 0x0800 /* 2048 This message was sent to more than one UIN. This is a flag and is
OR'd with one of the above */
/* TCP Message Command Types */
#define TCP_MSG_AUTO 0x0000 /* TCP message ACK and Auto-Reply */
#define TCP_MSG_REAL 0x0010 /* TCP message */
#define TCP_MSG_LIST 0x0020 /* TCP message sent to the contact list */
#define TCP_MSG_URGENT 0x0040 /* TCP message sent urgently */
/* The following are flags and are OR'd with the above Command Types */
#define TCP_MSGF_S_INVISIBLE 0x0080 /* The message sender is Invisible */
#define TCP_MSGF_S_AWAY 0x0100 /* The message sender is Away */
#define TCP_MSGF_S_OCCUPIED 0x0200 /* The message sender is Occupied */
#define TCP_MSGF_S_NA 0x0800 /* The message sender is Not Available */
#define TCP_MSGF_S_DND 0x1000 /* The message sender is Do Not Disturb */
/* TCP Message Status' */
#define TCP_STAT_ONLINE 0x0000
#define TCP_STAT_REFUSE 0x0001
#define TCP_STAT_AWAY 0x0004
#define TCP_STAT_OCCUPIED 0x0009
#define TCP_STAT_DND 0x000A
#define TCP_STAT_NA 0x000E
Other Forms of the TCP Message Packet
The TCP Cancel packet is formatted just
like a normal message, file, or chat
packet. It is sent if the user presses
the cancel button after sending the
message, file, or chat message and before
the receiving end has sent an ACK packet.
A cancel packet will have all its fields
set to NULL, no text or port information
will be sent. The Message Type will be the
same as the original message and the Message
Command Type will be 0x0010. Also, the TCP
Message Sequence will be the same as the
original message.
The MSG_READxxx Message types are ONLY received
when the local client is in that particular
mode. The Win95 client can only send one Message
Type at a time depending upon the status of the
client the message is being read from. What this
means is that if your local client is in AWAY
status mode, you will ONLY receive a message type
of 0x03E8. Your client's response when receiving
one of these packets is to merely grab the
configured message and send it with the ACK. The
PC clients do NOT notify the user when one of these
messages are received.
Reverse TCP Connections
Before going into Chat and File negotiation, one
more very important aspect of TCP connection negotiation
involves what I call the Reverse TCP connection. This
is a UDP packet containing IP and Port information that
is sent when client A wants to connect to client B, but
for some reason, be it a firewall or whatever, the connect()
failed. Here is the breakout of the Reverse TCP connect UDP
packet as created by the sender.
#define TCP_REQUEST 0x015E
UWORD UDP_Ver; /* Always 0x0002, UDP Version. */
UWORD UDP_Cmd; /* 0x015E TCP_REQUEST packet. */
UWORD UDP_Seq; /* UDP packet Sequence. */
ULONG UIN; /* Receiver's UIN. */
ULONG Remote_UIN; /* Remote UIN of requester. */
ULONG IP; /* Remote client's LAN External IP. */
ULONG Port; /* listen() Port in INTEL order to connect() with. */
UBYTE TCP_Flag; /* Always 0x04. TCP Capable flag again. */
ULONG Port2; /* Another Port in INTEL order. Not sure what this is for. */
ULONG Port3; /* listen() Port in INTEL order to connect() with, again. */
UWORD TCP_Ver; /* TCP Protocol version of sender. */
The receiver will receive the above packet with this additional data:
ULONG X1; /* Always 0x00000000. Unknown. */
ULONG X2; /* Always 0x00000000. Unknown. */
This is the packet that client A builds and sends to client B via
the server using UDP. Once client B receives this packet from the
server it will have 2 ULONGs of 0x00000000 appended to the end of the
packet making it 8 bytes larger than what the sender sent. I have never
seen anything other than all NULLs for these extra bytes at the receiver
end.
Here is the logic flow:
User A types in a message to send to user B.
Client A attempts to connect() with client B and fails.
Client A builds the TCP_REQUEST packet and sends to the server.
Client B receives the TCP_REQUEST packet with client A's IP
ort.
Client B attempts to connect() to client A and succeeds.
Client B sends the TCP Init packet to client A.
Client A sends the message typed by user A in step 1.
User B reads the message.
The client that performs a successful connect() (client B)
sends the TCP Init packet. After that, packet flow resumes as
normal just as if client A had actually performed the
connect().
The flow is essentially the same for Chat and File connections
with a few small changes. In the above example, client B knows
the Reverse TCP connect is for an incoming message because
client B did not ACCEPT anything from client A. This is different
for Chat and File. Like so:
User A requests to chat (or send a file) with user B.
User B accepts the request of user A and client B sends the necessary
IP
ort information along with the Message ACK packet back to
client A.
Client A attempts a connect() to the supplied IP
ort and fails.
Client A builds the TCP_REQUEST packet and sends to the server.
Client B receives the TCP_REQUEST packet with client A's IP
ort.
Client B attempts to connect() to client A and succeeds.
Client B sends the TCP Init packet to client A.
Client A sends the first actual Chat or File Init packet to client B.
Client B responds with the appropriate next packet.
In this example, client B knows what to expect because the Chat or File
Message packet has already arrived and been accepted by the user.
File Direct Protocol
After following the above described methods to negotiate, open, and send
the TCP Init packet, there are only seven packet types associated with
the File Direct Protocol. The first byte of the packets ranges from 0x00
to 0x06. The client sending the file(s) starts with packet 0x00, the
receiver replies with packet 0x01, sender sends 0x02, receiver sends 0x03.
Packets 0x04 and 0x05 are special packets and can be sent by either client
at ANY TIME during the transfer. Packet 0x06 contains the actual 2048 bytes
of the file being sent. If more than one file is to be sent, after each
file is finished and more files remain, the sender will again send packet
0x02 and the receiver will reply with 0x03. Here are the steps to send two
files:
S = Sender, R = Receiver.
S:0x00
R:0x01
S:0x02
R:0x03
S:0x06 (As many times to transfer the file as needed.)
S:0x02
R:0x03
S:0x06 (Again, as many times as necessary.)
S:Close the file direct socket.
Here are the packet break outs:
UBYTE 0x00 Packet.
DWORD 0x00000000 X1 Unknown.
DWORD Total number of all files to be sent.
DWORD Total bytes of all files to be sent.
DWORD Sender's speed of transfer. 0x00 to 0x64 where 0x00 = PAUSE and 0x64 =
No packet delay. Each count represents a .05 second delay where 0x63
is a .05 second delay, 0x62 is a .10 second delay, 0x61 is a .15
second delay, etc. before sending the next packet.
WORD Length of Nick plus NULL.
STRING Sender's Nick.
---
UBYTE 0x01 Packet.
DWORD Receiver's speed.
WORD Length of Nick plus NULL.
STRING Receiver's Nick.
---
UBYTE 0x02 Packet.
UBYTE 0x00 X1 Unknown.
WORD Length of filename.
STRING Name of next file to be sent.
WORD Length of text. Always 0x01.
STRING Text. Unknown. Always just the NULL.
DWORD Size of the next file to be sent.
DWORD 0x00000000 X2 Unknown.
DWORD Sender's speed. (Yes, again...)
---
UBYTE 0x03 Packet.
DWORD Size of file on receiver's end. Any number here other than
0x00000000 will cause the sender to skip the specified number of
bytes before sending the first packet. Used to implement file
transfer resume.
DWORD 0x00000000 X1 Unknown.
DWORD Receiver's speed. (Yes, again...)
---
UBYTE 0x04 Packet.
DWORD Possibly the current file number being transfered. Upon receipt of
this packet the sender will stop sending the current file and
either start on the next file or close the socket.
---
UBYTE 0x05 Packet.
DWORD Change speed. Can be sent by either client at any time during a
file transfer.
---
UBYTE 0x06 Packet.
... From 1 to 2048 bytes of the file being transferred. The client
should always send 2048 bytes of the file until the final packet.
Chat Mode Protocol
User to user chat mode
or single-chat is much
more complicated than
anything else in the ICQ
protocol. Add in multi-chat
and the whole process
becomes down right convoluted.
It has taken this author
several months to work
out just how the whole
framework of single-chat and
multi-chat all meshed together. After much study it finally
became clear that the listen() port used was key to understanding
the whole process. It turns out that single-chat is actually a
striped down multi-chat, not, as was originally thought, multi-chat
being a special case of, or built on top of, single-chat.
As stated, the listen() port is key as it controls who connects with
whom and whether or not the chat mode is single or multi. From here
on out, a “Chat Session” will refer two or more clients connected
in such a way that the sent and received text from all members will
be seen within a single window. Each chat listen() port controls
its own chat session. In other words, each chat session will have
exactly one chat listen() port no matter how many users are participating
in the chat session.
To initiate single-chat mode, a user requests another user to enter chat.
The requester's client will create a chat listen() port at this time,
however, it will not be passed to the receiver in the message packet. (
This is the listen() port used if someone else wants to join this session.)
Next, the receiver accepts and the receiver's client opens a new chat
session listen() socket and passes its port in the message ACK back to
the requester. The requester's client then attempts a connect() on that
port. The connection is made, the initial setup packets are passed back
and forth and single-chat mode is entered.
Here is the chat mode section of the message packet as sent by the requester:
UWORD SessionLen; /* Always 0x0001 for single-chat. */
char Chat_Session[]; /* Always 0x00 for single-chat. */
UWORD Chat_RevPort; /* Always 0x0000 in the message packet. */
UWORD Chat_X2; /* Always 0x0000, padding for port. */
ULONG Chat_Port; /* Always 0x0000 in the message packet. */
Here is the chat mode section of the message ACK packet:
UWORD SessionLen; /* Always 0x0001 in the ACK packet. */
char Chat_Session[]; /* Always 0x00 in the ACK packet. */
UWORD Chat_RevPort; /* The chat listen() port in network order. */
UWORD Chat_X2; /* Always 0x0000, padding for port. */
ULONG Chat_Port; /* The chat listen() port in intel order. */
The first method to initiate multi-chat mode starts when a user that is
already in single-chat session (as described above) requests another user
to join the chat session that is already in progress. The initial message
packet will contain a comma separated list of all users already in the chat
session, i.e. “User1, User2, User3”, and port of the listen() socket that
was created when the requester's client first sent/received a chat request
message packet. Next, the receiver accepts and the receiver's client opens a
chat listen() socket and its port is passed back in the ACK packet. After
sending the message ACK packet, the receiver then attempts a connect() on the
port passed in the message packet. The connection is made and the initial
setup packets are passed back and forth. In these setup packets, the
requester's client will pass some information on the other clients in the
chat session. This information allows the receiver's client to attempt
connect()s with those other users in the chat session. Once all the
connections are made and the setup packets are passed between the receiver's
client and the other members of the chat session, a multi-chat session is
established between all users.
Here is the chat mode section of the message packet as sent by the requester:
UWORD SessionLen; /* Length of the Chat_Session text. */
char Chat_Session[]; /* Comma separated list of all those in the session. */
UWORD Chat_RevPort; /* Chat listen() port for this session in network order. */
UWORD Chat_X2; /* Always 0x0000, padding for port. */
ULONG Chat_Port; /* Chat listen() port for this session in intel order. */
Here is the chat mode section of the message ACK packet:
UWORD SessionLen; /* Always 0x0001 in the ACK packet. */
char Chat_Session[]; /* Always 0x00 in the ACK packet. */
UWORD Chat_RevPort; /* Chat listen() port for this session in network order. */
UWORD Chat_X2; /* Always 0x0000, padding for port. */
ULONG Chat_Port; /* Chat listen() port for this session in intel order. */
The next method used to enter into multi-chat is when a user requests to chat
with a receiver that is already in a chat session. In this instance, the chat
portion of the message packet will be used in the exact same manner as if
initiating a normal single-chat session. The requesting client does not know
or care that the receiver is already participating in a chat session. Once
the receiver receives the chat request, the user selects the join option and
chooses a chat session already in progress. At this point, instead of the
receiving client making a new chat listen() socket, it passes the port of the
chat listen() socket previously created when the first chat session was
initiated. (Now, if the receiving user had NOT chosen the join option, a new
listen() socket would be created and a single-chat session would result with
the receiver having two chat windows open at once.) When the requesting client
receives the ACK packet, it attempts a connect() on that port. After the connect
succeeds, the chat initialization packets are passed back and forth. At this
point the requesting client learns of the other clients also in the chat
session and attempts to connect() with each of the other clients. After all
this a multi-chat session is in progress.
Finally, the last case is where both the requester and receiver are both in a
chat session already. The PC ICQ clients do not allow for the merging of two
already in progress chat sessions. If the requesting user selects the Join
option, the receiver will not be given the Join option, and if the requester
does not select Join, then the receiver is allowed the Join option. Then one
of the above three cases will be the resulting method used to initiate a chat
session.
Here are the chat initialization packets in detail. There are three packets passed
during the initialization phase. The client that performed the connect() will
send the first packet (with the exception of when a Reverse TCP Connect is
used as stated above.) The receiver will respond with the second packet, and
the requester sends the third and final packet. At this point the socket
becomes a character stream. That portion of the chat mode will be described
later.
First chat packet:
ULONG HandShake; /* Always 0x00000064. ICQ99b uses 0x00000065. */
ULONG HiVersion; /* Negative of the TCP protocol version. V2 = 0xFFFFFFFE */
ULONG UIN; /* Local UIN. */
UWORD NickLen; /* Length of the nick. */
char Nick[21]; /* Local nick. */
UWORD RevPort; /* Chat session port in network order. */
ULONG TextColor; /* Text or font color in the form 0x00RRGGBB. */
ULONG BackColor; /* Chat window background color in 0x00RRGGBB form. */
UBYTE X1; /* Always 0x00. */
Second chat packet:
ULONG HandShake; /* Always 0x00000064. ICQ99b uses 0x00000065. */
ULONG UIN; /* Local UIN. */
UWORD NickLen; /* Length of the nick. */
char Nick[21]; /* Local nick. */
ULONG TextColor; /* Text or font color in 0x00RRGGBB form. */
ULONG BackColor; /* Background color in 0x00RRGGBB form. */
UWORD Version; /* Version of TCP protocol used by the client. */
UWORD X1; /* Revision of the TCP protocol, used by Mac clients. */
ULONG Port; /* Chat session port in intel order. */
ULONG IP; /* LAN External. */
ULONG RealIP; /* LAN Internal. */
UBYTE TCP_Flag; /* TCP capable flag again. */
UWORD X2; /* Random, unique chat session identifier, use unknown. */
ULONG FontSize; /* Size of the font. */
ULONG FontFamily; /* Font family? Used for font substitution? */
UWORD FontLen; /* Length of font name text. */
char FontName[]; /* Font name. */
UWORD X3; /* Usually 0x0002. Unknown. */
UBYTE Count; /* For single-chat, always 0x00. When entering a chat session
already in progress, this is a count of all other clients in
the chat session. */
For single chat mode, this packet ends here with a Count of 0x00. When entering a chat
session already in progress, Count will be greater than 0x00. For each other
client in the chat session the following data will be appended to the second
chat packet:
UWORD Version; /* Version of the TCP protocol used by the client. */
UWORD X1; /* Revision of the TCP protocol, used by Mac clients. */
ULONG Port; /* Chat session port in intel order. */
ULONG UIN; /* UIN of the client being referenced. */
ULONG IP; /* LAN External. */
ULONG RealIP; /* LAN Internal. */
UWORD RevPort; /* Chat session port in network order. */
UBYTE TCP_Flag; /* TCP Capable flag. */
UWORD X2; /* Random, unique chat session identifier, use unknown. */
ULONG HandShake; /* Always 0x00000064. ICQ99b uses 0x00000065. */
It should be stated that the above additional data added to the second chat packet
will be data that was stored during a previous chat initialization phase and
has nothing to do with the client currently being connected to. Upon receipt
of this additional data, the client will attempt connect() with the supplied
IP and port. At this point a normal chat initialization phase will begin with
each of these additional clients. Also, each of these clients will send an
extended second packet containing the data of all the other clients in the
current session. Be prepared to ignore the UINs of those clients in which a
connection has already been established.
Third chat packet:
UWORD Version; /* Version of the TCP protocol used by the client. */
UWORD X1; /* Revision of the TCP protocol, used by Mac clients. */
ULONG Port; /* Chat listen() port in intel order. */
ULONG IP; /* LAN External IP. */
ULONG RealIP; /* LAN Internal IP. */
UBYTE TCP_Flag; /* TCP Capable flag again. */
UWORD X2; /* Random, unique chat session identifier, use unknown. */
ULONG FontSize; /* Size of the font. */
ULONG FontFamily; /* Font family? Used for font substitution? */
UWORD FontLen; /* Length of font name. */
char FontName[]; /* Font name. */
UWORD X3; /* Usually 0x0002. Unknown. */
It is unknown what the random number is in the chat packets. However, the PC ICQ clients will only make one number for each chat session. If another, separate, chat session is started, then a new random number will be generated.
To be continued...
7. Calculating the Checkcode
The checkcode is calculated before encrypting the packet.
Calculate NUMBER1.
B8 = Byte at position 8 of the packet. (starting at position 0)
B4 = Byte at position 4 of the packet.
B2 = Byte at position 2 of the packet.
B6 = Byte at position 6 of the packet.
Now put theese parts together and call them NUMBER1:
NUMBER1 = 0x B8 B4 B2 B6 (B8 = MSB, B6 = LSB)
Here's a fragment of C-code that will take care of this:
unsigned long number1;
number1 = packet[8];
number1 <<= 8;
number1 |= packet[4];
number1 <<= 8;
number1 |= packet[2];
number1 <<= 8;
number1 |= packet[6];
Calculate the following.
PL = Packet length
R1 = A random number beetween 0x18 and PL
R2 = Another random number beetween 0 and 0xFF (modulus 0x100)
C-code example: (assuming that pl holds the packet length)
int r1, r2;
r1 = 0x18 + rand() % (PL - 0x18);
r2 = rand() % 0x100;
Calculate NUMBER2.
X4 = R1
X3 = NOT (BYTE at pos X4 in the packet)
X2 = R2
X1 = NOT (BYTE at pos X2 in the TABLE) (see TABLE section)
NUMBER2 = 0x X4 X3 X2 X1 (X4 = MSB, X1 = LSB)
C-code example:
unsigned long number2;
number2 = r1;
number2 <<= 8;
number2 |= packet[r1];
number2 <<= 8;
number2 |= r2;
number2 <<= 8;
number2 |= table[r2];
number2 ^= 0xff00ff;
You can now calculate the checkcode.
CHECKCODE = NUMBER1 XOR NUMBER2
C example:
unsigned long cc = number1 ^ number2;
The Table
The algorithmes use a table of constants to found some numbers.
TABLE[X] mean data at position X in the table (starting at position 0).
POS DATA ASCII
--- ----------------------------------------------- ----------------
00 - 59 60 37 6B 65 62 46 48 53 61 4C 59 60 57 5B 3D Y`7kebFHSaLY`W[=
10 - 5E 34 6D 36 50 3F 6F 67 53 61 4C 59 40 47 63 39 ^4m6P?ogSaLY@Gc9
20 - 50 5F 5F 3F 6F 47 43 69 48 33 31 64 35 5A 4A 42 P__?oGCiH31d5ZJB
30 - 56 40 67 53 41 07 6C 49 58 3B 4D 46 68 43 69 48 V@gSA.lIX;MFhCiH
40 - 33 31 44 65 62 46 48 53 41 07 6C 69 48 33 51 54 31DebFHSA.liH3QT
50 - 5D 4E 6C 49 38 4B 55 4A 62 46 48 33 51 34 6D 36 ]NlI8KUJbFH3Q4m6
60 - 50 5F 5F 5F 3F 6F 47 63 59 40 67 33 31 64 35 5A P___?oGcY@g31d5Z
70 - 6A 52 6E 3C 51 34 6D 36 50 5F 5F 3F 4F 37 4B 35 jRn.Q4m6P__?O7K5
80 - 5A 4A 62 66 58 3B 4D 66 58 5B 5D 4E 6C 49 58 3B ZJbfX;MfX[]NlIX;
90 - 4D 66 58 3B 4D 46 48 53 61 4C 59 40 67 33 31 64 MfX;MFHSaLY@g31d
A0 - 55 6A 32 3E 44 45 52 6E 3C 31 64 55 6A 52 4E 6C Uj2.DERn.1dUjRNl
B0 - 69 48 53 61 4C 39 30 6F 47 63 59 60 57 5B 3D 3E iHSaL90oGcY`W[=.
C0 - 64 35 3A 3A 5A 6A 52 4E 6C 69 48 53 61 6C 49 58 d5::ZjRNliHSalIX
D0 - 3B 4D 46 68 63 39 50 5F 5F 3F 6F 67 53 41 25 41 ;MFhc9P__?ogSA%A
E0 - 3C 51 54 3D 5E 54 5D 4E 4C 39 50 5F 5F 5F 3F 6F .QT=^T]NL9P___?o
F0 - 47 43 69 48 33 51 54 5D 6E 3C 31 64 35 5A 00 00 GCiH3QT]n.1d5Z..
--- ----------------------------------------------- ----------------
Example : TABLE[0] = 0x59
TABLE[0xF2] = 0x69
Note: A lot of UDP packet was check to recreate this table, but some
data may be incorrect.
The Table in C
static const BYTE table[] = {
0x59, 0x60, 0x37, 0x6B, 0x65, 0x62, 0x46, 0x48,
0x53, 0x61, 0x4C, 0x59, 0x60, 0x57, 0x5B, 0x3D,
0x5E, 0x34, 0x6D, 0x36, 0x50, 0x3F, 0x6F, 0x67,
0x53, 0x61, 0x4C, 0x59, 0x40, 0x47, 0x63, 0x39,
0x50, 0x5F, 0x5F, 0x3F, 0x6F, 0x47, 0x43, 0x69,
0x48, 0x33, 0x31, 0x64, 0x35, 0x5A, 0x4A, 0x42,
0x56, 0x40, 0x67, 0x53, 0x41, 0x07, 0x6C, 0x49,
0x58, 0x3B, 0x4D, 0x46, 0x68, 0x43, 0x69, 0x48,
0x33, 0x31, 0x44, 0x65, 0x62, 0x46, 0x48, 0x53,
0x41, 0x07, 0x6C, 0x69, 0x48, 0x33, 0x51, 0x54,
0x5D, 0x4E, 0x6C, 0x49, 0x38, 0x4B, 0x55, 0x4A,
0x62, 0x46, 0x48, 0x33, 0x51, 0x34, 0x6D, 0x36,
0x50, 0x5F, 0x5F, 0x5F, 0x3F, 0x6F, 0x47, 0x63,
0x59, 0x40, 0x67, 0x33, 0x31, 0x64, 0x35, 0x5A,
0x6A, 0x52, 0x6E, 0x3C, 0x51, 0x34, 0x6D, 0x36,
0x50, 0x5F, 0x5F, 0x3F, 0x4F, 0x37, 0x4B, 0x35,
0x5A, 0x4A, 0x62, 0x66, 0x58, 0x3B, 0x4D, 0x66,
0x58, 0x5B, 0x5D, 0x4E, 0x6C, 0x49, 0x58, 0x3B,
0x4D, 0x66, 0x58, 0x3B, 0x4D, 0x46, 0x48, 0x53,
0x61, 0x4C, 0x59, 0x40, 0x67, 0x33, 0x31, 0x64,
0x55, 0x6A, 0x32, 0x3E, 0x44, 0x45, 0x52, 0x6E,
0x3C, 0x31, 0x64, 0x55, 0x6A, 0x52, 0x4E, 0x6C,
0x69, 0x48, 0x53, 0x61, 0x4C, 0x39, 0x30, 0x6F,
0x47, 0x63, 0x59, 0x60, 0x57, 0x5B, 0x3D, 0x3E,
0x64, 0x35, 0x3A, 0x3A, 0x5A, 0x6A, 0x52, 0x4E,
0x6C, 0x69, 0x48, 0x53, 0x61, 0x6C, 0x49, 0x58,
0x3B, 0x4D, 0x46, 0x68, 0x63, 0x39, 0x50, 0x5F,
0x5F, 0x3F, 0x6F, 0x67, 0x53, 0x41, 0x25, 0x41,
0x3C, 0x51, 0x54, 0x3D, 0x5E, 0x54, 0x5D, 0x4E,
0x4C, 0x39, 0x50, 0x5F, 0x5F, 0x5F, 0x3F, 0x6F,
0x47, 0x43, 0x69, 0x48, 0x33, 0x51, 0x54, 0x5D,
0x6E, 0x3C, 0x31, 0x64, 0x35, 0x5A, 0x00, 0x00,
};
8. Encrypting the packet
For a more detailed description, read Sebastien Dault's document.
Follow theese steps:
Calculate the Checkcode (see "Calculating the Checkcode")
Set PL = Packet length
Calculate the encryption code:
CODE = (LONG) (PL * 0x68656C6C) + CHECKCODE (flush the overflow)
For every longword (32 bits) in the packet, starting with 0x0A, XOR
the longword with the CODE previously calcualted added to the byte at
the corresponding position in the table. (eg. the longword at 0x0A in
the packet should be XORed with the byte at position 0x0A in the table
added to CODE.)
Now the packet is encypted. All we have to now is to insert the checkcode
into the packet so the server will be able to decrypt it. The server excpects
this code to be scrambled as follows:
Scramble the checkcode
Before inserting the checkcode you have to move the bits around a little. It
can be done like this:
A1 = CHECKCODE AND 0x0000001F
A2 = CHECKCODE AND 0x03E003E0
A3 = CHECKCODE AND 0xF8000400
A4 = CHECKCODE AND 0x0000F800
A5 = CHECKCODE AND 0x041F0000
A1 = A1 SHL 0x0C (SHL = Bitwise shift left)
A2 = A2 SHL 0x01
A3 = A3 SHR 0x0A (SHL = Bitwise shift right)
A4 = A4 SHL 0x10
A5 = A5 SHR 0x0F
CHECKCODETOINSERT = A1 + A2 + A3 + A4 + A5
Insert the checkcode into the packet at pos 0x14.
In C-code it could look like this:
/*
Encrypting the packet.
Assuming that checkcode has been calculated as previously
described, and that pl = packet length.
The packet to encrypt is pointed to by pkpptr.
*/
code = pl * 0x68656c6c + checkcode;
for(pos=0xa;pos < (pl + 3);pos++)
{
pktptr[pos]^ = code + table[pos & 0xFF];
}
/*
Scrambling the checkcode.
Assuming that cc holds the checkcode.
*/
ULONG a[6];
a[1] = cc & 0x0000001F;
a[2] = cc & 0x03E003E0;
a[3] = cc & 0xF8000400;
a[4] = cc & 0x0000F800;
a[5] = cc & 0x041F0000;
a[1] <<= 0x0C;
a[2] <<= 0x01;
a[3] >>= 0x0A;
a[4] <<= 0x10;
a[5] >>= 0x0F;
checkcodetoinsert = a[1] + a[2] + a[3] + a[4] + a[5];
谁有兴趣翻译成中文,善莫大蔫