Ejemplo n.º 1
0
        /// <summary>
        /// Completes an async event to receive data.
        /// </summary>
        /// <param name="result"></param>
        private void OnClientReceiveData(IAsyncResult result)
        {
            //log.Debug($"isAuth {isAuth}");
            //log.Debug("OnClientReceiveData");
            // Prevent invalid calls to this function..
            if (!this._isRunning || result.IsCompleted == false || !(result.AsyncState is Socket))
            {
                this.Stop();
                return;
            }

            lock (syncLock)
            {
                Socket client = (result.AsyncState as Socket);

                // Attempt to end the async call..
                int recvCount = 0;
                try
                {
                    try
                    {
                        recvCount = client.EndReceive(result);
                    }
                    catch (Exception exception)
                    {
                        //log.Debug(exception.ToString());
                        this.Stop();
                        throw;
                        // TODO: atleast log the exception.
                    }

                    if (recvCount == 0)
                    {
                        this.Stop();
                        return;
                    }
                }
                catch (Exception ex)
                {
                    this.Stop();
                    return;
                }

                // Read the current packet.
                byte[] recvData = new byte[recvCount];
                Array.Copy(this._clientBuffer, 0, recvData, 0, recvCount);

                this._clientBacklog.AddRange(recvData);

                //this.SendToServerRaw(recvData);

                // Iterate through the whole packets, parse them and delete them from the buffer.
                while (true)
                {
                    /*
                     * L2Packet structure:
                     | 2 byte size | 1 byte id | up to 65535 bytes for data (payload) |
                     */

                    // If packet buffer is lesser than 3 bytes there is no valid packet for parsing (the minimum is atleast 3 bytes (2 bytes for size, 1 for id)
                    if (this._clientBacklog.Count < 3)
                    {
                        break;
                    }

                    while (L2Injector._sgObjInit == false)
                    {
                        Thread.Sleep(20);
                    }

                    // Calculate the packet length by parsing the first 2 bytes.
                    int packetSize = BitConverter.ToInt16(this._clientBacklog.ToArray(), 0);
                    if (this._clientBacklog.Count < packetSize)
                    {
                        break;
                    }

                    byte[] receivedPacket = new byte[packetSize];
                    Array.Copy(this._clientBacklog.ToArray(), 0, receivedPacket, 0, packetSize);
                    bool shouldDropPacket = false;

                    this._clientBacklog.RemoveRange(0, packetSize);
                    if (!isAuth && _isInit)
                    {
                        _gamePacketObfuscator.DeobfuscatePacketFromClient(receivedPacket);
                        _secondaryGamePacketObfuscator?.DeobfuscatePacketFromClient(receivedPacket);
                        try
                        {
                            if (!JUSTASNIFFER)
                            {
                                var packet = packetFactory.CreatePacket(receivedPacket, false);
                                packet?.Parse(BotInstance.PlayerData);

                                if (packet?.DropPacket == true && _gamePacketObfuscator is SGInGameCipher)
                                {
                                    shouldDropPacket = true;
                                    //((SGInGameCipher)_gamePacketObfuscator).reverseCrypt(receivedPacket, ((SGInGameCipher)_gamePacketObfuscator).clientKeySend);
                                }
                            }

                            if (JUSTASNIFFER)
                            {
                                log.Debug(string.Join(", ", receivedPacket.Select(b => string.Format("{0:X2} ", b))));
                            }
                            //PacketParser.HandleOutgoingPacket(receivedPacket, this.data, this.logger);
                            //CB gameguard id
                            //b1 net ping id
                        }
                        catch (Exception ex)
                        {
                            log.Debug(ex.ToString());
                            throw;
                        }

                        if (!shouldDropPacket)
                        {
                            _secondaryGamePacketObfuscator?.ObfuscatePacketForServer(receivedPacket);
                            _gamePacketObfuscator.ObfuscatePacketForServer(receivedPacket);
                        }
                    }
                    else if (!_isInit)
                    {
                        if (_gamePacketObfuscator == null && receivedPacket.Length > 100)
                        {
                            int version = BitConverter.ToInt32(receivedPacket.ToArray(), 3);
                            if (version >= 268 && version <= 272)
                            {
                                log.Debug($"Unsupported H5 client.");
                            }
                            //log.Debug(version);

                            if (!JUSTASNIFFER)
                            {
                                BotInstance.Init(version, this);
                                packetFactory = ProtocolFactory.CreatePacketFactory(version);
                            }
                        }

                        if (L2Injector.IsSGLoaded() && _gamePacketObfuscator is LegacyInGameCipher)
                        {
                            _gamePacketObfuscator = new SGInGameCipher(new byte[1], 0);
                            //placeholder args, since they are not needed in the alg
                            //if (!JUSTASNIFFER)
                            L2Injector.FillSGObject((SGInGameCipher)_gamePacketObfuscator);
                            //((SGInGameCipher)_gamePacketObfuscator).reverseCrypt(receivedPacket,((SGInGameCipher)_gamePacketObfuscator).clientKeySend);

                            //_gamePacketObfuscator.DeobfuscatePacketFromClient(receivedPacket);
                            _isInit = true;
                        }
                    }
                    //log.Debug("_0");
                    if (_secondaryGamePacketObfuscator == null && L2Injector.IsRpgClient() &&
                        _gamePacketObfuscator is LegacyInGameCipher)
                    {
                        _secondaryGamePacketObfuscator =
                            new RpgInGameCipher(((LegacyInGameCipher)_gamePacketObfuscator).DynamicKeyBytes, 0);
                        ((RpgInGameCipher)_secondaryGamePacketObfuscator).SecretKey = L2Injector.GetRpgSecretKey();
                    }

                    // Send this packet to the server.
                    //log.Debug("_1");
                    if (!shouldDropPacket)
                    {
                        this.SendToServerRaw(receivedPacket);
                    }
                }

                // Begin listening for the next packet.
                this.Client_BeginReceive();
                //log.Debug("_5");
            }
        }