6.0.5.0 support (core packet changes)
Posted: Sat Dec 01, 2007 11:18 pm
Client 6.0.5.0 includes packet changes which will cause issues if not fixed at the core packet handling.
Before I go further I will explain in small detail how the UO login process works:
When a client first connects, it sends 4 bytes, which is a "seed", normally the client's local IP address. The first connection is actually made to the login server, which is the same listener as server in RunUO (on OSI its seperate I believe)
Following that is a 0x80 packet which includes the username and password. If the login server authenticates that, then it sends the server list.
Client then sends a 0xa0 packet which includes the server number to connect to.
Server sends the IP, port, and a 32-bit randomized key - This is mostly used by OSI to ensure a client went to the login server before hitting an actual server.
Now that client has the IP, it closes this connection, and connects to that IP and port, which will usually be the same as the first connection, in the case of RunUO.
When connected it sends a 4 byte seed which is the 32-bit random int generated earlier.
Then it sends a 0x91 packet with username and password, if server authenticates, it sends char list.
The only important thing related to this patch is the first 4 bytes sent by the client. In new patch, they made the
2nd seed longer. Instead of just 4 bytes, it is now 21 bytes, but 2nd login stage is still just 4 bytes.
To fix it, the server needs to be configured to wait for 21 bytes instead of just 4, but only for the 1st login
stage. Thankfully, the new seed includes a constant, which is the first byte, being 0xEF. So the server should
check if first byte equals to that, if yes, unqueue 21 bytes, if no, unqueue 4 only. The rest of the bytes can then
go to the packet handler (next will either be 0x80 or 0x91, depending on login stage.
Ok, now for code! These changes are done in core.
In bytequeue.cs, add this to the ByteQueue class:
Another site had posted something similar, but their code was wrong and did not take into consideration that the 2nd
login stage seed is still 4 bytes.
Now in messagepump.cs, find
And change the 4 to 21.
In same file, find the HandleReceive() function. Replace the if(!ns.Seeded) block with this:
Then in the while loop just below, replace the if(!ns.SentFirstPacket ... statement with this:
Note that AoV does not care what the random 32bit number is because I have it setup so the login server can redirect to the test shard located on another server, but really it should not be an issue. The password authentication process happens twice.
I believe this is it, and remember to update maps too since they changed. You'll want to add gates or something so
people can get to nix room in gaunt as they closed up the passage to prevent from getting DF in there.
This is how a typical login session should look like in packets:
Archived topic from AOV, old topic ID:1767, old post ID:11331
Before I go further I will explain in small detail how the UO login process works:
When a client first connects, it sends 4 bytes, which is a "seed", normally the client's local IP address. The first connection is actually made to the login server, which is the same listener as server in RunUO (on OSI its seperate I believe)
Following that is a 0x80 packet which includes the username and password. If the login server authenticates that, then it sends the server list.
Client then sends a 0xa0 packet which includes the server number to connect to.
Server sends the IP, port, and a 32-bit randomized key - This is mostly used by OSI to ensure a client went to the login server before hitting an actual server.
Now that client has the IP, it closes this connection, and connects to that IP and port, which will usually be the same as the first connection, in the case of RunUO.
When connected it sends a 4 byte seed which is the 32-bit random int generated earlier.
Then it sends a 0x91 packet with username and password, if server authenticates, it sends char list.
The only important thing related to this patch is the first 4 bytes sent by the client. In new patch, they made the
2nd seed longer. Instead of just 4 bytes, it is now 21 bytes, but 2nd login stage is still just 4 bytes.
To fix it, the server needs to be configured to wait for 21 bytes instead of just 4, but only for the 1st login
stage. Thankfully, the new seed includes a constant, which is the first byte, being 0xEF. So the server should
check if first byte equals to that, if yes, unqueue 21 bytes, if no, unqueue 4 only. The rest of the bytes can then
go to the packet handler (next will either be 0x80 or 0x91, depending on login stage.
Ok, now for code! These changes are done in core.
In bytequeue.cs, add this to the ByteQueue class:
Code: Select all
public int GetSeedLength()
{
if ( m_Buffer[0] == 0xef ) // we need to check if this is 1st login stage, or 2nd (NOTE: someone on
a forum mentioned this packet is not always 0xEF but I never seen it differently)
return 21;
return 4;
}
login stage seed is still 4 bytes.
Now in messagepump.cs, find
Code: Select all
m_Peek = new byte[4];
In same file, find the HandleReceive() function. Replace the if(!ns.Seeded) block with this:
Code: Select all
if (!ns.Seeded )
{
if ( buffer.Length >= seed_length )
{
buffer.Dequeue( m_Peek, 0, seed_length );
int seed = 0;
if ( seed_length == 4 )
{
seed = ( m_Peek[0] << 24 ) | ( m_Peek[1] << 16 ) | ( m_Peek[2] <<
8 ) | m_Peek[3];
}
else if ( seed_length == 21 )
{
seed = ( m_Peek[1] << 24 ) | ( m_Peek[2] << 16 ) | ( m_Peek[3] <<
8 ) | m_Peek[4];
ns.Version = new ClientVersion( m_Peek[8], m_Peek[12],
m_Peek[16], m_Peek[20] );
}
if ( seed == 0 )
{
Console.WriteLine( "Login: {0}: Invalid client detected,
disconnecting [MessagePump HandleReceive()]", ns );
ns.Dispose();
return false;
}
ns.m_Seed = seed;
ns.Seeded = true;
length = buffer.Length;
}
else
{
return true;
}
}
Then in the while loop just below, replace the if(!ns.SentFirstPacket ... statement with this:
Code: Select all
if ( !ns.SentFirstPacket && packetID != 0xF0 && packetID != 0xF1 && packetID != 0xCF && packetID != 0x80 && packetID
!= 0x91 && packetID != 0xA4 && packetID != 0xEF )
{
Console.WriteLine( "Client: {0}: Encrypted client detected,
disconnecting - Invd Pckt: 0x{1} ({2})", ns,packetID.ToString("X"),packetID );
ns.Dispose();
break;
}
Note that AoV does not care what the random 32bit number is because I have it setup so the login server can redirect to the test shard located on another server, but really it should not be an issue. The password authentication process happens twice.
I believe this is it, and remember to update maps too since they changed. You'll want to add gates or something so
people can get to nix room in gaunt as they closed up the passage to prevent from getting DF in there.
This is how a typical login session should look like in packets:
Code: Select all
[root@borg uocli]# ./uocli
===============================================================================
Ultima Online Command Line [uocli] - By Red Squirrel
===============================================================================
Enter server address [ravager.loc]:
Enter server port [1337]:
Enter username [test]:
Enter password[****]:
Enter Char Slot number (0-5) [0]:
Debug packets(Y/N)? [y]:
Connecting...
packet: 21 bytes
-------------------------------------------------------------------------------
ef 0a 01 01 14 00 00 00 01 00 00 00 03 00 00 00 03 00 00 00 07
. . . . . . . . . . . . . . . . . . . . .
-------------------------------------------------------------------------------
Authenticating...
first login packet: 62 bytes
-------------------------------------------------------------------------------
80 74 65 73 74 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
. t e s t . . . . . . . . . . . . . . . . . . . . .
00 00 00 00 00 74 65 73 74 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
. . . . . t e s t . . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 5d
. . . . . . . . . ]
-------------------------------------------------------------------------------
Received Packet: 2 bytes
-------------------------------------------------------------------------------
a8 00
. .
-------------------------------------------------------------------------------
Received Packet: 1 bytes
-------------------------------------------------------------------------------
56
V
-------------------------------------------------------------------------------
success, getting server list...
Received Packet: 83 bytes
-------------------------------------------------------------------------------
5d 00 02 00 00 41 67 65 20 6f 66 20 56 61 6c 6f 72 00 00 00 00 00 00 00 00 00
] . . . . A g e o f V a l o r . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 fb f2 a5 13 43 00 01 41 6f 56 20 54 43 31
. . . . . . . . . . . . . . . . C . . A o V T C 1
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
. . . . . . . . . . . . . . . . . . . . . . . . . .
fb d4 4e 65 d0
. . N e .
-------------------------------------------------------------------------------
Available shards:
0: Age of Valor
1: AoV TC1
Enter shard number [1]:
unknown metric packet: 268 bytes
-------------------------------------------------------------------------------
d9 02 00 00 00 1c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
. . . . . . . . . . . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
. . . . . . . . . . . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
. . . . . . . . . . . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
. . . . . . . . . . . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
. . . . . . . . . . . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
. . . . . . . . . . . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
. . . . . . . . . . . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
. . . . . . . . . . . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
. . . . . . . . . . . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
. . . . . . . . . . . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00
. . . . . . . .
-------------------------------------------------------------------------------
server selection packet: 3 bytes
-------------------------------------------------------------------------------
a0 00 01
. . .
-------------------------------------------------------------------------------
Received Packet: 11 bytes
-------------------------------------------------------------------------------
8c d0 65 4e d4 05 39 d3 ff c5 d2
. . e N . . 9 . . . .
-------------------------------------------------------------------------------
Connecting to '208.101.78.212:1337'...
encryption key packet: 4 bytes
-------------------------------------------------------------------------------
d3 ff c5 d2
. . . .
-------------------------------------------------------------------------------
post login packet: 65 bytes
-------------------------------------------------------------------------------
91 d3 ff c5 d2 74 65 73 74 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
. . . . . t e s t . . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 74 65 73 74 00 00 00 00 00 00 00 00 00 00 00 00 00
. . . . . . . . . t e s t . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00
. . . . . . . . . . . . .
-------------------------------------------------------------------------------
Picking char...
char picker packet: 73 bytes
-------------------------------------------------------------------------------
5d ed ed ed ed 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
] . . . . . . . . . . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
. . . . . . . . . . . . . . . . . . . . . . . . . .
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 d3 ff c5 d2
. . . . . . . . . . . . . . . . . . . . .
-------------------------------------------------------------------------------
Logged to world.