Esempio n. 1
0
        public void AnalyzeArea(IReader reader, long startAddress, MetaMap resultMap)
        {
            // Right now, this method only searches for the signatures of a few complex meta values.
            // Reflexives:      int32 entry count + uint32 address     + 4 bytes of padding
            // Data references: int32 size        + 8 bytes of padding + uint32 address
            // Tag references:  int32 class id    + 8 bytes of padding + uint32 datum index
            // ASCII strings:   characters with the values 0 or 0x20 - 0x7F

            // End at the next-highest address
            long endAddress = _memMap.GetNextHighestAddress(startAddress);

            if (endAddress == 0xFFFFFFFF)
            {
                throw new InvalidOperationException("Invalid start address for area analysis");
            }

            uint size          = (uint)(endAddress - startAddress); // The size of the block of data
            int  paddingLength = 0;                                 // The number of 4-byte padding values that have been read
            uint prePadding    = 0;                                 // The last non-padding uint32 that was read

            MetaValueGuess pendingGuess = null;                     // If not null and padding is encountered, this guess is confirmed

            for (int offset = 0; offset < size; offset += 4)
            {
                uint value = reader.ReadUInt32();

                long expValue = _expander.Expand(value);

                if (IsPadding(value))
                {
                    if (paddingLength == 0 && pendingGuess != null)
                    {
                        resultMap.AddGuess(pendingGuess);

                        // Add the address to the memory map
                        long address = pendingGuess.Pointer;
                        _memMap.AddAddress(address, (int)reader.Position);
                    }

                    // More padding! :D
                    paddingLength++;
                    pendingGuess = null;
                }
                else
                {
                    pendingGuess = null;
                    if (offset <= size - 8 &&
                        prePadding > 0 &&
                        prePadding < 0x80000000
                        // && (value & 3) == 0
                        && IsValidAddress(expValue) &&
                        expValue + prePadding > value &&
                        IsValidAddress(expValue + prePadding - 1) &&
                        !_memMap.BlockCrossesBoundary(expValue, (int)prePadding))
                    {
                        // Either a reflexive or a data reference
                        // Check the padding to determine which (see the comments at the beginning of this method)
                        if (paddingLength == 2 && offset >= 12 && (prePadding & 3) == 0)
                        {
                            // Found a data reference
                            uint dataSize = prePadding;
                            pendingGuess = new MetaValueGuess(offset - 12, MetaValueType.DataReference, expValue, dataSize);
                            // Guess with Pointer = address, Data1 = data size
                        }
                        else if (paddingLength == 0 && offset >= 4)
                        {
                            // Found a reflexive!
                            uint entryCount = prePadding;
                            pendingGuess = new MetaValueGuess(offset - 4, MetaValueType.Reflexive, expValue, entryCount);
                            // Guess with Pointer = address, Data1 = entry count
                        }
                    }
                    if (paddingLength == 2 && offset >= 12 &&
                        (_classIds.Contains((int)prePadding) || (prePadding == 0xFFFFFFFF && value == 0xFFFFFFFF)))
                    {
                        // Found a tag reference
                        uint classId    = prePadding;
                        uint datumIndex = value;
                        var  guess      = new MetaValueGuess(offset - 12, MetaValueType.TagReference, datumIndex, classId);
                        // Guess with Pointer = datum index, Data1 = class id
                        resultMap.AddGuess(guess);
                    }

                    // This obviously isn't a padding value because IsPadding returned false,
                    // so update padding run information accordingly
                    prePadding    = value;
                    paddingLength = 0;
                }
            }
        }