示例#1
0
        public O(Stream fileStream)
        {
            var logger = LogManager.GetLogger("O");

            var pageSize = 0x1000;

            var rawBytes2 = new byte[fileStream.Length];

            fileStream.Read(rawBytes2, 0, (int)fileStream.Length);

            var sig = 0x58444E49;

            var index2 = 0x0;

            while (index2 < rawBytes2.Length)
            {
                var index = 0x0;

                var rawBytes = new byte[pageSize];
                Buffer.BlockCopy(rawBytes2, index2, rawBytes, 0, pageSize);

                var headerBytes = new byte[4];

                fileStream.Seek(0, SeekOrigin.Begin);

                fileStream.Read(headerBytes, 0, 4);

                var sigActual = BitConverter.ToInt32(headerBytes, 0);

                if (sig != sigActual)
                {
                    {
                        throw new Exception("Invalid header! Expected 'INDX' Signature.");
                    }
                }

                Entries = new List <OEntry>();

                index += 4;

                var fixupOffset = BitConverter.ToInt16(rawBytes, index);
                index += 2;
                var numFixupPairs = BitConverter.ToInt16(rawBytes, index);
                index += 2;
                var logFileSequenceNumber = BitConverter.ToInt64(rawBytes, index);
                index += 8;
                var virtualClusterNumber = BitConverter.ToInt64(rawBytes, index);
                index += 8;

                var dataStartPosition = index;

                var indexValOffset = BitConverter.ToInt32(rawBytes, index);
                index += 4;
                var indexNodeSize = BitConverter.ToInt32(rawBytes, index);
                index += 4;
                var indexAllocatedSize = BitConverter.ToInt32(rawBytes, index);
                index += 4;
                var indexFlags = BitConverter.ToInt32(rawBytes, index);
                index += 4;

                var fixupTotalLength = numFixupPairs * 2;

                var fixupBuffer = new byte[fixupTotalLength];
                Buffer.BlockCopy(rawBytes, fixupOffset, fixupBuffer, 0, fixupTotalLength);


                var fixupData = new FixupData(fixupBuffer);

                var fixupOk = true;

                //fixup verification
                var counter = 512;
                foreach (var bytese in fixupData.FixupActual)
                {
                    //adjust the offset to where we need to check
                    var fixupOffset1 = counter - 2;

                    var expected = BitConverter.ToInt16(rawBytes, fixupOffset1);
                    if (expected != fixupData.FixupExpected)
                    {
                        fixupOk = false;
                        logger.Warn(
                            $"Fixup values do not match at 0x{fixupOffset1:X}. Expected: 0x{fixupData.FixupExpected:X2}, actual: 0x{expected:X2}");
                    }

                    //replace fixup expected with actual bytes. bytese has actual replacement values in it.
                    Buffer.BlockCopy(bytese, 0, rawBytes, fixupOffset1, 2);

                    counter += 512;
                }

                index += fixupTotalLength;

                while (index % 8 != 0)
                {
                    index += 1;
                }

                logger.Trace($"Overall offset: 0x{index2:X} Starting new INDEX ENTRY AREA at subindex {index:X}");

                while (index < rawBytes.Length)
                {
                    //var offsetToData = BitConverter.ToUInt16(rawBytes, index);
                    //var sizeOfData = BitConverter.ToUInt16(rawBytes, index+2);
                    var sizeOfIndexEntry = BitConverter.ToUInt16(rawBytes, index + 8);
                    //var sizeOfIndexKey = BitConverter.ToUInt16(rawBytes, index+10);
                    var flags = BitConverter.ToUInt16(rawBytes, index + 12);

                    if (sizeOfIndexEntry == 0x10)
                    {
                        sizeOfIndexEntry = 0x58;
                    }

                    if (flags == 3 || sizeOfIndexEntry == 0 || index + sizeOfIndexEntry > rawBytes.Length)
                    {
                        break;
                    }

                    var buff = new byte[sizeOfIndexEntry];
                    Buffer.BlockCopy(rawBytes, index, buff, 0, 0x58);

                    var oe = new OEntry(buff, index2 + index);

                    index += sizeOfIndexEntry;

                    if (oe.MftReference.MftEntryNumber == 0 && oe.MftReference.MftSequenceNumber == 0)
                    {
                        continue;
                    }

                    Entries.Add(oe);
                }

                index2 += pageSize;
            }
        }
示例#2
0
文件: I30.cs 项目: muyen2/MFT-1
        public I30(Stream fileStream)
        {
            var logger = LogManager.GetLogger("I30");

            var pageSize = 0x1000;

            //  var rawBytes2 = new byte[fileStream.Length];
            //  fileStream.Read(rawBytes2, 0, (int) fileStream.Length);

            var sig = 0x58444E49;

            Entries = new List <IndexEntry>();

            var pages = new List <byte[]>();

            using (var br = new BinaryReader(fileStream))
            {
                while (br.BaseStream.Position < br.BaseStream.Length)
                {
                    pages.Add(br.ReadBytes(pageSize));
                }
            }

            var pageNumber = 0;

            foreach (var page in pages)
            {
                //INDX pages are 4096 bytes each, so process them accordingly

                logger.Debug($"Procesing page 0x{pageNumber:X}");

                using (var br = new BinaryReader(new MemoryStream(page)))
                {
                    var sigActual = br.ReadInt32();

                    if (sig != sigActual)
                    {
                        throw new Exception("Invalid header! Expected 'INDX' Signature.");
                    }

                    var fixupOffset = br.ReadInt16();

                    var numFixupPairs = br.ReadInt16();

                    var logFileSequenceNumber = br.ReadInt64();

                    var virtualClusterNumber = br.ReadInt64();


                    var dataStartOffset   = br.ReadInt32();
                    var dataSize          = br.ReadInt32();
                    var dataSizeAllocated = br.ReadInt32();

                    var isLeafNode = br.ReadInt32() == 0; //this gets us by padding too

                    var fixupTotalLength = numFixupPairs * 2;

                    var fixupBuffer = new byte[fixupTotalLength];

                    fixupBuffer = br.ReadBytes(fixupTotalLength);

                    while (br.BaseStream.Position % 8 != 0)
                    {
                        br.ReadByte(); //gets us past padding
                    }

                    //since we need to change bytes for the index entries based on fixup, get an array of those bytes

                    var rawBytes = br.ReadBytes((int)(br.BaseStream.Length - br.BaseStream.Position));

                    var fixupData = new FixupData(fixupBuffer);

                    var fixupOk = true;

                    //fixup verification
                    var counter = 512 - dataStartOffset - 0x18; //datastartOffset is relative, so we need to account for where it begins, at 0x18
                    foreach (var bytese in fixupData.FixupActual)
                    {
                        //adjust the offset to where we need to check
                        var fixupOffset1 = counter - 2;

                        var expected = BitConverter.ToInt16(rawBytes, fixupOffset1);
                        if (expected != fixupData.FixupExpected)
                        {
                            fixupOk = false;
                            logger.Warn(
                                $"Fixup values do not match at 0x{fixupOffset1:X}. Expected: 0x{fixupData.FixupExpected:X2}, actual: 0x{expected:X2}");
                        }

                        //replace fixup expected with actual bytes. bytese has actual replacement values in it.
                        Buffer.BlockCopy(bytese, 0, rawBytes, fixupOffset1, 2);

                        counter += 512;
                    }

                    //rawbytes contains the data from the current page we need to parse to get to indexes
                    //datasize includes startoffset plus fixup, etc, so subtract data offset from size for the active index allocations
                    //valid data is allocated - dataoffset
                    //after that is slack

                    var activeSpace = new byte[dataSize - dataStartOffset];
                    Buffer.BlockCopy(rawBytes, 0, activeSpace, 0, activeSpace.Length);

                    var slackSpace = new byte[rawBytes.Length - activeSpace.Length];
                    Buffer.BlockCopy(rawBytes, dataSize - dataStartOffset, slackSpace, 0, slackSpace.Length);

                    //absolute offset is page # * 0x1000 + 0x18 + datastartoffset
                    //for slack, add activespace.len

                    using (var binaryReader = new BinaryReader(new MemoryStream(activeSpace)))
                    {
                        while (binaryReader.BaseStream.Position < binaryReader.BaseStream.Length)
                        {
                            var absoluteOffset = pageNumber * 0x1000 + 0x18 + dataStartOffset + binaryReader.BaseStream.Position;

                            logger.Trace($"IN ACTIVE LOOP: Absolute offset: 0x{absoluteOffset:X} brActive.BaseStream.Position: 0x{binaryReader.BaseStream.Position:X}");

                            binaryReader.ReadInt64();                              //mft info
                            var indexSize = binaryReader.ReadInt16();
                            binaryReader.BaseStream.Seek(-10, SeekOrigin.Current); //go back to start of the index data

                            var indxBuffer = binaryReader.ReadBytes(indexSize);

                            var ie = new IndexEntry(indxBuffer, absoluteOffset, pageNumber, false);

                            if (ie.MftReferenceSelf.MftEntryNumber != 0)
                            {
                                //its ok
                                logger.Info(ie);
                                Entries.Add(ie);
                            }
                        }
                    }


                    using (var binaryReader = new BinaryReader(new MemoryStream(slackSpace)))
                    {
                        var startOffset = 0;

                        while (binaryReader.BaseStream.Position < binaryReader.BaseStream.Length)
                        {
                            var absoluteOffset = pageNumber * 0x1000 + 0x18 + dataStartOffset + binaryReader.BaseStream.Position + activeSpace.Length;

                            logger.Info($"IN SLACK LOOP: Absolute offset: 0x{absoluteOffset:X} brActive.BaseStream.Position: 0x{binaryReader.BaseStream.Position:X}");
示例#3
0
文件: FileRecord.cs 项目: Seabreg/MFT
        public FileRecord(byte[] rawBytes, int offset)
        {
            Offset = offset;

            var sig = BitConverter.ToInt32(rawBytes, 0);

            switch (sig)
            {
            case FileSig:
                break;

            case BaadSig:
                _logger.Debug($"Bad signature at offset 0x{offset:X}");
                IsBad = true;
                return;

            default:
                //not initialized
                _logger.Debug($"Uninitialized entry (no signature) at offset 0x{offset:X}");
                IsUninitialized = true;
                return;
            }

            _logger.Debug($"Processing FILE record at offset 0x{offset:X}");

            Attributes = new List <Attribute>();

            FixupOffset     = BitConverter.ToInt16(rawBytes, 0x4);
            FixupEntryCount = BitConverter.ToInt16(rawBytes, 0x6);

            //to build fixup info, take FixupEntryCount x 2 bytes as each are 2 bytes long
            var fixupTotalLength = FixupEntryCount * 2;

            var fixupBuffer = new byte[fixupTotalLength];

            Buffer.BlockCopy(rawBytes, FixupOffset, fixupBuffer, 0, fixupTotalLength);

            //pull this early so we can check if its free in our fix up value messages
            EntryFlags = (EntryFlag)BitConverter.ToInt16(rawBytes, 0x16);

            FixupData = new FixupData(fixupBuffer);

            FixupOk = true;

            //fixup verification
            var counter = 512;

            foreach (var bytese in FixupData.FixupActual)
            {
                //adjust the offset to where we need to check
                var fixupOffset = counter - 2;

                var expected = BitConverter.ToInt16(rawBytes, fixupOffset);
                if (expected != FixupData.FixupExpected && EntryFlags != 0x0)
                {
                    FixupOk = false;
                    _logger.Warn(
                        $"Offset: 0x{Offset:X} Entry/seq: 0x{EntryNumber:X}/0x{SequenceNumber:X} Fixup values do not match at 0x{fixupOffset:X}. Expected: 0x{FixupData.FixupExpected:X2}, actual: 0x{expected:X2}");
                }

                //replace fixup expected with actual bytes. bytese has actual replacement values in it.
                Buffer.BlockCopy(bytese, 0, rawBytes, fixupOffset, 2);

                counter += 512;
            }

            LogSequenceNumber = BitConverter.ToInt64(rawBytes, 0x8);

            SequenceNumber = BitConverter.ToUInt16(rawBytes, 0x10);

            ReferenceCount = BitConverter.ToInt16(rawBytes, 0x12);

            FirstAttributeOffset = BitConverter.ToInt16(rawBytes, 0x14);

            ActualRecordSize = BitConverter.ToInt32(rawBytes, 0x18);

            AllocatedRecordSize = BitConverter.ToInt32(rawBytes, 0x1c);

            var entryBytes = new byte[8];

            Buffer.BlockCopy(rawBytes, 0x20, entryBytes, 0, 8);

            MftRecordToBaseRecord = new MftEntryInfo(entryBytes);

            FirstAvailablAttribueId = BitConverter.ToInt16(rawBytes, 0x28);

            EntryNumber = BitConverter.ToUInt32(rawBytes, 0x2c);

            //start attribute processing at FirstAttributeOffset

            var index = (int)FirstAttributeOffset;

            while (index < ActualRecordSize)
            {
                var attrType = (AttributeType)BitConverter.ToInt32(rawBytes, index);

                var attrSize = BitConverter.ToInt32(rawBytes, index + 4);

                if (attrSize == 0 || attrType == AttributeType.EndOfAttributes)
                {
                    index += 8; //skip -1 type and 0 size

                    if (index != ActualRecordSize)
                    {
                        _logger.Warn($"Slack space found in entry/seq: 0x{EntryNumber:X}/0x{SequenceNumber:X}");
                    }

                    //TODO process slack here?
                    break;
                }

                _logger.Debug(
                    $"Found Attribute Type {attrType.ToString()} at absolute offset: 0x{index + offset:X}");

                _logger.Trace(
                    $"ActualRecordSize: 0x{ActualRecordSize:X}, size: 0x{attrSize:X}, index: 0x{index:X}");

                var rawAttr = new byte[attrSize];
                Buffer.BlockCopy(rawBytes, index, rawAttr, 0, attrSize);

                switch (attrType)
                {
                case AttributeType.StandardInformation:
                    var si = new StandardInfo(rawAttr);
                    Attributes.Add(si);
                    break;

                case AttributeType.FileName:
                    var fi = new FileName(rawAttr);
                    Attributes.Add(fi);
                    break;

                case AttributeType.Data:
                    var d = new Data(rawAttr);
                    Attributes.Add(d);
                    break;

                case AttributeType.IndexAllocation:
                    var ia = new IndexAllocation(rawAttr);
                    Attributes.Add(ia);
                    break;

                case AttributeType.IndexRoot:
                    var ir = new IndexRoot(rawAttr);
                    Attributes.Add(ir);
                    break;

                case AttributeType.Bitmap:
                    var bm = new Bitmap(rawAttr);
                    Attributes.Add(bm);
                    break;

                case AttributeType.VolumeVersionObjectId:
                    var oi = new ObjectId_(rawAttr);
                    Attributes.Add(oi);
                    break;

                case AttributeType.SecurityDescriptor:
                    var sd = new SecurityDescriptor(rawAttr);
                    Attributes.Add(sd);
                    break;

                case AttributeType.VolumeName:
                    var vn = new VolumeName(rawAttr);
                    Attributes.Add(vn);
                    break;

                case AttributeType.VolumeInformation:
                    var vi = new VolumeInformation(rawAttr);
                    Attributes.Add(vi);
                    break;

                case AttributeType.LoggedUtilityStream:
                    var lus = new LoggedUtilityStream(rawAttr);
                    Attributes.Add(lus);
                    break;

                case AttributeType.ReparsePoint:
                    try
                    {
                        var rp = new ReparsePoint(rawAttr);
                        Attributes.Add(rp);
                    }
                    catch (Exception)
                    {
                        var l = LogManager.GetLogger("ReparsePoint");

                        l.Error(
                            $"There was an error parsing a ReparsePoint in FILE record at offset 0x{Offset:X}. Please extract via --dd and --do and send to [email protected]");
                    }

                    break;

                case AttributeType.AttributeList:
                    var al = new AttributeList(rawAttr);
                    Attributes.Add(al);
                    break;

                case AttributeType.Ea:
                    var ea = new ExtendedAttribute(rawAttr);
                    Attributes.Add(ea);
                    break;

                case AttributeType.EaInformation:
                    var eai = new ExtendedAttributeInformation(rawAttr);
                    Attributes.Add(eai);
                    break;

                default:
                    throw new Exception($"Add me: {attrType} (0x{attrType:X})");
                }

                index += attrSize;
            }

            //rest is slack. handle here?
            _logger.Trace($"Slack starts at 0x{index:X} Absolute offset: 0x{index + offset:X}");
        }