public byte[] BuildWmiSectionAndHash(XmlWriter writer, string sectionName, string select, string from, bool skipHash) { WmiSection section = GetSection(sectionName); var stringValues = new List <string>(); var numericValues = new List <int>(); string[] fieldNames = select.Split(','); writer.WriteStartElement(sectionName); if (skipHash) { writer.WriteAttributeString("s", "1"); } for (int i = 0; i < section.Data.Count; i++) { var dataEntry = section.Data[i]; foreach (var fieldName in fieldNames) { bool isSkipField = false; string actualFieldName = fieldName; if (fieldName.StartsWith("@")) { isSkipField = true; actualFieldName = fieldName.Substring(1); } if (!dataEntry.ContainsKey(actualFieldName)) { continue; } string fieldValue = dataEntry[actualFieldName]; writer.WriteStartElement(actualFieldName); writer.WriteAttributeString("n", (i + 1).ToString()); if (isSkipField || skipHash) { writer.WriteAttributeString("s", "1"); } else { if (section.NumericFields.Contains(fieldName)) { numericValues.Add(int.Parse(fieldValue)); } else { stringValues.Add(fieldValue); } } writer.WriteValue(fieldValue); writer.WriteEndElement(); } } writer.WriteEndElement(); if (!skipHash) { numericValues.Sort(); stringValues.Sort(); var sha1 = new Sha1Digest(); foreach (int value in numericValues) { sha1.BlockUpdate(BitConverter.GetBytes(value), 0, 4); } foreach (string value in stringValues) { byte[] rawData = Encoding.Unicode.GetBytes(value); sha1.BlockUpdate(rawData, 0, rawData.Length); } byte[] hash = new byte[sha1.GetDigestSize()]; sha1.DoFinal(hash, 0); return(hash); } return(null); }
public byte[] BuildWmiSectionAndHash(XmlWriter writer, string sectionName, string select, string from, bool skipHash) { WmiSection section = GetSection(sectionName); // Check if the SELECT and FROM clauses are the same in our static data and the requested data // It's not the end of the world if they're different, but we might send some dodgy data if (section.Select != select || section.From != from) { Log.Warn($"Queries do not match for '{sectionName}' section: request=SELECT {section.Select + section.From}, saved=SELECT {select + from}"); } // Define storage for WMI values to be hashed var stringValues = new List <string>(); var numericValues = new List <int>(); // Get the requested fields from the query string[] fieldNames = select.Split(','); writer.WriteStartElement(sectionName); if (skipHash) { writer.WriteAttributeString("s", "1"); } // For each row of saved data, write the appropriate fields to the xml stream for (int i = 0; i < section.Data.Count; i++) { var dataEntry = section.Data[i]; foreach (var fieldName in fieldNames) { bool isSkipField = false; string actualFieldName = fieldName; if (fieldName.StartsWith("@")) { isSkipField = true; actualFieldName = fieldName.Substring(1); } // Skip the field if we don't have data for it if (!dataEntry.ContainsKey(actualFieldName)) { Log.Warn($"Missing field '{fieldName}' from a data entry in the '{sectionName}' section"); continue; } string fieldValue = dataEntry[actualFieldName]; writer.WriteStartElement(actualFieldName); writer.WriteAttributeString("n", (i + 1).ToString()); // If the field starts with an @, we need to add s="1" if (isSkipField || skipHash) { writer.WriteAttributeString("s", "1"); } else { if (section.NumericFields.Contains(fieldName)) { numericValues.Add(int.Parse(fieldValue)); } else { stringValues.Add(fieldValue); } } writer.WriteValue(fieldValue); writer.WriteEndElement(); } } writer.WriteEndElement(); // Sort the values and hash if necessary if (!skipHash) { numericValues.Sort(); stringValues.Sort(); var sha1 = new Sha1Digest(); foreach (int value in numericValues) { sha1.BlockUpdate(BitConverter.GetBytes(value), 0, 4); } foreach (string value in stringValues) { byte[] rawData = Encoding.Unicode.GetBytes(value); sha1.BlockUpdate(rawData, 0, rawData.Length); } byte[] hash = new byte[sha1.GetDigestSize()]; sha1.DoFinal(hash, 0); return(hash); } return(null); }