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; 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); }