protected byte[] _ReadArrayItem(FieldGuessData output, uint itemSize) { try { using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider()) { return(sha1.ComputeHash(MetadataReader.ReadBytes((int)itemSize))); } } catch (EndOfStreamException) { return(null); } }
protected void TryReadArrayItems(FieldGuessData output) { const uint max = 32; Metadata.Position = output.ArrayInfo.Offset; output.ArraySHA1 = new Dictionary <uint, ArrayFieldDataHash[]>(); for (uint i = 1; i <= max; i++) { // bool badSize = false; output.ArraySHA1[i] = new ArrayFieldDataHash[output.ArrayInfo.Count]; long itemBeforePos = Metadata.Position; for (uint ai = 0; ai < output.ArrayInfo.Count; ++ai) { // long thisItemBeforePos = metadata.Position; output.ArraySHA1[i][ai] = new ArrayFieldDataHash { SHA1 = _ReadArrayItem(output, i), ItemSize = i }; // if (output.ArraySHA1[i][ai].SHA1 == null) { // badSize = true; // } // if (badSize) { // continue; // } // if (i != 16 || output.ArraySHA1[i][ai].SHA1 == null) continue; // todo: this is broken //metadata.Position = thisItemBeforePos; //ulong padding = metadataReader.ReadUInt64(); //ulong key = metadataReader.ReadUInt64(); ////Common.STUGUID guid = new Common.STUGUID(key, padding); //Common.STUGUID guid = new Common.STUGUID(key); //DemangleInstance(guid, output.Checksum); //using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider()) { // output.ArraySHA1[i][ai].DemangleSHA1 = sha1.ComputeHash(BitConverter.GetBytes(guid)); //} } Metadata.Position = itemBeforePos; } }
protected void TryReadInlineArray(FieldGuessData output, BinaryReader reader) { if (output.IsInlineStandard) { return; } if (output.InlineFields?.Length >= 1) { return; } long beforePos = reader.BaseStream.Position; STUInlineArrayInfo inline = reader.Read <STUInlineArrayInfo>(); try { Dictionary <uint, FieldGuessData> inlineFields = new Dictionary <uint, FieldGuessData>(); for (uint i = 0; i < inline.Count; ++i) { uint fieldIndex = reader.ReadUInt32(); foreach (FieldGuessData inlineField in GuessFields(InstanceFields[fieldIndex], reader)) { if (!inlineFields.ContainsKey(inlineField.Checksum)) { inlineFields[inlineField.Checksum] = inlineField; } else { if (inlineFields[inlineField.Checksum].Size < inlineField.Size) { inlineFields[inlineField.Checksum].Size = inlineField.Size; } } } } output.InlineFields = inlineFields.Values.ToArray(); output.IsInlineArray = true; } catch (Exception) { output.IsInlineArray = false; } reader.BaseStream.Position = beforePos; }
protected void TryReadInlineStandard(FieldGuessData output, BinaryReader reader) { if (output.IsInlineArray) { return; } long beforePos = reader.BaseStream.Position; STUInlineInfo inline = reader.Read <STUInlineInfo>(); try { FieldGuessData[] inlineFields = GuessFields(InstanceFields[inline.FieldListIndex], reader); output.IsInlineStandard = true; output.InlineFields = inlineFields; } catch (Exception) { output.IsInlineStandard = false; } reader.BaseStream.Position = beforePos; }
protected void TryReadArray(FieldGuessData output, STUInstanceField field, BinaryReader reader) { long beforePos = reader.BaseStream.Position; try { int offset = reader.ReadInt32(); Metadata.Position = offset; STUArrayInfo array = MetadataReader.Read <STUArrayInfo>(); if (array.Count < 99999 && array.Count > 0) { output.IsArray = true; output.ArrayInfo = array; } // uint parent = 0; // if (instanceArrayRef?.Length > array.InstanceIndex) { // parent = instanceArrayRef[array.InstanceIndex].Checksum; // } } catch (Exception) { output.IsArray = false; } reader.BaseStream.Position = beforePos; }
protected FieldGuessData[] GuessFields(STUInstanceField[] definedFields, BinaryReader reader, uint instanceChecksum = 0) { FieldGuessData[] output = new FieldGuessData[definedFields.Length]; // FieldLocationInfo[] fieldSizes = GetFieldSizes(definedFields, reader); // todo: use this for something uint outputIndex = 0; foreach (STUInstanceField field in definedFields) { FieldGuessData fieldOutput = new FieldGuessData { Size = field.FieldSize, Checksum = field.FieldChecksum }; if (instanceChecksum != 0) { foreach (KeyValuePair <uint, List <ChainedInstanceInfo> > pair in ChainedInstances ) // if (pair.Key != instanceChecksum) continue; { foreach (ChainedInstanceInfo info in pair.Value) { if (info.OwnerChecksum != instanceChecksum || info.OwnerField != field.FieldChecksum) { continue; } fieldOutput.IsChained = true; fieldOutput.ChainedInstanceChecksum = info.Checksum; break; } } } if (field.FieldSize == 0) { TryReadInlineStandard(fieldOutput, reader); TryReadInlineArray(fieldOutput, reader); uint size = reader.ReadUInt32(); reader.BaseStream.Position += size; } else { TryReadArray(fieldOutput, field, reader); if (fieldOutput.IsArray) { TryReadArrayItems(fieldOutput); } long startPosition = reader.BaseStream.Position; using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider()) { byte[] fieldSHA1Demangle = null; if (field.FieldSize == 8) { Common.STUGUID f = new Common.STUGUID(reader.ReadUInt64()); DemangleInstance(f, field.FieldChecksum); fieldSHA1Demangle = sha1.ComputeHash(BitConverter.GetBytes(f)); // is this bad? reader.BaseStream.Position = startPosition; } byte[] fieldSHA1 = sha1.ComputeHash(reader.ReadBytes((int)field.FieldSize)); fieldOutput.SHA1 = fieldSHA1; fieldOutput.DemangleSHA1 = fieldSHA1Demangle; } } output[outputIndex] = fieldOutput; outputIndex++; } return(output); }