########################################################################## Title: Very very quick and practical explanation to the UnrealTournament 2003 heartbeat method 0.1.2 Authors: Luigi Auriemma e-mail: aluigi@autistici.org web: aluigi.org ########################################################################## TCP connection: ut2003master2.epicgames.com:28902 UDP: ut2003master2.epicgames.com:28902 ########################################################################## 1) server -> client (TCP) "\x07\x00\x00\x00\x06\x31\x30\x30\x38\x33\x00" | | | | | challenge number (10083 in this case) | length of the data below Total length of the data (without the first 32 bits) ########################################################################## 2) client -> server (TCP) --- 5a 00 00 00 21 63 34 34 P..°þ...Z...!c44 0040 61 37 62 37 62 31 36 32 34 65 39 64 34 35 39 63 a7b7b1624e9d459c 0050 32 32 66 61 63 36 31 64 63 39 64 63 63 00 21 64 22fac61dc9dcc.!d 0060 39 64 31 64 35 61 65 35 65 35 35 39 61 31 61 33 9d1d5ae5e559a1a3 0070 32 66 61 33 32 65 38 64 30 31 38 39 35 62 34 00 2fa32e8d01895b4. 0080 07 53 45 52 56 45 52 00 9e 08 00 00 ff ff ff ff .SERVER..... 0090 06 04 69 74 74 00 ..itt. --- - 0x0000005a is the length of the data block - 0x21 is the length of the first hash - MD5 hash of the client's cdkey. Example: hash of "UT2DEM-UT2DEM-UT2DEM-UT2DEM" (without " naturally) - 0x21 is the length of the second hash - MD5 hash of the client's cdkey plus the challenge number sent by the server in the previous packet. Example: hash of "UT2DEM-UT2DEM-UT2DEM-UT2DEM10083" - 0x07 is the size of the next test string - SERVER is a string (probably means that the client is a game server) - "\x0e\x08\x00\x00" it is the game version (2206 that is the demo ver) - "\xff\xff\xff\xff\x06" I don't know what it is but it is not important - 0x04 length of the language string - itt is the italian language ########################################################################## 3) server -> client (TCP) "\x0a\x00\x00\x00\x09\x41\x50\x50\x52\x4f\x56\x45\x44\x00" | | | | | "APPROVED" (if it is different means that the | | checksums previously sent by the client are not | | corrects and the connection will be interrupted) | length of "APPROVED" total length ########################################################################## 4) client -> server (TCP) "\x08\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" | | | | | I don't know | I don't know total length ########################################################################## 5) server -> client (TCP) "\x06\x00\x00\x00\x00\x00\xbc\x27\x00\x00" | | | | | ID to use for the heartbeat registration | | (keep it in mind until the end of these steps) | packet number requested (0 in this case) total length ########################################################################## 6) client -> server (UDP) [source port is the query port as 7778] "\x79\x00\x00\x00\x00\xbc\x27\x00\x00" | | | previous ID sent by the server for this session probably means that this is a heartbeat packet (?) ########################################################################## 7) server -> client (TCP) "\x06\x00\x00\x00\x00\x01\xbc\x27\x00\x00\x06\x00\x00\x00\x00\x02\xbc\x27\x00\x00" | | | | | | | | | | | ID | | | | packet number (2) | | | length of this piece of data | | ID | packet number (1) length of this piece of data (seems that the master server considers this data as 2 different pieces of data) ########################################################################## 8) client -> server (UDP) [source port is data port as 7777] "\x79\x00\x00\x00\x01\xbc\x27\x00\x00" | | | | | ID | packet number (it is the packet number sent in the first | field of the previous packet sent by the server) heartbeat identifier (?) ########################################################################## 9) client -> server (UDP) [source port is query port as 7778] "\x79\x00\x00\x00\x02\xbc\x27\x00\x00" | | | | | ID | packet number (it is the packet number sent in the second | field of the previous packet sent by the server) heartbeat identifier (?) ########################################################################## 10) server -> client (TCP) "\x11\x00\x00\x00\x01\x78\x00\x00\x00\x62\x1e\x00\x00\x61\x1e\x00\x00\x62\x1e\x00\x00" | | | | | | | | | | | query port registered | | | | | (source port in step 9) | | | | data port registered | | | | (source port used in step 8) | | | client's query port registered by the master server | | | (source port used in step 6) | | acknowledge identifier (?) | I don't know total length ########################################################################## 11) client -> server (TCP) "\x05\x00\x00\x00\x04\x21\x00\x00\x00" | | | | | I don't know (ping?) | length total length ########################################################################## 12) server -> client (TCP) "\x05\x00\x00\x00\x03\x00\x00\x00\x00" | | | | | I don't know (ping answer or acknowledge?) | length total length ########################################################################## Now the server could send some checksums, but I don't know what they are. They can be easily ignored, however the connection with the master server must NOT be terminated until the game server is active. When the connection will terminate and no more heartbeats will be sent, the game server will be removed from the master server list (http://ut2003master.epicgames.com/serverlist/full-all.txt and http://ut2003master.epicgames.com/serverlist/demo-all.txt) Now the client must send a heartbeat and then a hertbeat every 60 seconds. A typical heartbeat (UDP packet ever to port 28902) is the following: --- d8 00 00 00 01 00 00 00 P.!.é..Ø....... 0040 00 00 00 61 1e 00 00 00 00 00 00 05 54 65 73 74 ...a........Test 0050 00 0b 44 4d 2d 41 6e 74 61 6c 75 73 00 0c 78 44 ..DM-Antalus..xD 0060 65 61 74 68 4d 61 74 63 68 00 00 00 00 00 20 00 eathMatch..... . 0070 00 00 00 00 00 00 09 0b 73 65 72 76 65 72 6d 6f ........servermo 0080 64 65 00 0a 64 65 64 69 63 61 74 65 64 00 0a 61 de..dedicated..a 0090 64 6d 69 6e 6e 61 6d 65 00 06 41 64 6d 69 6e 00 dminname..Admin. 00a0 0b 61 64 6d 69 6e 65 6d 61 69 6c 00 00 0a 67 61 .adminemail...ga 00b0 6d 65 73 74 61 74 73 00 06 66 61 6c 73 65 00 0a mestats..false.. 00c0 67 6f 61 6c 73 63 6f 72 65 00 03 32 35 00 0a 74 goalscore..25..t 00d0 69 6d 65 6c 69 6d 69 74 00 02 30 00 0b 6d 69 6e imelimit..0..min 00e0 70 6c 61 79 65 72 73 00 02 30 00 0d 74 72 61 6e players..0..tran 00f0 73 6c 6f 63 61 74 6f 72 00 06 66 61 6c 73 65 00 slocator..false. 0100 0b 77 65 61 70 6f 6e 73 74 61 79 00 06 66 61 6c .weaponstay..fal 0110 73 65 00 00 se.. --- NOTE: before each string there is a byte that contains its length. Look my UT2003heartbeat tool for details and a practical example: http://aluigi.org/testz/ut2003heartbeat.zip BYEZ