Register for your free account! | Forgot your password?

Go Back   elitepvpers > MMORPGs > Conquer Online 2 > CO2 Private Server
You last visited: Today at 19:56

  • Please register to post and access all features, it's quick, easy and FREE!

Advertisement



Packet Corruption after DH exchange (5065)

Discussion on Packet Corruption after DH exchange (5065) within the CO2 Private Server forum part of the Conquer Online 2 category.

Reply
 
Old   #1
 
elite*gold: 0
Join Date: Oct 2022
Posts: 21
Received Thanks: 0
Packet Corruption after DH exchange (5065)

I tried to implement the DH Key Exchange and Blowfish by reading your code, but I've run into a curious issue I can't seem to figure out the past couple of days. I've done it sequentially and synchronously to make it easier to understand what's happening, as my problem is very hard to understand for me.

Code:
[LOGIN] Client connected: 192.168.0.10:58146
[LOGIN/1051] Account: asdasdasd, Pass: asdasdasd, Server: Light
[GAME] Client connected: 192.168.0.10:53050
[LOGIN/1052] Client Id: 499999, File: res.dat
54 39 40 E1 B9 8D B2 A6 00 00 00 12 00 00 00 3A             [email protected]:
6F BF 1C 0A A3 BE 32 34 05 11 CF 7C ED D1 20 76             o.....24...|.. v
FF 80 00 00 00 42 39 39 35 45 33 30 35 39 38 41             .....B995E30598A
38 44 46 31 39 37 33 30 37 43 33 33 44 39 39 31             8DF197307C33D991
32 41 35 38 31 34 30 38 34 37 31 44 39 45 31 46             2A581408471D9E1F
31 35 30 31 37 46 43 30 41 30 39 43 43 38 45 39             15017FC0A09CC8E9
35 30 36 37 42 31 34 45 33 45 44 35 38 37 46 31             5067B14E3ED587F1
42 42 35 36 46 37 34 35 35 32 43 32 35 45 35 34             BB56F74552C25E54
36 36 39 45 46 42 44 35 31 46 34 38 33 41 42 44             669EFBD51F483ABD
38 32 35 31 44 35 32 35 35 36 39 37 43 46 37 30             8251D5255697CF70
42 35 31 42 35 54 51 43 6C 69 65 6E 74                      B51B5TQClient

Pubkey: B995E30598A8DF197307C33D9912A581408471D9E1F15017FC0A09CC8E95067B14E3ED587F1BB56F74552C25E54669EFBD51F483ABD8251D5255697CF70B51B5
[GAME] Unknown packet ID: 23953
FF 4F 91 5D E1 08 CD 26 02 00 00 00 7B 00 45 6E             .O.]...&....{.En
00 00 00 00 00 00 00 00 0A 00 00 00 54 51 43 6C             ............TQCl
69 65 6E 74                                                 ient
Game Server Packet 1052 is corrupted. The first couple bytes return garbage, but starting at offset 8, the data is valid. I even get the correct footer (TQClient) The lengths are fine, as you can see in the hexdumps. both packets (DH and 1052) end with TQClient. The code is synchronous, so there's nothing else going on with the crypto.

Here's my code

Code:
private static void GameServerLoop()
    {
        TcpListener listener = new(System.Net.IPAddress.Any, 5816);
        listener.Start();
        while (true)
        {
            var client = listener.AcceptTcpClient();
            var stream = client.GetStream();
            var reader = new BinaryReader(stream);

            Console.WriteLine($"[GAME] Client connected: {client.Client.RemoteEndPoint}");

            var ipendpoint = client.Client.RemoteEndPoint?.ToString();
            if (ipendpoint == null)
                break;

            var (found, player) = IpRegistry.GetEntity(ipendpoint.Split(':')[0]);
            if (!found)
                continue;

            ref var net = ref player.Get<NetworkComponent>();
            net.Socket.Close();
            net.Socket.Dispose();
            net.Socket = client.Client;

            net.DiffieHellman.ComputePublicKeyAsync();
            Memory<byte> dhx = MsgDHX.Create(net.ServerIV, net.ClientIV, DiffieHellman.P, DiffieHellman.G, net.DiffieHellman.GetPublicKey());

            net.GameCrypto.Encrypt(dhx.Span, dhx.Span);
            player.NetSync(dhx);

            var count = reader.Read(net.RecvBuffer.Span);
            var packet = net.RecvBuffer[..count];
            net.GameCrypto.Decrypt(packet.Span, packet.Span);
            var pubkey = Encoding.ASCII.GetString(ParseResponse(packet));
            Console.WriteLine(GamePacketHandler.Dump(packet.ToArray()));
            Console.WriteLine($"Pubkey: {pubkey}");

            net.DiffieHellman.ComputePrivateKey(pubkey);
            net.GameCrypto.GenerateKeys(net.DiffieHellman.GetPrivateKey());
            net.GameCrypto.SetIVs(net.ClientIV, net.ServerIV);

            count = reader.Read(net.RecvBuffer.Span);
            packet = net.RecvBuffer[..count];
            net.GameCrypto.Decrypt(packet.Span, packet.Span);

            GamePacketHandler.Process(in player, packet);
        }
    }


The only changes I made to Comet code were those that gave me compiler warnings about uninitialized variables / possible null de-referencing / naming rules / making it compatible with ECS architecture.
.Nostalgia is offline  
Old 10/21/2022, 11:25   #2
 
Spirited's Avatar
 
elite*gold: 12
Join Date: Jul 2011
Posts: 7,913
Received Thanks: 3,993
Well, if you're getting a response, then it's safe to say it's not a problem with sending the handshake request to the client. I'd appreciate a few more details around your socket system if you don't mind (I still suspect there's something off there, maybe):

What's the definition of Read from your TCP listener class?
What's the size of your RecvBuffer and how are you currently parsing the response?
What does the "GamePacketHandler.Process(in player, packet);" do after "net.GameCrypto.SetIVs(net.ClientIV, net.ServerIV);"?

And sorry, I'm heading off to bed... so I might not respond to this right away. Cheers.
Spirited is offline  
Old 10/21/2022, 11:44   #3
 
elite*gold: 0
Join Date: Oct 2022
Posts: 21
Received Thanks: 0
Quote:
Originally Posted by Spirited View Post
Well, if you're getting a response, then it's safe to say it's not a problem with sending the handshake request to the client. I'd appreciate a few more details around your socket system if you don't mind (I still suspect there's something off there, maybe):

And sorry, I'm heading off to bed... so I might not respond to this right away. Cheers.
That's not my class, that's the built in TcpListener in System.Net.

Quote:
What's the size of your RecvBuffer and how are you currently parsing the response?
1024 bytes.

Code:
    // redux copy paste
    private static unsafe byte[] ParseResponse(Memory<byte> packet)
    {
        byte[] publicKey;
        fixed (byte* ptr = packet.Span)
        {
            var length = *(ushort*)(ptr + 7);
            var junkLength = *(int*)(ptr + 11);
            var publicKeyLength = *(int*)(ptr + 15 + junkLength);

            publicKey = new byte[publicKeyLength];
            for (var i = 0; i < publicKeyLength; i++)
                publicKey[i] = *(ptr + 19 + junkLength + i);
        }

        return publicKey;
    }
Quote:
What does the "GamePacketHandler.Process(in player, packet);" do after "net.GameCrypto.SetIVs(net.ClientIV, net.ServerIV);"?
actually that's was just a copy/paste mistake, that line wasnt supposed to be there. I've updated the first post. However, for completeness:

Code:
   public static unsafe class GamePacketHandler
    {
        internal static void Process(in Entity ntt, Memory<byte> packet)
        {
            var size = BitConverter.ToUInt16(packet.Span[0..]);
            var id = BitConverter.ToUInt16(packet.Span[2..]);
            ref readonly var net = ref ntt.Get<NetworkComponent>();

            Console.WriteLine($"[LOGIN] Received packet {id} with size {size} | actual buffer size: {packet.Length}");

            switch (id)
            {
                default:
                    {
                        Console.WriteLine($"[GAME] Unknown packet ID: {id}");
                        FConsole.WriteLine(Dump(packet.ToArray()));
                        break;
                    }
            }
Code:
[LOGIN] Client connected: 192.168.0.10:39646
[LOGIN/1051] Account: username, Pass: password, Server: Light
[GAME] Client connected: 192.168.0.10:49670
[LOGIN/1052] Client Id: 1499999, File: res.dat
2D 74 68 12 F3 40 D8 C2 00 00 00 2E 00 00 00 2E             -th..#..........
67 8D B9 F1 24 A6 C2 B1 9D D4 5F CF 7B 71 44 55             g...$....._.{qDU
F7 9C CC 45 D6 35 46 58 67 D7 FC EF A3 E2 0E 50             ...E.5FXg......P
3C E7 C0 72 C1 EB DE 16 4F 7A 99 66 24 80 00 00             <..r....Oz.f$...
00 37 39 39 33 39 43 35 42 43 38 46 45 34 41 30             .79939C5BC8FE4A0
30 31 44 32 33 45 33 35 36 30 38 45 33 31 34 39             01D23E35608E3149
37 39 32 42 38 42 41 34 39 41 33 44 44 34 45 45             792B8BA49A3DD4EE
39 31 45 43 41 41 42 41 35 35 32 31 46 41 35 42             91ECAABA5521FA5B
41 36 39 46 33 31 36 36 30 35 30 38 35 45 36 35             A69F316605085E65
32 43 37 30 39 33 45 34 31 32 34 36 46 36 44 42             2C7093E41246F6DB
32 38 41 44 37 42 42 44 36 37 41 42 31 31 36 30             28AD7BBD67AB1160
42 36 36 34 31 41 33 42 37 41 30 35 41 32 38 39             B6641A3B7A05A289
38 54 51 43 6C 69 65 6E 74                                  8TQClient

Pubkey: 79939C5BC8FE4A001D23E35608E3149792B8BA49A3DD4EE91ECAABA5521FA5BA69F316605085E652C7093E41246F6DB28AD7BBD67AB1160B6641A3B7A05A2898
[GAME] Received packet 65268 with size 29441 | actual buffer size: 36
[GAME] Unknown packet ID: 65268
01 73 F4 FE 5A CA AD 73 02 00 00 00 7B 00 45 6E             .s..Z..s....{.En
00 00 00 00 00 00 00 00 0A 00 00 00 54 51 43 6C             ............TQCl
69 65 6E 74                                                 ient
.Nostalgia is offline  
Old 10/21/2022, 15:08   #4
 
pintinho12's Avatar
 
elite*gold: 0
Join Date: Jul 2009
Posts: 865
Received Thanks: 370
Aren't you missing this before getting the data from the socket? It's right after exchange.
If you see Comet will decrypt the first packet in two parts to avoid processing more than it should, I may be missing something but your code just decrypts the whole exchange message and it may be receiving the first 8 bytes of 1052 at the end of the exchange packet.

Code:
// Now that the key has changed, decrypt the rest of the bytes in the buffer
                // and prepare to start receiving packets on a standard receive loop.
                if (consumed < examined)
                {
                    actor.Cipher?.Decrypt(
                        actor.Buffer[consumed..examined].Span,
                        actor.Buffer[consumed..examined].Span);

                    if (!Splitting(actor, examined, ref consumed))
                    {
                        logger.LogError("[Exchange] Client disconnected due to invalid packet.");
                        actor.Disconnect();
                        Disconnecting(actor);
                        return;
                    }

                    remaining = examined - consumed;
                    actor.Buffer[consumed..examined].CopyTo(actor.Buffer);
                }
I had this problem once but I can't remember what was causing it
pintinho12 is offline  
Old 10/21/2022, 18:31   #5
 
elite*gold: 0
Join Date: Oct 2022
Posts: 21
Received Thanks: 0
Quote:
Originally Posted by pintinho12 View Post
Aren't you missing this before getting the data from the socket? It's right after exchange.
If you see Comet will decrypt the first packet in two parts to avoid processing more than it should, I may be missing something but your code just decrypts the whole exchange message and it may be receiving the first 8 bytes of 1052 at the end of the exchange packet.

Code:
// Now that the key has changed, decrypt the rest of the bytes in the buffer
                // and prepare to start receiving packets on a standard receive loop.
                if (consumed < examined)
                {
                    actor.Cipher?.Decrypt(
                        actor.Buffer[consumed..examined].Span,
                        actor.Buffer[consumed..examined].Span);

                    if (!Splitting(actor, examined, ref consumed))
                    {
                        logger.LogError("[Exchange] Client disconnected due to invalid packet.");
                        actor.Disconnect();
                        Disconnecting(actor);
                        return;
                    }

                    remaining = examined - consumed;
                    actor.Buffer[consumed..examined].CopyTo(actor.Buffer);
                }
I had this problem once but I can't remember what was causing it
This is why I added the hex dumps. you can see that both packets get received completely in both Read calls (ends with TQClient) so there's nothing past that in the buffer.

The 2nd Read() always returns 36 bytes (28 for 1052 + 8 for tqclient)

As I show in the ouput:

Quote:
[GAME] Received packet 65268 with size 29441 | actual buffer size: 36
and again

Quote:
00 00 00 00 00 00 00 00 0A 00 00 00 54 51 43 6C ............TQCl
69 65 6E 74 ient
ends with TQClient, proving(? adding the question mark because Spirited said the same thing in his thread, im starting to think im missing something here or both of you just overlooked the same thing) that the buffer contained the entire packet and nothing else

I'd love to try other implementations from other public sources, but all of them rely on some windows only libraries I can't run on linux... Or other Client versions - but again, only 4330 and 5065 seem to work on linux.
.Nostalgia is offline  
Old 10/21/2022, 20:13   #6
 
Spirited's Avatar
 
elite*gold: 12
Join Date: Jul 2011
Posts: 7,913
Received Thanks: 3,993
How often can you replicate this exact issue? Does it have the same corrupted bytes every time? Is that also the exact code you're using, or is there more context around those network calls / decrypts that we're not seeing? Is there also a reason why you're not using Comet's socket system? You can make the socket events synchronous if you want.
Spirited is offline  
Old 10/21/2022, 21:09   #7
 
elite*gold: 0
Join Date: Oct 2022
Posts: 21
Received Thanks: 0
The first bytes of the 1052 packet are random (not consistent) everytime. I've posted the exact code I'm using, yes. There's nothing else going on.
.Nostalgia is offline  
Old 10/21/2022, 21:26   #8
 
pintinho12's Avatar
 
elite*gold: 0
Join Date: Jul 2009
Posts: 865
Received Thanks: 370
Quote:
Originally Posted by .Nostalgia View Post
The first bytes of the 1052 packet are random (not consistent) everytime. I've posted the exact code I'm using, yes. There's nothing else going on.
That's the problem, if they're encrypted they'll always be random and if they're being decrypted by the wrong key they will always result in trash. I had that issue with Phoenix quite a while ago
pintinho12 is offline  
Old 10/23/2022, 09:06   #9
 
elite*gold: 0
Join Date: Oct 2022
Posts: 21
Received Thanks: 0
While building a minimal example to upload here, I've found the root of the problem.

It's related to me initializing the IV arrays with random bytes it seems. If I keep the arrays empty, it works fine.

Code:
            Socket = socket;
            RecvBuffer = new byte[1024];
            ClientIV = new byte[8];
            ServerIV = new byte[8];

            // Random.Shared.NextBytes(ClientIV);
            // Random.Shared.NextBytes(ServerIV);
Code:
Pubkey: 8CEFCC6D97B002414D8BC6D32A20F50BA3D4E9C3E7CE9488667119D5FC7B28645CD475889A107E9EC941C5DBA4B9BA6C6216037B6E6AF8815A76B8367C00F87E
[GAME] Received packet 1052 with size 28 | actual buffer size: 36
[GAME] Client Version: 123, Language: En
Edit: well the client crashes when I finish the login sequence, wine can't run conquer. Game over. Guess I'll not get to make a conquer server.
.Nostalgia is offline  
Old 10/24/2022, 08:03   #10
 
Spirited's Avatar
 
elite*gold: 12
Join Date: Jul 2011
Posts: 7,913
Received Thanks: 3,993
Quote:
Originally Posted by .Nostalgia View Post
While building a minimal example to upload here, I've found the root of the problem.

It's related to me initializing the IV arrays with random bytes it seems. If I keep the arrays empty, it works fine.

Code:
            Socket = socket;
            RecvBuffer = new byte[1024];
            ClientIV = new byte[8];
            ServerIV = new byte[8];

            // Random.Shared.NextBytes(ClientIV);
            // Random.Shared.NextBytes(ServerIV);
Code:
Pubkey: 8CEFCC6D97B002414D8BC6D32A20F50BA3D4E9C3E7CE9488667119D5FC7B28645CD475889A107E9EC941C5DBA4B9BA6C6216037B6E6AF8815A76B8367C00F87E
[GAME] Received packet 1052 with size 28 | actual buffer size: 36
[GAME] Client Version: 123, Language: En
Edit: well the client crashes when I finish the login sequence, wine can't run conquer. Game over. Guess I'll not get to make a conquer server.
Ah, yeah. My friend and I tried getting Conquer running on his Linux laptop, and it was a mess. We couldn't get the textboxes working (was trying the 5017 client). Maybe you could run it the old fashion way in kvm.
Spirited is offline  
Old 10/25/2022, 12:12   #11
 
elite*gold: 0
Join Date: Oct 2022
Posts: 21
Received Thanks: 0
So I've made the IVs work, turns out my MsgDHX was swapping Client/Server IVs.
I'm also using KVM to run conquer in a windows XP vm but the client crashes (with a Send Report message box) and in debug/ the log file contains the following:
At first I thought maybe there's an issue with the virtual VGA adapter, so I tried to use a 4330 client as well, replacing the gamecrypto and the character info packet - and it worked, I got to see Twin City.

Packet Issue? Client issue? Who the f*** knows. I used Spirited's packet wiki, i assume that info is 100% accurate.

- Edit:

Fixed the offsets, client doesn't create a debug log anymore, just crashes like before. Starting to think there's some virtualization issue with 3d

I am under the impression that the client should just close without saying anything if the packets are wrong

LOL

I sent ANSWER_OK on the MsgTextType 2100 instead of 2101. That was the issue.

Thank you, i think i'll be fine from this point on (sorry for the double / tripple post, this forum has bugs i think)
.Nostalgia is offline  
Reply


Similar Threads Similar Threads
TheeUnforgiven 5065 source and project ORION 5065 proxy bot
09/27/2015 - CO2 PServer Guides & Releases - 14 Replies
TheeUnforgiven is based on redux 5065 (all credits for the base goes for pro4never, link to it's thread) that is the change log, i've done way more than that but i sometimes ignore updating the change log, i've fixed some fatal exploits (which i personally exploited the hell out of them on private servers using redux source), made botting a little bit harder, implemented lots of quests and features, fixed lots of stuff, here read it for yourself that whole progress has been done in 3...
[HELP] Need Source 5065 and Appserver for 5065
08/24/2009 - CO2 Private Server - 5 Replies
i need this all plx fast:(



All times are GMT +1. The time now is 19:56.


Powered by vBulletin®
Copyright ©2000 - 2023, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Support | Contact Us | FAQ | Advertising | Privacy Policy | Terms of Service | Abuse
Copyright ©2023 elitepvpers All Rights Reserved.