Example #1
0
        public Version26(byte[] rawBytes, string sourceFilename)
        {
            SourceFilename = sourceFilename;

            RawBytes = rawBytes;

            Header = new Header(rawBytes.Take(84).ToArray());

            //TODO factor out creation of File info blocks
            var fileInfoBytes = rawBytes.Skip(84).Take(224).ToArray();

            FileMetricsOffset = BitConverter.ToInt32(fileInfoBytes, 0);
            FileMetricsCount = BitConverter.ToInt32(fileInfoBytes, 4);

            TraceChainsOffset = BitConverter.ToInt32(fileInfoBytes, 8);
            TraceChainsCount = BitConverter.ToInt32(fileInfoBytes, 12);

            FilenameStringsOffset = BitConverter.ToInt32(fileInfoBytes, 16);
            FilenameStringsSize = BitConverter.ToInt32(fileInfoBytes, 20);

            VolumesInfoOffset = BitConverter.ToInt32(fileInfoBytes, 24);
            VolumeCount = BitConverter.ToInt32(fileInfoBytes, 28);

            VolumesInfoSize = BitConverter.ToInt32(fileInfoBytes, 32);

            //at offset 36 there are 8 unknown values, seemingly empty

            var runtimeBytes = fileInfoBytes.Skip(44).Take(64).ToArray();

            LastRunTimes = new List<DateTimeOffset>();

            for (var i = 0; i < 7; i++)
            {
                var rawTime = BitConverter.ToInt64(runtimeBytes, i*8);

                if (rawTime > 0)
                {
                    LastRunTimes.Add(DateTimeOffset.FromFileTime(rawTime));
                }
            }

            //at offset 108 there are 16 bytes of unknown, possibly previous data from runtimes

            RunCount = BitConverter.ToInt32(fileInfoBytes, 124);

            var unknown0 = BitConverter.ToInt32(fileInfoBytes, 128);
            var unknown1 = BitConverter.ToInt32(fileInfoBytes, 132);
            //at offset 136 there is 88 bytes of unknown, empty values
            var unknown2 = BitConverter.ToInt32(fileInfoBytes, 128);

            //TODO do something with stuff below here. relevant stuff must be moved to interface

            var fileMetricsBytes = rawBytes.Skip(FileMetricsOffset).Take(FileMetricsCount*32).ToArray();
            var tempIndex = 0;

            //TODO must end up as a property
            var fileMetrics = new List<FileMetric23>();

            while (tempIndex < fileMetricsBytes.Length)
            {
                fileMetrics.Add(new FileMetric23(fileMetricsBytes.Skip(tempIndex).Take(32).ToArray()));
                tempIndex += 32;
            }

            var traceChains = new List<TraceChain17>();

            var traceChainBytes = rawBytes.Skip(TraceChainsOffset).Take(12*TraceChainsCount).ToArray();
            var traceIndex = 0;
            while (traceIndex < traceChainBytes.Length)
            {
                traceChains.Add(new TraceChain17(traceChainBytes.Skip(traceIndex).Take(12).ToArray()));
                traceIndex += 12;
            }

            var filenameStringsBytes = rawBytes.Skip(FilenameStringsOffset).Take(FilenameStringsSize).ToArray();

            var filenamesRaw = Encoding.Unicode.GetString(filenameStringsBytes);
            var fileNames = filenamesRaw.Split(new[] {'\0'}, StringSplitOptions.RemoveEmptyEntries);

            Filenames = new List<string>();

            Filenames.AddRange(fileNames);

            var volumeInfoBytes = rawBytes.Skip(VolumesInfoOffset).Take(VolumesInfoSize).ToArray();
            var volumeDevicePathOffset = BitConverter.ToInt32(volumeInfoBytes, 0);
            var volDevicePathNumChars = BitConverter.ToInt32(volumeInfoBytes, 4);

            //TODO for all versions, need to loop to get all volumes, not just first one, based on VolumeCount

            VolumeDeviceName =
                Encoding.Unicode.GetString(
                    rawBytes.Skip(VolumesInfoOffset + volumeDevicePathOffset).Take(volDevicePathNumChars*2).ToArray());

            var ct = BitConverter.ToInt64(volumeInfoBytes, 8);
            VolumeCreatedOn = DateTimeOffset.FromFileTime(ct);

            VolumeSerialNumber = BitConverter.ToInt32(volumeInfoBytes, 16).ToString("X");

            var fileRefOffset = BitConverter.ToInt32(volumeInfoBytes, 20);
            var fileRefSize = BitConverter.ToInt32(volumeInfoBytes, 24);


            var dirStringsOffset = BitConverter.ToInt32(volumeInfoBytes, 28);
            var numDirectoryStrings = BitConverter.ToInt32(volumeInfoBytes, 32);


            //filerefs are at VolumesInfoOffset + fileRefOffset
            var fileRefsIndex = VolumesInfoOffset + fileRefOffset;
            var fileRefBytes = rawBytes.Skip(fileRefsIndex).Take(fileRefSize).ToArray();

            var fileRefVer = BitConverter.ToInt32(fileRefBytes, 0);
            var numFileRefs = BitConverter.ToInt32(fileRefBytes, 4);

            tempIndex = 8;

            FileReferences = new List<MFTInformation>();

            while (tempIndex < fileRefBytes.Length && FileReferences.Count < numFileRefs)
            {
                FileReferences.Add(new MFTInformation(fileRefBytes.Skip(tempIndex).Take(8).ToArray()));
                tempIndex += 8;
            }

            DirectoryNames = new List<string>();

            var dirStringsIndex = VolumesInfoOffset + dirStringsOffset;
            var dirStringsBytes = rawBytes.Skip(dirStringsIndex).ToArray();

            tempIndex = 0;
            for (var i = 0; i < numDirectoryStrings; i++)
            {
                var dirCharCount = BitConverter.ToInt16(dirStringsBytes, tempIndex)*2 + 2;
                // double the count since its unicode and add 2 extra for null char
                tempIndex += 2;
                var dirName = Encoding.Unicode.GetString(dirStringsBytes, tempIndex, dirCharCount).Trim('\0');
                DirectoryNames.Add(dirName);

                tempIndex += dirCharCount;
            }
        }
Example #2
0
        public Version23(byte[] rawBytes, string sourceFilename)
        {
            SourceFilename = sourceFilename;

            RawBytes = rawBytes;

            Header = new Header(rawBytes.Take(84).ToArray());

            var fileInfoBytes = rawBytes.Skip(84).Take(156).ToArray();

            FileMetricsOffset = BitConverter.ToInt32(fileInfoBytes, 0);
            FileMetricsCount = BitConverter.ToInt32(fileInfoBytes, 4);

            TraceChainsOffset = BitConverter.ToInt32(fileInfoBytes, 8);
            TraceChainsCount = BitConverter.ToInt32(fileInfoBytes, 12);

            FilenameStringsOffset = BitConverter.ToInt32(fileInfoBytes, 16);
            FilenameStringsSize = BitConverter.ToInt32(fileInfoBytes, 20);

            VolumesInfoOffset = BitConverter.ToInt32(fileInfoBytes, 24);
            VolumeCount = BitConverter.ToInt32(fileInfoBytes, 28);

            VolumesInfoSize = BitConverter.ToInt32(fileInfoBytes, 32);

            //at offset 36 there are 8 unknown bytes

            var rawTime = BitConverter.ToInt64(fileInfoBytes, 44);

            LastRunTimes = new List<DateTimeOffset>();

            LastRunTimes.Add(DateTimeOffset.FromFileTime(rawTime));

            //at offset 52 there are 16 unknown bytes

            RunCount = BitConverter.ToInt32(fileInfoBytes, 68);

            //at offset 72, there are 4 unknown bytes
            //at offset 76, there are 80 unknown bytes

            //TODO do something with stuff below here. relevant stuff must be moved to interface

            var fileMetricsBytes = rawBytes.Skip(FileMetricsOffset).Take(FileMetricsCount*32).ToArray();
            var tempIndex = 0;

            var fileMetrics = new List<FileMetric23>();

            while (tempIndex < fileMetricsBytes.Length)
            {
                fileMetrics.Add(new FileMetric23(fileMetricsBytes.Skip(tempIndex).Take(32).ToArray()));
                tempIndex += 32;
            }

            var traceChains = new List<TraceChain17>();

            var traceChainBytes = rawBytes.Skip(TraceChainsOffset).Take(12*TraceChainsCount).ToArray();
            var traceIndex = 0;
            while (traceIndex < traceChainBytes.Length)
            {
                traceChains.Add(new TraceChain17(traceChainBytes.Skip(traceIndex).Take(12).ToArray()));
                traceIndex += 12;
            }

            var filenameStringsBytes = rawBytes.Skip(FilenameStringsOffset).Take(FilenameStringsSize).ToArray();

            var filenamesRaw = Encoding.Unicode.GetString(filenameStringsBytes);
            var fileNames = filenamesRaw.Split(new[] {'\0'}, StringSplitOptions.RemoveEmptyEntries);

            Filenames = new List<string>();

            Filenames.AddRange(fileNames);

            var volumeInfoBytes = rawBytes.Skip(VolumesInfoOffset).Take(VolumesInfoSize).ToArray();
            var volumeDevicePathOffset = BitConverter.ToInt32(volumeInfoBytes, 0);
            var volDevicePathNumChars = BitConverter.ToInt32(volumeInfoBytes, 4);

            VolumeDeviceName =
                Encoding.Unicode.GetString(
                    rawBytes.Skip(VolumesInfoOffset + volumeDevicePathOffset).Take(volDevicePathNumChars*2).ToArray());

            var ct = BitConverter.ToInt64(volumeInfoBytes, 8);
            VolumeCreatedOn = DateTimeOffset.FromFileTime(ct);

            VolumeSerialNumber = BitConverter.ToInt32(volumeInfoBytes, 16).ToString("X");

            var fileRefOffset = BitConverter.ToInt32(volumeInfoBytes, 20);
            var fileRefSize = BitConverter.ToInt32(volumeInfoBytes, 24);


            var dirStringsOffset = BitConverter.ToInt32(volumeInfoBytes, 28);
            var numDirectoryStrings = BitConverter.ToInt32(volumeInfoBytes, 32);


            //filerefs are at VolumesInfoOffset + fileRefOffset
            var fileRefsIndex = VolumesInfoOffset + fileRefOffset;
            var fileRefBytes = rawBytes.Skip(fileRefsIndex).Take(fileRefSize).ToArray();

            var fileRefVer = BitConverter.ToInt32(fileRefBytes, 0);
            var numFileRefs = BitConverter.ToInt32(fileRefBytes, 4);

            tempIndex = 8;

            FileReferences = new List<MFTInformation>();

            while (tempIndex < fileRefBytes.Length && FileReferences.Count < numFileRefs)
            {
                FileReferences.Add(new MFTInformation(fileRefBytes.Skip(tempIndex).Take(8).ToArray()));
                tempIndex += 8;
            }

            DirectoryNames = new List<string>();

            var dirStringsIndex = VolumesInfoOffset + dirStringsOffset;
            var dirStringsBytes = rawBytes.Skip(dirStringsIndex).ToArray();

            tempIndex = 0;
            for (var i = 0; i < numDirectoryStrings; i++)
            {
                var dirCharCount = BitConverter.ToInt16(dirStringsBytes, tempIndex)*2 + 2;
                // double the count since its unicode and add 2 extra for null char
                tempIndex += 2;
                var dirName = Encoding.Unicode.GetString(dirStringsBytes, tempIndex, dirCharCount).Trim('\0');
                DirectoryNames.Add(dirName);

                tempIndex += dirCharCount;
            }
        }
Example #3
0
        public Version17(byte[] rawBytes, string sourceFilename)
        {
            SourceFilename = sourceFilename;

            RawBytes = rawBytes;

            var headerBytes = new byte[84];
            Buffer.BlockCopy(rawBytes, 0, headerBytes, 0, 84);

            Header = new Header(headerBytes);

            var fi = new FileInfo(sourceFilename);
            SourceCreatedOn = new DateTimeOffset(fi.CreationTimeUtc);
            SourceModifiedOn = new DateTimeOffset(fi.LastWriteTimeUtc);
            SourceAccessedOn = new DateTimeOffset(fi.LastAccessTimeUtc);

            var fileInfoBytes = new byte[68];
            Buffer.BlockCopy(rawBytes, 84, fileInfoBytes, 0, 68);

            FileMetricsOffset = BitConverter.ToInt32(fileInfoBytes, 0);
            FileMetricsCount = BitConverter.ToInt32(fileInfoBytes, 4);

            TraceChainsOffset = BitConverter.ToInt32(fileInfoBytes, 8);
            TraceChainsCount = BitConverter.ToInt32(fileInfoBytes, 12);

            FilenameStringsOffset = BitConverter.ToInt32(fileInfoBytes, 16);
            FilenameStringsSize = BitConverter.ToInt32(fileInfoBytes, 20);

            VolumesInfoOffset = BitConverter.ToInt32(fileInfoBytes, 24);
            VolumeCount = BitConverter.ToInt32(fileInfoBytes, 28);

            VolumesInfoSize = BitConverter.ToInt32(fileInfoBytes, 32);

            var rawTime = BitConverter.ToInt64(fileInfoBytes, 36);

            LastRunTimes = new List<DateTimeOffset>();

            LastRunTimes.Add(DateTimeOffset.FromFileTime(rawTime).ToUniversalTime());

            TotalDirectoryCount = -1;

            RunCount = BitConverter.ToInt32(fileInfoBytes, 60);

            var fileMetricsBytes = new byte[FileMetricsCount * 20];
            Buffer.BlockCopy(rawBytes, FileMetricsOffset, fileMetricsBytes, 0, FileMetricsCount * 20);
            var tempIndex = 0;

            FileMetrics = new List<FileMetric>();

            var fileMetricsTempBuffer = new byte[20];
            while (tempIndex < fileMetricsBytes.Length)
            {
                Buffer.BlockCopy(fileMetricsBytes, tempIndex, fileMetricsTempBuffer, 0, 20);
                FileMetrics.Add(new FileMetric(fileMetricsTempBuffer, true));
                tempIndex += 20;
            }

            TraceChains = new List<TraceChain>();

            var traceChainBytes = new byte[12 * TraceChainsCount];
            Buffer.BlockCopy(rawBytes, TraceChainsOffset, traceChainBytes, 0, 12 * TraceChainsCount);
            var traceIndex = 0;
            var traceChainTempBuffer = new byte[12];
            while (traceIndex < traceChainBytes.Length)
            {
                Buffer.BlockCopy(traceChainBytes, traceIndex, traceChainTempBuffer, 0, 12);
                TraceChains.Add(new TraceChain(traceChainTempBuffer, false));
                traceIndex += 12;
            }

            var filenameStringsBytes = new byte[FilenameStringsSize];
            Buffer.BlockCopy(rawBytes, FilenameStringsOffset, filenameStringsBytes, 0, FilenameStringsSize);

            var filenamesRaw = Encoding.Unicode.GetString(filenameStringsBytes);
            var fileNames = filenamesRaw.Split(new[] {'\0'}, StringSplitOptions.RemoveEmptyEntries);

            Filenames = new List<string>();

            Filenames.AddRange(fileNames);

            var volumeInfoBytes = new byte[VolumesInfoSize];
            Buffer.BlockCopy(rawBytes, VolumesInfoOffset, volumeInfoBytes, 0, VolumesInfoSize);

            VolumeInformation = new List<VolumeInfo>();

            var volBytes = new byte[40];
            for (var j = 0; j < VolumeCount; j++)
            {
                var skipSize = j*40;
                Buffer.BlockCopy(volumeInfoBytes, skipSize, volBytes, 0, 40);

                var volDevOffset = BitConverter.ToInt32(volBytes, 0);
                var volDevNumChar = BitConverter.ToInt32(volBytes, 4);

                var ct = BitConverter.ToInt64(volBytes, 8);

                var devNameBytes = new byte[volDevNumChar * 2];
                Buffer.BlockCopy(rawBytes, VolumesInfoOffset + volDevOffset, devNameBytes, 0, volDevNumChar * 2);
                var devName = Encoding.Unicode.GetString(devNameBytes);

                var sn = BitConverter.ToInt32(volBytes, 16).ToString("X");

                VolumeInformation.Add(new VolumeInfo(volDevOffset, DateTimeOffset.FromFileTime(ct).ToUniversalTime(), sn, devName));

                var fileRefOffset = BitConverter.ToInt32(volBytes, 20);
                var fileRefSize = BitConverter.ToInt32(volBytes, 24);

                var dirStringsOffset = BitConverter.ToInt32(volBytes, 28);
                var numDirectoryStrings = BitConverter.ToInt32(volBytes, 32);

                //filerefs are at VolumesInfoOffset + fileRefOffset
                var fileRefsIndex = VolumesInfoOffset + fileRefOffset;
                var fileRefBytes = new byte[fileRefSize];
                Buffer.BlockCopy(rawBytes, fileRefsIndex, fileRefBytes, 0, fileRefSize);

                var fileRefVer = BitConverter.ToInt32(fileRefBytes, 0);
                var numFileRefs = BitConverter.ToInt32(fileRefBytes, 4);

                tempIndex = 8;

                var tempFileRefBytes = new byte[8];
                while (tempIndex < fileRefBytes.Length && VolumeInformation.Last().FileReferences.Count < numFileRefs)
                {
                    Buffer.BlockCopy(fileRefBytes, tempIndex, tempFileRefBytes, 0, 8);
                    VolumeInformation.Last()
                        .FileReferences.Add(new MFTInformation(tempFileRefBytes));
                    tempIndex += 8;
                }

                var dirStringsIndex = VolumesInfoOffset + dirStringsOffset;
                var dirStringsBytes = new byte[rawBytes.Length - dirStringsIndex];
                Buffer.BlockCopy(rawBytes, dirStringsIndex, dirStringsBytes, 0, rawBytes.Length - dirStringsIndex);

                tempIndex = 0;
                for (var k = 0; k < numDirectoryStrings; k++)
                {
                    var dirCharCount = BitConverter.ToInt16(dirStringsBytes, tempIndex)*2 + 2;
                    // double the count since its Unicode and add 2 extra for null char
                    tempIndex += 2;
                    var dirName = Encoding.Unicode.GetString(dirStringsBytes, tempIndex, dirCharCount).Trim('\0');
                    VolumeInformation.Last().DirectoryNames.Add(dirName);

                    tempIndex += dirCharCount;
                }
            }
        }
Example #4
0
        public Version26(byte[] rawBytes, string sourceFilename)
        {
            SourceFilename = sourceFilename;

            RawBytes = rawBytes;

            var headerBytes = new byte[84];
            Buffer.BlockCopy(rawBytes, 0, headerBytes, 0, 84);

            Header = new Header(headerBytes);

            var fi = new FileInfo(sourceFilename);
            SourceCreatedOn = new DateTimeOffset(fi.CreationTimeUtc);
            SourceModifiedOn = new DateTimeOffset(fi.LastWriteTimeUtc);
            SourceAccessedOn = new DateTimeOffset(fi.LastAccessTimeUtc);

            //TODO factor out creation of File info blocks
            var fileInfoBytes = new byte[224];
            Buffer.BlockCopy(rawBytes, 84, fileInfoBytes, 0, 224);

            FileMetricsOffset = BitConverter.ToInt32(fileInfoBytes, 0);
            FileMetricsCount = BitConverter.ToInt32(fileInfoBytes, 4);

            TraceChainsOffset = BitConverter.ToInt32(fileInfoBytes, 8);
            TraceChainsCount = BitConverter.ToInt32(fileInfoBytes, 12);

            FilenameStringsOffset = BitConverter.ToInt32(fileInfoBytes, 16);
            FilenameStringsSize = BitConverter.ToInt32(fileInfoBytes, 20);

            VolumesInfoOffset = BitConverter.ToInt32(fileInfoBytes, 24);
            VolumeCount = BitConverter.ToInt32(fileInfoBytes, 28);

            VolumesInfoSize = BitConverter.ToInt32(fileInfoBytes, 32);

            //at offset 36 there are 8 unknown values, seemingly empty
            TotalDirectoryCount = BitConverter.ToInt32(fileInfoBytes, 36);

            var runtimeBytes = fileInfoBytes.Skip(44).Take(64).ToArray();

            LastRunTimes = new List<DateTimeOffset>();

            for (var i = 0; i < 8; i++)
            {
                var rawTime = BitConverter.ToInt64(runtimeBytes, i*8);

                if (rawTime > 0)
                {
                    LastRunTimes.Add(DateTimeOffset.FromFileTime(rawTime).ToUniversalTime());
                }
            }

            //at offset 108 there are 16 bytes of unknown, possibly previous data from runtimes

            RunCount = BitConverter.ToInt32(fileInfoBytes, 124);

            var unknown0 = BitConverter.ToInt32(fileInfoBytes, 128);
            var unknown1 = BitConverter.ToInt32(fileInfoBytes, 132);
            //at offset 136 there is 88 bytes of unknown, empty values
            var unknown2 = BitConverter.ToInt32(fileInfoBytes, 128);

            var fileMetricsBytes = new byte[FileMetricsCount * 32];
            Buffer.BlockCopy(rawBytes, FileMetricsOffset, fileMetricsBytes, 0, FileMetricsCount * 32);
            var tempIndex = 0;

            FileMetrics = new List<FileMetric>();

             var fileMetricsTempBuffer = new byte[32];
            while (tempIndex < fileMetricsBytes.Length)
            {
                Buffer.BlockCopy(fileMetricsBytes, tempIndex, fileMetricsTempBuffer, 0, 32);
                FileMetrics.Add(new FileMetric(fileMetricsTempBuffer, false));
                tempIndex += 32;
            }

            TraceChains = new List<TraceChain>();

            var traceChainBytes = new byte[12 * TraceChainsCount]; 
            Buffer.BlockCopy(rawBytes, TraceChainsOffset, traceChainBytes, 0, 12 * TraceChainsCount);
            var traceIndex = 0;
            var traceChainTempBuffer = new byte[12];
            while (traceIndex < traceChainBytes.Length)
            {
                Buffer.BlockCopy(traceChainBytes, traceIndex, traceChainTempBuffer, 0, 12);
                TraceChains.Add(new TraceChain(traceChainTempBuffer, false));
                traceIndex += 12;
            }

            var filenameStringsBytes = new byte[FilenameStringsSize];
            Buffer.BlockCopy(rawBytes, FilenameStringsOffset, filenameStringsBytes, 0, FilenameStringsSize);

            var filenamesRaw = Encoding.Unicode.GetString(filenameStringsBytes);
            var fileNames = filenamesRaw.Split(new[] {'\0'}, StringSplitOptions.RemoveEmptyEntries);

            Filenames = new List<string>();

            Filenames.AddRange(fileNames);

            var volumeInfoBytes = new byte[VolumesInfoSize];
            Buffer.BlockCopy(rawBytes, VolumesInfoOffset, volumeInfoBytes, 0, VolumesInfoSize);

            VolumeInformation = new List<VolumeInfo>();

            var volBytes = new byte[104];
            for (var j = 0; j < VolumeCount; j++)
            {
                var skipSize = j*104;
                Buffer.BlockCopy(volumeInfoBytes, skipSize, volBytes, 0, 104);

                var volDevOffset = BitConverter.ToInt32(volBytes, 0);
                var volDevNumChar = BitConverter.ToInt32(volBytes, 4);

                var ct = BitConverter.ToInt64(volBytes, 8);

                var devNameBytes = new byte[volDevNumChar * 2];
                Buffer.BlockCopy(rawBytes, VolumesInfoOffset + volDevOffset, devNameBytes, 0, volDevNumChar * 2);
                var devName = Encoding.Unicode.GetString(devNameBytes);

                var sn = BitConverter.ToInt32(volBytes, 16).ToString("X");

                VolumeInformation.Add(new VolumeInfo(volDevOffset, DateTimeOffset.FromFileTime(ct).ToUniversalTime(), sn, devName));

                var fileRefOffset = BitConverter.ToInt32(volBytes, 20);
                var fileRefSize = BitConverter.ToInt32(volBytes, 24);

                var dirStringsOffset = BitConverter.ToInt32(volBytes, 28);
                var numDirectoryStrings = BitConverter.ToInt32(volBytes, 32);

                //filerefs are at VolumesInfoOffset + fileRefOffset
                var fileRefsIndex = VolumesInfoOffset + fileRefOffset;
                var fileRefBytes = new byte[fileRefSize];
                Buffer.BlockCopy(rawBytes, fileRefsIndex, fileRefBytes, 0, fileRefSize);

                var fileRefVer = BitConverter.ToInt32(fileRefBytes, 0);
                var numFileRefs = BitConverter.ToInt32(fileRefBytes, 4);

                tempIndex = 8;

                var tempFileRefBytes = new byte[8];
                while (tempIndex < fileRefBytes.Length && VolumeInformation.Last().FileReferences.Count < numFileRefs)
                {
                    Buffer.BlockCopy(fileRefBytes, tempIndex, tempFileRefBytes, 0, 8);
                    VolumeInformation.Last()
                        .FileReferences.Add(new MFTInformation(tempFileRefBytes));
                    tempIndex += 8;
                }

                var dirStringsIndex = VolumesInfoOffset + dirStringsOffset;
                var dirStringsBytes = new byte[rawBytes.Length - dirStringsIndex];
                Buffer.BlockCopy(rawBytes, dirStringsIndex, dirStringsBytes, 0, rawBytes.Length - dirStringsIndex);

                tempIndex = 0;
                for (var k = 0; k < numDirectoryStrings; k++)
                {
                    var dirCharCount = BitConverter.ToInt16(dirStringsBytes, tempIndex)*2 + 2;
                    // double the count since its Unicode and add 2 extra for null char
                    tempIndex += 2;
                    var dirName = Encoding.Unicode.GetString(dirStringsBytes, tempIndex, dirCharCount).Trim('\0');
                    VolumeInformation.Last().DirectoryNames.Add(dirName);

                    tempIndex += dirCharCount;
                }
            }
        }
Example #5
0
        public Version23(byte[] rawBytes, string sourceFilename)
        {
            SourceFilename = sourceFilename;

            RawBytes = rawBytes;

            try
            {
                var headerBytes = new byte[84];
                Buffer.BlockCopy(rawBytes, 0, headerBytes, 0, 84);

                Header = new Header(headerBytes);

                try
                {
                    var fi = new FileInfo(sourceFilename);
                    SourceCreatedOn  = new DateTimeOffset(fi.CreationTimeUtc);
                    SourceModifiedOn = new DateTimeOffset(fi.LastWriteTimeUtc);
                    SourceAccessedOn = new DateTimeOffset(fi.LastAccessTimeUtc);
                }
                catch (Exception e)
                {
                }

                var fileInfoBytes = new byte[156];
                Buffer.BlockCopy(rawBytes, 84, fileInfoBytes, 0, 156);

                FileMetricsOffset = BitConverter.ToInt32(fileInfoBytes, 0);
                FileMetricsCount  = BitConverter.ToInt32(fileInfoBytes, 4);

                TraceChainsOffset = BitConverter.ToInt32(fileInfoBytes, 8);
                TraceChainsCount  = BitConverter.ToInt32(fileInfoBytes, 12);

                FilenameStringsOffset = BitConverter.ToInt32(fileInfoBytes, 16);
                FilenameStringsSize   = BitConverter.ToInt32(fileInfoBytes, 20);

                VolumesInfoOffset = BitConverter.ToInt32(fileInfoBytes, 24);
                VolumeCount       = BitConverter.ToInt32(fileInfoBytes, 28);

                VolumesInfoSize = BitConverter.ToInt32(fileInfoBytes, 32);

                //at offset 36 there are 8 unknown bytes
                TotalDirectoryCount = BitConverter.ToInt32(fileInfoBytes, 36);

                var rawTime = BitConverter.ToInt64(fileInfoBytes, 44);

                LastRunTimes = new List <DateTimeOffset>();

                LastRunTimes.Add(DateTimeOffset.FromFileTime(rawTime).ToUniversalTime());

                //at offset 52 there are 16 unknown bytes

                RunCount = BitConverter.ToInt32(fileInfoBytes, 68);

                //at offset 72, there are 4 unknown bytes
                //at offset 76, there are 80 unknown bytes

                var fileMetricsBytes = new byte[FileMetricsCount * 32];
                Buffer.BlockCopy(rawBytes, FileMetricsOffset, fileMetricsBytes, 0, FileMetricsCount * 32);
                var tempIndex = 0;

                FileMetrics = new List <FileMetric>();

                var fileMetricsTempBuffer = new byte[32];
                while (tempIndex < fileMetricsBytes.Length)
                {
                    Buffer.BlockCopy(fileMetricsBytes, tempIndex, fileMetricsTempBuffer, 0, 32);
                    FileMetrics.Add(new FileMetric(fileMetricsTempBuffer, false));
                    tempIndex += 32;
                }

                TraceChains = new List <TraceChain>();

                var traceChainBytes = new byte[12 * TraceChainsCount];
                Buffer.BlockCopy(rawBytes, TraceChainsOffset, traceChainBytes, 0, 12 * TraceChainsCount);
                var traceIndex           = 0;
                var traceChainTempBuffer = new byte[12];
                while (traceIndex < traceChainBytes.Length)
                {
                    Buffer.BlockCopy(traceChainBytes, traceIndex, traceChainTempBuffer, 0, 12);
                    TraceChains.Add(new TraceChain(traceChainTempBuffer, false));
                    traceIndex += 12;
                }

                var filenameStringsBytes = new byte[FilenameStringsSize];
                Buffer.BlockCopy(rawBytes, FilenameStringsOffset, filenameStringsBytes, 0, FilenameStringsSize);

                var filenamesRaw = Encoding.Unicode.GetString(filenameStringsBytes);
                var fileNames    = filenamesRaw.Split(new[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);

                Filenames = new List <string>();

                Filenames.AddRange(fileNames);

                var volumeInfoBytes = new byte[VolumesInfoSize];
                Buffer.BlockCopy(rawBytes, VolumesInfoOffset, volumeInfoBytes, 0, VolumesInfoSize);

                VolumeInformation = new List <VolumeInfo>();

                var volBytes = new byte[104];
                for (var j = 0; j < VolumeCount; j++)
                {
                    var skipSize = j * 104;
                    Buffer.BlockCopy(volumeInfoBytes, skipSize, volBytes, 0, 104);

                    var volDevOffset  = BitConverter.ToInt32(volBytes, 0);
                    var volDevNumChar = BitConverter.ToInt32(volBytes, 4);

                    var ct = BitConverter.ToInt64(volBytes, 8);

                    var devNameBytes = new byte[volDevNumChar * 2];
                    Buffer.BlockCopy(rawBytes, VolumesInfoOffset + volDevOffset, devNameBytes, 0, volDevNumChar * 2);
                    var devName = Encoding.Unicode.GetString(devNameBytes);

                    var sn = BitConverter.ToInt32(volBytes, 16).ToString("X");

                    VolumeInformation.Add(new VolumeInfo(volDevOffset, DateTimeOffset.FromFileTime(ct).ToUniversalTime(), sn, devName));

                    var fileRefOffset = BitConverter.ToInt32(volBytes, 20);
                    var fileRefSize   = BitConverter.ToInt32(volBytes, 24);

                    var dirStringsOffset    = BitConverter.ToInt32(volBytes, 28);
                    var numDirectoryStrings = BitConverter.ToInt32(volBytes, 32);

                    //filerefs are at VolumesInfoOffset + fileRefOffset
                    var fileRefsIndex = VolumesInfoOffset + fileRefOffset;
                    var fileRefBytes  = new byte[fileRefSize];
                    Buffer.BlockCopy(rawBytes, fileRefsIndex, fileRefBytes, 0, fileRefSize);

                    var fileRefVer  = BitConverter.ToInt32(fileRefBytes, 0);
                    var numFileRefs = BitConverter.ToInt32(fileRefBytes, 4);

                    tempIndex = 8;

                    var tempFileRefBytes = new byte[8];
                    while (tempIndex < fileRefBytes.Length && VolumeInformation.Last().FileReferences.Count < numFileRefs)
                    {
                        Buffer.BlockCopy(fileRefBytes, tempIndex, tempFileRefBytes, 0, 8);
                        VolumeInformation.Last()
                        .FileReferences.Add(new MFTInformation(tempFileRefBytes));
                        tempIndex += 8;
                    }

                    var dirStringsIndex = VolumesInfoOffset + dirStringsOffset;
                    var dirStringsBytes = new byte[rawBytes.Length - dirStringsIndex];
                    Buffer.BlockCopy(rawBytes, dirStringsIndex, dirStringsBytes, 0, rawBytes.Length - dirStringsIndex);

                    tempIndex = 0;
                    for (var k = 0; k < numDirectoryStrings; k++)
                    {
                        var dirCharCount = BitConverter.ToInt16(dirStringsBytes, tempIndex) * 2 + 2;
                        // double the count since its Unicode and add 2 extra for null char
                        tempIndex += 2;
                        var dirName = Encoding.Unicode.GetString(dirStringsBytes, tempIndex, dirCharCount).Trim('\0');
                        VolumeInformation.Last().DirectoryNames.Add(dirName);

                        tempIndex += dirCharCount;
                    }
                }
            }
            catch (Exception)
            {
                ParsingError = true;
            }
        }