Montag, 7. November 2016

HowTo: Understand 0B000002 vs. 0B004002 packets

The 0B000002 and 0B004002 are both ping pong packets (i.e. they are exchanged between client and server without any user input, just to confirm the connection works). What makes them really interesting is that they are quite different, but very similar.

Let me explain: The 0B000002 has 18 bytes of body, while the 0B004002 has 22 bytes, a difference of four bytes. The body if 0B004002 is offset by these 4 bytes.

MeaningBytes 0B000002Bytes 0B004002
Sequence number of the last packet seen from "the other side"N/A0x14 - 0x17
Value specified in the 01000006 packet sent by the server0x14 - 0x170x18 - 0x1b
Unknown, but constantly increasing number0x18 - 0x1b0x1c - 0x1f
Client/Server uptime?0x1c - 0x210x20 - 0x25
Byteswapped confirmation that a packet group was received (e.g. 0x0000ebff will be sent by the client, when all packets of the group ffeb are received)0x12 - 0x250x26 - 0x29

As you can see both packets share the same payload, but the 0B004002 one also ships upfront the sequence number of the last packet received by the other side of the communication.

Dienstag, 1. November 2016

HowTo: Read the first packet sent by the server

The first packet sent by the server back to the client can be understood as follows:

Header:

BytesDescriptionLength
0x00-0x01Set to the session ID of the server2
0x02-0x03The length of the packets body in bytes2
0x04-0x07The command (aka action aka OP code): 040000004
0x08-0x0BThe sequence number of the packet: 000000004
0x0C-0x0FThe checksum of the packets body4
0x10-0x11Unknown initial value4
0x12-0x13Unknown initial value4

Body:

BytesDescriptionLength
0x14-0x17Base value for "ping pong" packets, though byte-swapped4
0x18-0x1bUnknown4
0x1c-0x23Some kind of session key (returned byte swapped in the next packet from the client)4
0x24-0x25Padding: 00 002
0x26-0x27Session ID for the client (will be the first 2 bytes of every next packet from the client)2
0x28-0x2bBase for the checksum generation on the server4
0x2c-0x2fBase for the checksum generation on the client4
0x30-0x3fSome constant (same for every account, every server)16
That's all currently known behind the magic happening in the first packet from the server.

HowTo: Read the first packet sent by the client

The first packet sent by the client to the server can be understood as follows:

Header:

BytesDescriptionLength
0x00-0x01Set to 00 00 (no session ID yet)2
0x02-0x03The length of the packets body in bytes2
0x04-0x07The command (aka action aka OP code): 000100004
0x08-0x0BThe sequence number of the packet: 000000004
0x0C-0x0FThe checksum of the packets body4
0x10-0x1100 004
0x12-0x1300 004

Body:

BytesDescriptionLength
0x14Length of the following (ASCII) string1
0x15-0x53The client version "061004_netver:..." as ASCII string63
0x54-0x57Length of the following block (0x0145 bytes, byte swapped)4
0x58-0x5BUnknown?4
0x5C-0x5FSet to 04 00 00 00 if a GLS ticket follows4
0x60-0x63Seconds since 1970, bytes must be read "backwards"4
0x64Length of the following (UTF-16) string4
0x65-0x96The account identifier? (a GUID/UUID in UTF-16)4
0x97-0x9aGLS ticket length (byte swapped) 0x0102 == 258 bytes4
0x9b-0x19cGLS ticket generated by the launcher4
That's all currently known behind the magic happening in the first packet.

Sonntag, 30. Oktober 2016

HowTo: Understanding a packet header

Let's take a look at some of the packets we already know and understand. First of a few basics as a reminder:
  1. each and every packet has a header and a body
  2. the header is fixed size, the body is variable in size
  3. the header is fixed in content, the body varies
For now let's focus on what we know about the header.
BytesDescriptionLength
0x00-0x01The session ID. The server and the client each have a session ID.2
0x02-0x03The length of the packets body in bytes2
0x04-0x07The command (aka action aka OP code) this packet will perform4
0x08-0x0BThe sequence number of the packet (necessary for ordering UDP packets)4
0x0C-0x0FThe checksum of the packets body4
0x10-0x11Packet group number (e.g. 0xffeb, confirmed in the 08004002 packet)4
0x12-0x13Unclear, get increased by the server4

Freitag, 28. Oktober 2016

HowTo: Capture decrypted packets

To get decrypted packets for further analysis, you can easily capture and decrypt them using the LOTRO-Tools.

First of all clone the git repository from https://gitlab.com/lotro/server.

Open the Solution "LOTRO-Tools.sln" in Monodevelop or Visual Studio.

Build the project LOTROPacketCaptureAndAutoDecryption and launch it from bin/Debug/LOTROPacketCaptureAndAutoDecryption.exe

Look into the subfolder decrypted_packets for available files. The files contain a single packet each. The filename is like the following:

  • 4 digits represent the sequential number of captured packets
  • the text "client" says it was a packet sent by the client, the text "server" indicates it was a packet from the server
  • the last 8 digits describe the action to be performed by the packet
Examples:
0000_client-00010000 is the first package captured (sequence starts at 0000), was sent from the client and contains the action 00010000

0001_server-00040000 is the second package captured, was sent by the server and contains the action 00040000

HowTo: Use LOTRO-Tools on Linux

LOTRO-Tools was developed on Windows using winpcap. It fails on Linux because SharpPcap is erroneously looking for "libwpcap.so" (as it would look for wpcap.dll on Windows), while it should look for "libpcap.so" instead. You can work around that using

sudo ln -s /usr/lib/libpcap.so /usr/lib/libwpcap.so

HowTo: Capture the appropriate packets between the client and the server

To only capture the packets necessary for analysis of the game protocol (i.e. not the chat protocol), you can use the following pcap (e.g. Wireshark) filter:

!broadcast and !multicast and udp and !port 53 and !port 59511 and !port 161 and !port 2900 and !port 5355

HowTo: Disabling checksum checks in the LOTRO client

To test a local server that does not support checksumming, you can patch you lotroclient.exe

Go to position: 3B 4C 24 1C 75 6A 8B

Replace "75 6A" with "90 90"