public override void HandlePacket(LobbyClient client, ServerPacket packet) { var reader = packet.Reader; string realTag = reader.ReadUnicodeString(50); uint accountPremium = reader.ReadUInt32(); ulong timeStamp = reader.ReadUInt64(), accountPermissions = reader.ReadUInt64(); for (int i = 0; i < 5; i++) { reader.ReadInt32(); } ushort voicePortMin = reader.ReadUInt16(), voicePortMax = reader.ReadUInt16(); uint voiceAccountId = reader.ReadUInt32(); string voiceUsername = reader.ReadASCIIString(17), voiceKey = reader.ReadASCIIString(17); RsaKeyParameters serverPub = WindowsRSA.ReadPublicKeyBlob(reader); string countryCode = reader.ReadUnicodeString(), voiceURL = reader.ReadASCIIString(); var generator = new RsaKeyPairGenerator(); generator.Init(new KeyGenerationParameters(new SecureRandom(), 1024)); AsymmetricCipherKeyPair clientKeyPair = generator.GenerateKeyPair(); RsaKeyParameters clientPub = (RsaKeyParameters)clientKeyPair.Public; client.ClientDecryptEngine = new Pkcs1Encoding(new RsaEngine()); client.ClientDecryptEngine.Init(false, clientKeyPair.Private); byte[] clientPubBlob = WindowsRSA.CreatePublicKeyBlob(clientPub); client.ServerEncryptEngine = new Pkcs1Encoding(new RsaEngine()); client.ServerEncryptEngine.Init(true, serverPub); byte[] encryptedClientKey = WindowsRSA.EncryptData(client.ServerEncryptEngine, clientPubBlob); client.SetEncryptionKey(client.SrpKey); var keyExchange = new GC2LS_KEY_EXCHANGE(encryptedClientKey); client.SendPacket(keyExchange); client.OnLoginSuccess(client, null); }
public override void HandlePacket(LobbyClient client, ServerPacket packet) { var reader = packet.Reader; // Read data from packet uint hwVValue = reader.ReadUInt32(); int encryptedDataSize = reader.ReadInt32(); byte[] encryptedData = reader.ReadBytes(encryptedDataSize); // Decrypt data byte[] decryptedData = WindowsRSA.DecryptData(client._clientDecryptEngine, encryptedData); // Create reader for decrypted data var dataReader = new APBBinaryReader(new MemoryStream(decryptedData)); string queryLanguage = dataReader.ReadASCIIString(4); if (queryLanguage != "WQL") { Log.Warn($"Unexpected query language for WMI request ({queryLanguage})"); client.Disconnect(); return; } int numSections = dataReader.ReadInt32(); int numFields = dataReader.ReadInt32(); XmlWriterSettings settings = new XmlWriterSettings(); settings.OmitXmlDeclaration = true; // Create array to store hashes of sections var hashes = new List <byte[]>(numSections); // Create XML writer to write response for WMI queries StringBuilder hwBuilder = new StringBuilder(); XmlWriter hwWriter = XmlWriter.Create(hwBuilder, settings); hwWriter.WriteStartElement("HW"); hwWriter.WriteAttributeString("v", hwVValue.ToString()); // Read each section, which contains data on a WQL query for the HW part of the response for (int i = 0; i < numSections; i++) { byte sectionNumber = dataReader.ReadByte(); byte sectionNameLength = dataReader.ReadByte(); string sectionName = dataReader.ReadASCIIString(sectionNameLength + 1); byte skipHash = dataReader.ReadByte(); byte selectLength = dataReader.ReadByte(); string selectClause = dataReader.ReadASCIIString(selectLength + 1); byte fromLength = dataReader.ReadByte(); string fromClause = dataReader.ReadASCIIString(fromLength + 1); Log.Info($"WMI Query: Section={sectionName}, SkipHash={skipHash}, Query=SELECT {selectClause} {fromClause}"); byte[] hash = client._hardwareStore.BuildWmiSectionAndHash(hwWriter, sectionName, selectClause, fromClause, (skipHash == 1)); if (hash != null) { hashes.Add(hash); } } hwWriter.WriteEndElement(); hwWriter.Flush(); // Create the middle section, which is the first 4 bytes of each hash concatenated together byte[] hashBlock = new byte[4 * hashes.Count]; for (int i = 0; i < hashes.Count; i++) { Buffer.BlockCopy(hashes[i], 0, hashBlock, i * 4, 4); } // Now we need to prepare the BFP section, which in APB is done with similar code to that at https://github.com/cavaliercoder/sysinv/ StringBuilder bfpBuilder = new StringBuilder(); XmlWriter bfpWriter = XmlWriter.Create(bfpBuilder, settings); client._hardwareStore.BuildBfpSection(bfpWriter); bfpWriter.Flush(); // Generate the hash for the BFP section byte[] bfpHash = client._hardwareStore.BuildBfpHash(); // Generate the Windows information section byte[] windowsInfo = client._hardwareStore.BuildWindowsInfo(); // Encrypt the BFP, HW, and hash sections with our public key byte[] hwUnicodeData = Encoding.Unicode.GetBytes(hwBuilder.ToString()); byte[] bfpUnicodeData = Encoding.Unicode.GetBytes(bfpBuilder.ToString()); byte[] encryptedHWData = WindowsRSA.EncryptData(client._serverEncryptEngine, hwUnicodeData); byte[] encryptedBFPData = WindowsRSA.EncryptData(client._serverEncryptEngine, bfpUnicodeData); byte[] encryptedHashBlock = WindowsRSA.EncryptData(client._serverEncryptEngine, hashBlock); // Construct and send the response! var hardwareInfo = new GC2LS_HARDWARE_INFO(windowsInfo, 0, 0, client._hardwareStore.BfpVersion, bfpHash, encryptedHashBlock, encryptedBFPData, encryptedHWData); client.SendPacket(hardwareInfo); }
public override void HandlePacket(LobbyClient client, ServerPacket packet) { var reader = packet.Reader; string realTag = reader.ReadUnicodeString(50); uint accountPremium = reader.ReadUInt32(); ulong timeStamp = reader.ReadUInt64(); ulong accountPermissions = reader.ReadUInt64(); Log.Debug($"m_szRealTag = {realTag}"); Log.Debug($"m_nAccountPremium = {accountPremium}"); Log.Debug($"m_nTimestamp = {timeStamp}"); Log.Debug($"m_nAccountPermissions = {accountPermissions}"); for (int i = 0; i < 5; i++) { Log.Debug($"m_nConfigFileVersion[{i}] = {reader.ReadInt32()}"); } ushort voicePortMin = reader.ReadUInt16(); ushort voicePortMax = reader.ReadUInt16(); uint voiceAccountId = reader.ReadUInt32(); string voiceUsername = reader.ReadASCIIString(17); string voiceKey = reader.ReadASCIIString(17); Log.Debug($"m_nVoicePortMin = {voicePortMin}"); Log.Debug($"m_nVoicePortMax = {voicePortMax}"); Log.Debug($"m_nVoiceAccountID = {voiceAccountId}"); Log.Debug($"m_szVoiceUsername = {voiceUsername}"); Log.Debug($"m_szUnknownVoiceKey = {voiceKey}"); // Read the server's public key RsaKeyParameters serverPub = WindowsRSA.ReadPublicKeyBlob(reader); // Read the rest of the packet data string countryCode = reader.ReadUnicodeString(); string voiceURL = reader.ReadASCIIString(); Log.Debug($"m_nCountryCode = {countryCode}"); Log.Debug($"m_szVoiceURL = {voiceURL}"); // Create a new random RSA 1024 bit keypair for the client var generator = new RsaKeyPairGenerator(); generator.Init(new KeyGenerationParameters(new SecureRandom(), 1024)); AsymmetricCipherKeyPair clientKeyPair = generator.GenerateKeyPair(); RsaKeyParameters clientPub = (RsaKeyParameters)clientKeyPair.Public; // Create the decryption engine for later client._clientDecryptEngine = new Pkcs1Encoding(new RsaEngine()); client._clientDecryptEngine.Init(false, clientKeyPair.Private); // Put the client public key into the Microsoft Crypto API format byte[] clientPubBlob = WindowsRSA.CreatePublicKeyBlob(clientPub); // Create encryption engine with the server's public key client._serverEncryptEngine = new Pkcs1Encoding(new RsaEngine()); client._serverEncryptEngine.Init(true, serverPub); // Encrypt the client key blob to send to the server byte[] encryptedClientKey = WindowsRSA.EncryptData(client._serverEncryptEngine, clientPubBlob); // Use the SRP key we calculated before client.SetEncryptionKey(client._srpKey); var keyExchange = new GC2LS_KEY_EXCHANGE(encryptedClientKey); client.SendPacket(keyExchange); client.OnLoginSuccess(client, null); }
public override void HandlePacket(LobbyClient client, ServerPacket packet) { var reader = packet.Reader; uint hwVValue = reader.ReadUInt32(); int encryptedDataSize = reader.ReadInt32(); byte[] encryptedData = reader.ReadBytes(encryptedDataSize); byte[] decryptedData = WindowsRSA.DecryptData(client.ClientDecryptEngine, encryptedData); var dataReader = new APBBinaryReader(new MemoryStream(decryptedData)); string queryLanguage = dataReader.ReadASCIIString(4); if (queryLanguage != "WQL") { client.Disconnect(); return; } int numSections = dataReader.ReadInt32(), numFields = dataReader.ReadInt32(); XmlWriterSettings settings = new XmlWriterSettings(); settings.OmitXmlDeclaration = true; var hashes = new List <byte[]>(numSections); StringBuilder hwBuilder = new StringBuilder(); XmlWriter hwWriter = XmlWriter.Create(hwBuilder, settings); hwWriter.WriteStartElement("HW"); hwWriter.WriteAttributeString("v", hwVValue.ToString()); for (int i = 0; i < numSections; i++) { byte sectionNumber = dataReader.ReadByte(), sectionNameLength = dataReader.ReadByte(); string sectionName = dataReader.ReadASCIIString(sectionNameLength + 1); byte skipHash = dataReader.ReadByte(), selectLength = dataReader.ReadByte(); string selectClause = dataReader.ReadASCIIString(selectLength + 1); byte fromLength = dataReader.ReadByte(); string fromClause = dataReader.ReadASCIIString(fromLength + 1); byte[] hash = client.HardwareStore.BuildWmiSectionAndHash(hwWriter, sectionName, selectClause, fromClause, (skipHash == 1)); if (hash != null) { hashes.Add(hash); } } hwWriter.WriteEndElement(); hwWriter.Flush(); byte[] hashBlock = new byte[4 * hashes.Count]; for (int i = 0; i < hashes.Count; i++) { Buffer.BlockCopy(hashes[i], 0, hashBlock, i * 4, 4); } StringBuilder bfpBuilder = new StringBuilder(); XmlWriter bfpWriter = XmlWriter.Create(bfpBuilder, settings); client.HardwareStore.BuildBfpSection(bfpWriter); bfpWriter.Flush(); byte[] bfpHash = client.HardwareStore.BuildBfpHash(); byte[] windowsInfo = client.HardwareStore.BuildWindowsInfo(); byte[] hwUnicodeData = Encoding.Unicode.GetBytes(hwBuilder.ToString()); byte[] bfpUnicodeData = Encoding.Unicode.GetBytes(bfpBuilder.ToString()); byte[] encryptedHWData = WindowsRSA.EncryptData(client.ServerEncryptEngine, hwUnicodeData); byte[] encryptedBFPData = WindowsRSA.EncryptData(client.ServerEncryptEngine, bfpUnicodeData); byte[] encryptedHashBlock = WindowsRSA.EncryptData(client.ServerEncryptEngine, hashBlock); var hardwareInfo = new GC2LS_HARDWARE_INFO(windowsInfo, 0, 0, client.HardwareStore.BfpVersion, bfpHash, encryptedHashBlock, encryptedBFPData, encryptedHWData); client.SendPacket(hardwareInfo); }