internal StandardInformationAttribute(INtfsContext context, AttributeRecord record)
     : base(context, record)
 {
     byte[] content = Utilities.ReadAll(Content);
     _si = new StandardInformation();
     _si.ReadFrom(content, 0);
 }
Пример #2
0
        //static void MessageWrite(string str)
        //{
        //    Console.Write(">" + "{0} {1}\n>", str, message1);
        //    Console.ReadLine();
        //}

        static void CreateDirectory(FileRecordSegmentHeader parentFolder, FileRecordSegmentHeader childFolder, string name, NtfsFileSystem fs)
        {
            childFolder.CreateFileRecordHeader(Enums.MFTEntryFlags.FileNameIndexPresent, parentFolder);

            StandardInformation stdInfo = new StandardInformation();

            stdInfo.CreateStandInfoFile(FileAttributes.Normal);
            childFolder.UsedEntrySize += stdInfo.RecordLength;

            IndexRoot indRoot = new IndexRoot();
            //childFolder.UsedEntrySize += indRoot.RecordLength;

            FileName fileName = new FileName();

            fileName.CreateFileNameFile(name);
            fileName.RealSize          = fileName.AllocatedSize = 0;
            childFolder.UsedEntrySize += fileName.RecordLength;

            if (childFolder.UsedEntrySize >= (fs.VolumeSize - fs.BytesOccupied + 8))
            {
                Console.WriteLine("Volume is full!");
                Save(fs.VolName.Name, fs.Save());
                Environment.Exit(0);
            }

            childFolder.attributes.Add(stdInfo);
            childFolder.attributes.Add(fileName);
            childFolder.attributes.Add(indRoot);

            ((IndexRoot)parentFolder.attributes.ElementAt(2)).Children.Add(childFolder);
            ((IndexRoot)parentFolder.attributes.ElementAt(2)).numberOfChildren++;
            childFolder.parent = parentFolder;

            fs.BytesOccupied += childFolder.UsedEntrySize + 8;
            fs.DirectoryRecordCount++;
            parentFolder.UsedFolderSize += childFolder.UsedEntrySize;
        }
Пример #3
0
        private FileRecord(ref FileRecord[] recordArray, byte[] bytes, int offset, int bytesPerFileRecord, string volume, bool fast)
        {
            if (Encoding.ASCII.GetString(bytes, 0x00 + offset, 0x04) == "FILE")
            {
                OffsetOfUS            = BitConverter.ToUInt16(bytes, 0x04 + offset);
                SizeOfUS              = BitConverter.ToUInt16(bytes, 0x06 + offset);
                LogFileSequenceNumber = BitConverter.ToUInt64(bytes, 0x08 + offset);
                SequenceNumber        = BitConverter.ToUInt16(bytes, 0x10 + offset);
                Hardlinks             = BitConverter.ToUInt16(bytes, 0x12 + offset);
                OffsetOfAttribute     = BitConverter.ToUInt16(bytes, 0x14 + offset);
                Flags           = (FILE_RECORD_FLAG)BitConverter.ToUInt16(bytes, 0x16 + offset);
                Deleted         = isDeleted(Flags);
                Directory       = isDirectory(Flags);
                RealSize        = BitConverter.ToInt32(bytes, 0x18 + offset);
                AllocatedSize   = BitConverter.ToInt32(bytes, 0x1C + offset);
                ReferenceToBase = BitConverter.ToUInt64(bytes, 0x20 + offset);
                NextAttrId      = BitConverter.ToUInt16(bytes, 0x28 + offset);
                RecordNumber    = BitConverter.ToUInt32(bytes, 0x2C + offset);
                Attribute       = FileRecordAttribute.GetInstances(bytes, OffsetOfAttribute + offset, bytesPerFileRecord, volume);

                #region AttributeProperties

                foreach (FileRecordAttribute attr in Attribute)
                {
                    if (attr.Name == FileRecordAttribute.ATTR_TYPE.STANDARD_INFORMATION)
                    {
                        StandardInformation stdInfo = attr as StandardInformation;
                        ModifiedTime = stdInfo.ModifiedTime;
                        AccessedTime = stdInfo.AccessedTime;
                        ChangedTime  = stdInfo.ChangedTime;
                        BornTime     = stdInfo.BornTime;
                        Permission   = stdInfo.Permission;
                    }
                    else if (attr.Name == FileRecordAttribute.ATTR_TYPE.ATTRIBUTE_LIST)
                    {
                        if (!(Deleted))
                        {
                            AttributeList attrList          = null;
                            List <FileRecordAttribute> list = new List <FileRecordAttribute>();
                            list.AddRange(Attribute);

                            if (attr.NonResident)
                            {
                                attrList = new AttributeList(attr as NonResident);
                            }
                            else
                            {
                                attrList = attr as AttributeList;
                            }

                            foreach (AttrRef attribute in attrList.AttributeReference)
                            {
                                if (attribute.RecordNumber != RecordNumber)
                                {
                                    FileRecord record = null;

                                    // Test if we have already parse the record
                                    if (recordArray[attribute.RecordNumber] != null)
                                    {
                                        record = recordArray[attribute.RecordNumber];
                                    }
                                    else
                                    {
                                        // If not parse it and add it to the array
                                        record = new FileRecord(ref recordArray, bytes, bytesPerFileRecord * (int)attribute.RecordNumber, bytesPerFileRecord, volume, fast);
                                        recordArray[attribute.RecordNumber] = record;
                                    }

                                    // Add the attributes to the attribute array
                                    list.AddRange(record.Attribute);
                                    list.Remove(attr);
                                }
                            }

                            Attribute = list.ToArray();
                        }
                    }
                    else if (attr.Name == FileRecordAttribute.ATTR_TYPE.FILE_NAME)
                    {
                        FileName fN = attr as FileName;
                        if (!(fN.Namespace == 2))
                        {
                            Name = fN.Filename;
                            ParentSequenceNumber = fN.ParentSequenceNumber;
                            ParentRecordNumber   = fN.ParentRecordNumber;
                            FNModifiedTime       = fN.ModifiedTime;
                            FNAccessedTime       = fN.AccessedTime;
                            FNChangedTime        = fN.ChangedTime;
                            FNBornTime           = fN.BornTime;
                        }
                    }
                }

                #endregion AttributeProperties

                #region FullName

                if (fast)
                {
                    FullName = Name;
                }
                else
                {
                    StringBuilder sb        = new StringBuilder();
                    string        volLetter = Helper.GetVolumeLetter(volume);

                    if (RecordNumber == 0)
                    {
                        sb.Append(volLetter);
                        sb.Append('\\');
                        sb.Append(Name);
                        FullName = sb.ToString();
                    }
                    else if (RecordNumber == 5)
                    {
                        FullName = volLetter;
                    }
                    else
                    {
                        FileRecord parent = null;

                        if (recordArray[this.ParentRecordNumber] != null)
                        {
                            parent = recordArray[this.ParentRecordNumber];
                        }
                        else
                        {
                            parent = new FileRecord(ref recordArray, bytes, bytesPerFileRecord * (int)this.ParentRecordNumber, bytesPerFileRecord, volume, fast);
                            recordArray[this.ParentRecordNumber] = parent;
                        }

                        if (parent.SequenceNumber == this.ParentSequenceNumber)
                        {
                            sb.Append(parent.FullName);
                        }
                        else
                        {
                            sb.Append(@"$OrphanFiles");
                        }

                        if (Name != null)
                        {
                            sb.Append('\\');
                            FullName = sb.Append(Name).ToString();
                        }
                        else
                        {
                            FullName = sb.ToString();
                        }
                    }
                }

                #endregion FullName
            }
        }
Пример #4
0
        private FileRecord(byte[] recordBytes, string volume, int bytesPerFileRecord, bool fast)
        {
            if (Encoding.ASCII.GetString(recordBytes, 0x00, 0x04) == "FILE")
            {
                VolumePath            = volume;
                OffsetOfUS            = BitConverter.ToUInt16(recordBytes, 0x04);
                SizeOfUS              = BitConverter.ToUInt16(recordBytes, 0x06);
                LogFileSequenceNumber = BitConverter.ToUInt64(recordBytes, 0x08);
                SequenceNumber        = BitConverter.ToUInt16(recordBytes, 0x10);
                Hardlinks             = BitConverter.ToUInt16(recordBytes, 0x12);
                OffsetOfAttribute     = BitConverter.ToUInt16(recordBytes, 0x14);
                Flags           = (FILE_RECORD_FLAG)BitConverter.ToUInt16(recordBytes, 0x16);
                Deleted         = isDeleted(Flags);
                Directory       = isDirectory(Flags);
                RealSize        = BitConverter.ToInt32(recordBytes, 0x18);
                AllocatedSize   = BitConverter.ToInt32(recordBytes, 0x1C);
                ReferenceToBase = BitConverter.ToUInt64(recordBytes, 0x20);
                NextAttrId      = BitConverter.ToUInt16(recordBytes, 40);
                RecordNumber    = BitConverter.ToUInt32(recordBytes, 44);
                Attribute       = FileRecordAttribute.GetInstances(recordBytes, OffsetOfAttribute, bytesPerFileRecord, volume);

                #region AttributeProperties

                foreach (FileRecordAttribute attr in Attribute)
                {
                    if (attr.Name == FileRecordAttribute.ATTR_TYPE.STANDARD_INFORMATION)
                    {
                        StandardInformation stdInfo = attr as StandardInformation;
                        ModifiedTime = stdInfo.ModifiedTime;
                        AccessedTime = stdInfo.AccessedTime;
                        ChangedTime  = stdInfo.ChangedTime;
                        BornTime     = stdInfo.BornTime;
                        Permission   = stdInfo.Permission;
                    }
                    else if (attr.Name == FileRecordAttribute.ATTR_TYPE.ATTRIBUTE_LIST)
                    {
                        if (!(Deleted))
                        {
                            AttributeList attrList          = null;
                            List <FileRecordAttribute> list = new List <FileRecordAttribute>();
                            list.AddRange(Attribute);

                            if (attr.NonResident)
                            {
                                attrList = new AttributeList(attr as NonResident);
                            }
                            else
                            {
                                attrList = attr as AttributeList;
                            }

                            foreach (AttrRef attribute in attrList.AttributeReference)
                            {
                                if (attribute.RecordNumber != RecordNumber)
                                {
                                    FileRecord record = FileRecord.Get(volume, (int)attribute.RecordNumber);
                                    list.AddRange(record.Attribute);
                                    list.Remove(attr);
                                }
                            }

                            Attribute = list.ToArray();
                        }
                    }
                    else if (attr.Name == FileRecordAttribute.ATTR_TYPE.FILE_NAME)
                    {
                        FileName fN = attr as FileName;
                        if (!(fN.Namespace == 2))
                        {
                            Name = fN.Filename;
                            ParentSequenceNumber = fN.ParentSequenceNumber;
                            ParentRecordNumber   = fN.ParentRecordNumber;
                            FNModifiedTime       = fN.ModifiedTime;
                            FNAccessedTime       = fN.AccessedTime;
                            FNChangedTime        = fN.ChangedTime;
                            FNBornTime           = fN.BornTime;
                        }
                    }
                }

                #endregion AttributeProperties

                #region FullName

                if (fast)
                {
                    FullName = Name;
                }
                else
                {
                    StringBuilder sb        = new StringBuilder();
                    string        volLetter = Helper.GetVolumeLetter(volume);

                    if (RecordNumber == 0)
                    {
                        sb.Append(volLetter);
                        sb.Append('\\');
                        sb.Append(Name);
                        FullName = sb.ToString();
                    }
                    else if (RecordNumber == 5)
                    {
                        FullName = volLetter;
                    }
                    else
                    {
                        FileRecord parent = new FileRecord(GetRecordBytes(volume, (int)ParentRecordNumber), volume, bytesPerFileRecord, false);
                        if (parent.SequenceNumber == this.ParentSequenceNumber)
                        {
                            sb.Append(parent.FullName);
                        }
                        else
                        {
                            sb.Append(@"$OrphanFiles");
                        }

                        if (Name != null)
                        {
                            sb.Append('\\');
                            FullName = sb.Append(Name).ToString();
                        }
                        else
                        {
                            FullName = sb.ToString();
                        }
                    }
                }

                #endregion FullName
            }
        }
Пример #5
0
        /// <summary>
        /// Begin the process of interpreting MFT data
        /// </summary>
        private unsafe Node[] ProcessMft()
        {
            //64 KB seems to be optimal for Windows XP, Vista is happier with 256KB...
            uint bufferSize = (Environment.OSVersion.Version.Major >= 6 ? 256u : 64u) * 1024;

            byte[] data = new byte[bufferSize];

            fixed(byte *buffer = data)
            {
                //Read the $MFT record from disk into memory, which is always the first record in the MFT.
                ReadFile(buffer, _diskInfo.BytesPerMftRecord, _diskInfo.MftStartLcn * _diskInfo.BytesPerSector * _diskInfo.SectorsPerCluster);

                //Fixup the raw data from disk. This will also test if it's a valid $MFT record.
                FixupRawMftdata(buffer, _diskInfo.BytesPerMftRecord);

                List <Stream> mftStreams = new List <Stream>();

                if ((_retrieveMode & RetrieveMode.StandardInformations) == RetrieveMode.StandardInformations)
                {
                    _standardInformations = new StandardInformation[1];                     //allocate some space for $MFT record
                }

                Node mftNode;

                if (!ProcessMftRecord(buffer, _diskInfo.BytesPerMftRecord, 0, out mftNode, mftStreams, true))
                {
                    throw new Exception("Can't interpret Mft Record");
                }

                //the bitmap data contains all used inodes on the disk
                _bitmapData = ProcessBitmapData(mftStreams);

                OnBitmapDataAvailable();

                Stream dataStream = SearchStream(mftStreams, AttributeType.AttributeData);

                UInt32 maxInode = (UInt32)_bitmapData.Length * 8;

                if (maxInode > (UInt32)(dataStream.Size / _diskInfo.BytesPerMftRecord))
                {
                    maxInode = (UInt32)(dataStream.Size / _diskInfo.BytesPerMftRecord);
                }

                Node[] nodes = new Node[maxInode];
                nodes[0] = mftNode;

                if ((_retrieveMode & RetrieveMode.StandardInformations) == RetrieveMode.StandardInformations)
                {
                    StandardInformation mftRecordInformation = _standardInformations[0];
                    _standardInformations    = new StandardInformation[maxInode];
                    _standardInformations[0] = mftRecordInformation;
                }

                if ((_retrieveMode & RetrieveMode.Streams) == RetrieveMode.Streams)
                {
                    _streams = new Stream[maxInode][];
                }

                /* Read and process all the records in the MFT. The records are read into a
                *  buffer and then given one by one to the InterpretMftRecord() subroutine. */

                UInt64 BlockStart = 0, BlockEnd = 0;
                UInt64 RealVcn = 0, Vcn = 0;

                Stopwatch stopwatch = new Stopwatch();

                stopwatch.Start();

                ulong totalBytesRead = 0;
                int   fragmentIndex  = 0;
                int   fragmentCount  = dataStream.Fragments.Count;

                for (UInt32 nodeIndex = 1; nodeIndex < maxInode; nodeIndex++)
                {
                    // Ignore the Inode if the bitmap says it's not in use.
                    if ((_bitmapData[nodeIndex >> 3] & BitmapMasks[nodeIndex % 8]) == 0)
                    {
                        continue;
                    }

                    if (nodeIndex >= BlockEnd)
                    {
                        if (!ReadNextChunk(
                                buffer,
                                bufferSize,
                                nodeIndex,
                                fragmentIndex,
                                dataStream,
                                ref BlockStart,
                                ref BlockEnd,
                                ref Vcn,
                                ref RealVcn))
                        {
                            break;
                        }

                        totalBytesRead += (BlockEnd - BlockStart) * _diskInfo.BytesPerMftRecord;
                    }

                    FixupRawMftdata(
                        buffer + (nodeIndex - BlockStart) * _diskInfo.BytesPerMftRecord,
                        _diskInfo.BytesPerMftRecord
                        );

                    List <Stream> streams = null;
                    if ((_retrieveMode & RetrieveMode.Streams) == RetrieveMode.Streams)
                    {
                        streams = new List <Stream>();
                    }

                    Node newNode;
                    if (!ProcessMftRecord(
                            buffer + (nodeIndex - BlockStart) * _diskInfo.BytesPerMftRecord,
                            _diskInfo.BytesPerMftRecord,
                            nodeIndex,
                            out newNode,
                            streams,
                            false))
                    {
                        continue;
                    }

                    nodes[nodeIndex] = newNode;

                    if (streams != null)
                    {
                        _streams[nodeIndex] = streams.ToArray();
                    }
                }

                stopwatch.Stop();

                Trace.WriteLine(
                    string.Format(
                        "{0:F3} MB of volume metadata has been read in {1:F3} s at {2:F3} MB/s",
                        (float)totalBytesRead / (1024 * 1024),
                        (float)stopwatch.Elapsed.TotalSeconds,
                        ((float)totalBytesRead / (1024 * 1024)) / stopwatch.Elapsed.TotalSeconds
                        )
                    );

                return(nodes);
            }
        }
Пример #6
0
        static void Main(string[] args)
        {
            string command, fsName, subDir1, subDir2, currentDir;

            subDir1 = subDir2 = string.Empty;

            while (true)
            {
                Console.Clear();
                Console.Write(">" + "Enter Filesystem name!\n>");
                command = Console.ReadLine();
                //command.Substring(command.IndexOf(">"));
                if (Regex.IsMatch(command, @"^[A-Za-z0-9]+$"))
                {
                    fsName = command;
                    break;
                }
                else
                {
                    Console.Write(">" + "FS name is not valid!" + message1);
                    Console.ReadLine();
                }
            }
            NtfsFileSystem ntfsFS = new NtfsFileSystem(fsName);

            currentDir = fsName;
            var currectFolder = ntfsFS.Root;

            Console.Clear();
            while (true)
            {
                Console.Write("{0}:\\{1}{2}>", fsName, subDir1 == string.Empty ? subDir1 : subDir1 + "\\", subDir2);
                string[] textCatch = Console.ReadLine().Split('"');       // e.q. textCatch[1] is "text for input."
                string[] tokens    = (textCatch[0].ToLower()).Split(' '); //string[] tokens = command.Split(' ');
                command = tokens[0];
                command = command.Trim();
                bool   toContinue = true;
                choice selected   = choice.wrong_command;

                {
                    int i = 0;
                    foreach (var ch in choices)
                    {
                        if (command.Equals(choices[i++].Item1))
                        {
                            selected = (choice)(--i);
                        }

                        if (ch.Item1.Equals(command) && (tokens.Length - 1 >= ch.Item2 && tokens.Length - 1 <= ch.Item3))
                        {
                            toContinue = false;
                            break;
                        }
                    }
                }

                if (toContinue)
                {
                    Console.Write("{0}:\\>{1} {2}\n", fsName, "Command has wrong number of arguments!", message1);
                    //Console.ReadLine();
                    continue;
                }

                //for (int i = 0; i < (int)choice.cd_remove; ++i)
                //    if (command.Equals(choices[i].Item1))
                //    {
                //        selected = (choice)i;
                //        break;
                //    }

                if (selected != choice.wrong_command)
                {
                    switch (selected)
                    {
                    case choice.mkdir:
                    {
                        if (!(subDir1 != String.Empty && subDir2 != String.Empty))
                        {
                            FileRecordSegmentHeader mkFolder = new FileRecordSegmentHeader();
                            CreateDirectory(currectFolder, mkFolder, tokens[1], ntfsFS);
                        }
                        else
                        {
                            Console.WriteLine("Allowed directory depth is 2. Can't make {0} directory!", tokens[1]);
                        }

                        break;
                    }

                    case choice.create:
                    {
                        FileRecordSegmentHeader createFile = new FileRecordSegmentHeader();
                        CreateFile(currectFolder, createFile, tokens[1], ntfsFS);

                        break;
                    }

                    case choice.put:
                    {
                        //if (Directory.Exists(tokens[1]))
                        using (var stream = new FileStream(tokens[1], FileMode.Open))
                        {
                            if (stream.Length <= 64_000)
                            {
                                try
                                {
                                    FileRecordSegmentHeader header = new FileRecordSegmentHeader();
                                    FileRecordSegmentHeader parent = currectFolder;

                                    header.CreateFileRecordHeader(Enums.MFTEntryFlags.FileRecordSegmentInUse, parent);

                                    StandardInformation stdInfo = new StandardInformation();
                                    stdInfo.CreateStandInfoFile(FileAttributes.Normal);
                                    header.UsedEntrySize += stdInfo.RecordLength;

                                    FileName fileName = new FileName();
                                    fileName.CreateFileNameFile(Path.GetFileName(tokens[1]));
                                    header.UsedEntrySize += fileName.RecordLength;

                                    if (stream.Length <= (header.TotalEntrySize - header.UsedEntrySize))
                                    {
                                        fileName.AllocatedSize = header.TotalEntrySize - header.UsedEntrySize;
                                        fileName.RealSize      = (ulong)stream.Length;
                                        header.UsedEntrySize  += (uint)fileName.RealSize;

                                        Data data = new Data();
                                        var  mem  = new MemoryStream();
                                        stream.CopyTo(mem);
                                        data.DataBytes = mem.ToArray();

                                        header.attributes.Add(stdInfo);
                                        header.attributes.Add(fileName);
                                        header.attributes.Add(data);

                                        if (header.TotalEntrySize < (ntfsFS.VolumeSize - ntfsFS.BytesOccupied) + 8)         // +8 for reference in folder
                                        {
                                            ntfsFS.mftHeaderRecord.Add(header);

                                            ((FileSystem.Attributes.Indexroot.IndexRoot)parent.attributes.ElementAt(2)).Children.Add(header);
                                            ((FileSystem.Attributes.Indexroot.IndexRoot)parent.attributes.ElementAt(2)).numberOfChildren++;
                                            header.parent = parent;

                                            ntfsFS.FileRecordCount++;
                                            ntfsFS.BytesOccupied  += 8;         // one child added
                                            ntfsFS.BytesOccupied  += header.TotalEntrySize;
                                            parent.UsedFolderSize += header.TotalEntrySize;
                                        }
                                        else
                                        {
                                            Save(fsName, ntfsFS.Save());
                                            throw new Exception("Volume is full!");
                                        }
                                    }
                                    else
                                    {
                                        Console.WriteLine("File is too large!");
                                    }
                                }
                                catch (Exception e)
                                {
                                    Console.WriteLine(e);
                                    Environment.Exit(0);
                                }
                            }
                            else
                            {
                                Console.WriteLine("File is larger than 64 KB!");
                            }
                        }
                        //else
                        //    Console.WriteLine("Directory '{0}' doesn't exist!", tokens[1]);

                        break;
                    }

                    case choice.get:
                    {
                        //FileInfo fileInfo = new FileInfo(tokens[1]);
                        //using (FileStream fs = fileInfo.Create())
                        //{
                        byte[] data = ntfsFS.searchDataInDirectory(currectFolder, tokens[2]);
                        if (data != null)
                        {
                            File.WriteAllBytes(tokens[1], data);
                        }
                        else
                        {
                            Console.WriteLine("File is not located in the current folder!");
                        }

                        break;
                    }

                    case choice.ls:
                    {
                        Console.WriteLine();
                        foreach (var child in ((FileSystem.Attributes.Indexroot.IndexRoot)currectFolder.attributes.ElementAt(2)).Children)
                        {
                            if (child.Flags == Enums.MFTEntryFlags.FileRecordSegmentInUse)
                            {
                                Console.WriteLine(((StandardInformation)child.attributes.ElementAt(0)).CreationTime.ToString() + "    " + "    " +
                                                  child.UsedEntrySize.ToString("N1") + " " + ((FileName)child.attributes.ElementAt(1)).Filename);
                            }
                            else
                            {
                                Console.WriteLine(((StandardInformation)child.attributes.ElementAt(0)).CreationTime.ToString() + "    " + "<DIR>" +
                                                  "     " + ((FileName)child.attributes.ElementAt(1)).Filename);
                            }
                        }
                        Console.WriteLine();
                        break;
                    }

                    case choice.cp:
                    {
                        try
                        {
                            // get the file
                            FileRecordSegmentHeader fileToCpy = null;
                            FileRecordSegmentHeader header    = new FileRecordSegmentHeader();
                            FileRecordSegmentHeader parent    = null;

                            foreach (var child in ((FileSystem.Attributes.Indexroot.IndexRoot)currectFolder.attributes.ElementAt(2)).Children)
                            {
                                if (((FileName)child.attributes.ElementAt(1)).Filename.Equals(tokens[1]))
                                {
                                    fileToCpy = child;
                                    break;
                                }
                            }

                            if (fileToCpy != null)
                            {
                                string[] splitDestination = tokens[2].Split('\\');
                                if (splitDestination.Length > 2)
                                {
                                    Console.WriteLine("Moving failed!");
                                }
                                else
                                {
                                    FileRecordSegmentHeader moveFolder = null;
                                    FileRecordSegmentHeader tmp        = null;
                                    foreach (var child in ((FileSystem.Attributes.Indexroot.IndexRoot)currectFolder.parent.attributes.ElementAt(2)).Children)
                                    {
                                        if (((FileName)child.attributes.ElementAt(1)).Filename.Equals(splitDestination[0]))
                                        {
                                            tmp = moveFolder = child;
                                            break;
                                        }
                                    }

                                    if (moveFolder != null)
                                    {
                                        if (splitDestination.Length == 2)
                                        {
                                            foreach (var child in ((FileSystem.Attributes.Indexroot.IndexRoot)tmp.attributes.ElementAt(2)).Children)
                                            {
                                                if (((FileName)child.attributes.ElementAt(1)).Filename.Equals(splitDestination[1]))
                                                {
                                                    moveFolder = child;
                                                    break;
                                                }
                                            }

                                            if ((tmp != moveFolder && splitDestination.Length == 2) || (tmp == moveFolder && splitDestination.Length == 1))
                                            {
                                                //((FileSystem.Attributes.Indexroot.IndexRoot)currectFolder.attributes.ElementAt(2)).Children.Remove(moveFolder);
                                                //((FileSystem.Attributes.Indexroot.IndexRoot)moveFolder.attributes.ElementAt(2)).Children.Add(moveFolder);
                                                //moveFolder.parent = moveFolder;

                                                parent = moveFolder;
                                                header.CreateFileRecordHeader(Enums.MFTEntryFlags.FileRecordSegmentInUse, parent);

                                                StandardInformation stdInfo = new StandardInformation();
                                                stdInfo.CreateStandInfoFile(FileAttributes.Normal);
                                                header.UsedEntrySize += stdInfo.RecordLength;

                                                FileName fileName = new FileName();
                                                fileName.CreateFileNameFile(((FileName)fileToCpy.attributes.ElementAt(1)).Filename);
                                                header.UsedEntrySize += fileName.RecordLength;

                                                fileName.AllocatedSize = header.TotalEntrySize - header.UsedEntrySize;
                                                fileName.RealSize      = (ulong)((FileName)fileToCpy.attributes.ElementAt(1)).RealSize;
                                                header.UsedEntrySize  += (uint)fileName.RealSize;

                                                Data data = new Data();
                                                Array.Copy(((Data)fileToCpy.attributes.ElementAt(2)).DataBytes, 0, data.DataBytes, 0, ((Data)fileToCpy.attributes.ElementAt(2)).DataBytes.Length);


                                                header.attributes.Add(stdInfo);
                                                header.attributes.Add(fileName);
                                                header.attributes.Add(data);

                                                if (header.TotalEntrySize < (ntfsFS.VolumeSize - ntfsFS.BytesOccupied) + 8)         // +8 for reference in folder
                                                {
                                                    ntfsFS.mftHeaderRecord.Add(header);

                                                    ((FileSystem.Attributes.Indexroot.IndexRoot)parent.attributes.ElementAt(2)).Children.Add(header);
                                                    ((FileSystem.Attributes.Indexroot.IndexRoot)parent.attributes.ElementAt(2)).numberOfChildren++;
                                                    header.parent = parent;

                                                    ntfsFS.FileRecordCount++;
                                                    ntfsFS.BytesOccupied  += 8;         // one child added
                                                    ntfsFS.BytesOccupied  += header.TotalEntrySize;
                                                    parent.UsedFolderSize += header.TotalEntrySize;
                                                }
                                                else
                                                {
                                                    Save(fsName, ntfsFS.Save());
                                                    throw new Exception("Volume is full!");
                                                }
                                            }

                                            else if (tmp == moveFolder && splitDestination.Length == 2)
                                            {
                                                Console.WriteLine("Copying failed!");
                                            }
                                        }
                                    }
                                    else
                                    {
                                        Console.WriteLine("Copying failed!");
                                    }
                                }
                            }
                            else
                            {
                                Console.WriteLine("Copying failed!");
                            }
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine(e);
                            Environment.Exit(0);
                        }

                        break;
                    }

                    case choice.mv:
                    {
                        string[] splitDestination = tokens[2].Split('\\');
                        if (splitDestination.Length > 2)
                        {
                            Console.WriteLine("Moving failed!");
                        }
                        else
                        {
                            FileRecordSegmentHeader movingFile = null;
                            foreach (var child in ((FileSystem.Attributes.Indexroot.IndexRoot)currectFolder.attributes.ElementAt(2)).Children)
                            {
                                if (((FileName)child.attributes.ElementAt(1)).Filename.Equals(tokens[1]))
                                {
                                    movingFile = child;
                                    break;
                                }
                            }

                            if (movingFile != null)
                            {
                                FileRecordSegmentHeader moveFolder = null;
                                FileRecordSegmentHeader tmp        = null;
                                foreach (var child in ((FileSystem.Attributes.Indexroot.IndexRoot)currectFolder.parent.attributes.ElementAt(2)).Children)
                                {
                                    if (((FileName)child.attributes.ElementAt(1)).Filename.Equals(splitDestination[0]))
                                    {
                                        tmp = moveFolder = child;
                                        break;
                                    }
                                }

                                if (moveFolder != null)
                                {
                                    if (splitDestination.Length == 2)
                                    {
                                        foreach (var child in ((FileSystem.Attributes.Indexroot.IndexRoot)tmp.attributes.ElementAt(2)).Children)
                                        {
                                            if (((FileName)child.attributes.ElementAt(1)).Filename.Equals(splitDestination[1]))
                                            {
                                                moveFolder = child;
                                                break;
                                            }
                                        }
                                    }
                                    if ((tmp != moveFolder && splitDestination.Length == 2) || (tmp == moveFolder && splitDestination.Length == 1))
                                    {
                                        ((FileSystem.Attributes.Indexroot.IndexRoot)currectFolder.attributes.ElementAt(2)).Children.Remove(movingFile);
                                        ((FileSystem.Attributes.Indexroot.IndexRoot)moveFolder.attributes.ElementAt(2)).Children.Add(movingFile);
                                        moveFolder.parent = moveFolder;
                                    }
                                    else if (tmp == moveFolder && splitDestination.Length == 2)
                                    {
                                        Console.WriteLine("Moving failed!");
                                    }
                                }
                                else
                                {
                                    Console.WriteLine("Moving failed!");
                                }
                            }
                            else
                            {
                                Console.WriteLine("Moving failed!");
                            }
                        }

                        break;
                    }

                    case choice.rename:
                    {
                        ntfsFS.changeName(currectFolder, tokens[1], tokens[2]);
                        break;
                    }

                    case choice.echo:
                    {
                        try
                        {
                            if (textCatch[1].Length < 64_000)
                            {
                                FileRecordSegmentHeader header = new FileRecordSegmentHeader();
                                FileRecordSegmentHeader parent = currectFolder;

                                header.CreateFileRecordHeader(Enums.MFTEntryFlags.FileRecordSegmentInUse, parent);

                                StandardInformation stdInfo = new StandardInformation();
                                stdInfo.CreateStandInfoFile(FileAttributes.Normal);
                                header.UsedEntrySize += stdInfo.RecordLength;

                                FileName fileName = new FileName();
                                fileName.CreateFileNameFile(tokens[1]);
                                header.UsedEntrySize += fileName.RecordLength;

                                if (textCatch.Length <= (header.TotalEntrySize - header.UsedEntrySize))
                                {
                                    fileName.AllocatedSize = header.TotalEntrySize - header.UsedEntrySize;
                                    fileName.RealSize      = (ulong)textCatch.Length;
                                    header.UsedEntrySize  += (uint)fileName.RealSize;

                                    Data data = new Data();
                                    //Array.Copy(textCatch, 0, data.DataBytes, 0, textCatch.Length);
                                    data.DataBytes = Encoding.ASCII.GetBytes(textCatch[1]);

                                    header.attributes.Add(stdInfo);
                                    header.attributes.Add(fileName);
                                    header.attributes.Add(data);

                                    if (header.TotalEntrySize < (ntfsFS.VolumeSize - ntfsFS.BytesOccupied) + 8)         // +8 for reference in folder
                                    {
                                        ntfsFS.mftHeaderRecord.Add(header);

                                        ((FileSystem.Attributes.Indexroot.IndexRoot)parent.attributes.ElementAt(2)).Children.Add(header);
                                        ((FileSystem.Attributes.Indexroot.IndexRoot)parent.attributes.ElementAt(2)).numberOfChildren++;
                                        header.parent = parent;

                                        ntfsFS.FileRecordCount++;
                                        ntfsFS.BytesOccupied  += 8;         // one child added
                                        ntfsFS.BytesOccupied  += header.TotalEntrySize;
                                        parent.UsedFolderSize += header.TotalEntrySize;
                                    }
                                    else
                                    {
                                        Save(fsName, ntfsFS.Save());
                                        throw new Exception("Volume is full!");
                                    }
                                }
                                else
                                {
                                    Console.WriteLine("File is too large!");
                                }
                            }
                            else
                            {
                                Console.WriteLine("Text file is larger than 64 KB!");
                            }
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine(e);
                            Environment.Exit(0);
                        }

                        break;
                    }

                    case choice.cat:
                    {
                        if (tokens[1].Contains(".txt"))
                        {
                            Console.WriteLine(System.Text.Encoding.ASCII.GetString(ntfsFS.searchDataInDirectory(currectFolder, tokens[1])));
                        }
                        else
                        {
                            Console.WriteLine("File is not *.txt!");
                        }
                        break;
                    }

                    case choice.rm:
                    {
                        FileRecordSegmentHeader deleteThisChild = null;
                        foreach (var child in ((IndexRoot)currectFolder.attributes.ElementAt(2)).Children)
                        {
                            if (((FileName)child.attributes.ElementAt(1)).Filename.Equals(tokens[1]))
                            {
                                deleteThisChild = child;
                                break;
                            }
                        }


                        if (deleteThisChild != null)
                        {
                            ntfsFS.BytesOccupied        -= 8;
                            ntfsFS.BytesOccupied        -= deleteThisChild.TotalEntrySize;
                            currectFolder.UsedFolderSize = deleteThisChild.TotalEntrySize;

                            if (deleteThisChild.Flags == Enums.MFTEntryFlags.FileRecordSegmentInUse)
                            {
                                ntfsFS.FileRecordCount--;
                            }
                            else
                            {
                                ntfsFS.DirectoryRecordCount--;
                            }

                            ((IndexRoot)currectFolder.attributes.ElementAt(2)).Children.Remove(deleteThisChild);
                            deleteThisChild.parent = null;
                        }
                        else
                        {
                            Console.WriteLine("File/Folder not found!");
                        }

                        break;
                    }

                    case choice.stat:
                    {
                        ntfsFS.printData(currectFolder, tokens[1]);
                        break;
                    }

                    case choice.cd:
                    {
                        if (!currentDir.Equals(tokens[1]))
                        {
                            var currectFolderNew = ntfsFS.FindFolder(currectFolder, tokens[1]);
                            if (currectFolderNew != null)
                            {
                                currectFolder = currectFolderNew;
                                if (currentDir.Equals(fsName))
                                {
                                    currentDir = subDir1 = tokens[1];
                                }
                                else if (currentDir.Equals(subDir1))
                                {
                                    currentDir = subDir2 = tokens[1];
                                }
                            }
                            else
                            {
                                Console.WriteLine("Directory '{0}' doesn't exist in '{1}'!", tokens[1], currentDir);
                            }
                        }
                        else
                        {
                            Console.WriteLine("This is not possible!");
                        }

                        break;
                    }

                    case choice.cd_remove:
                    {
                        if (currentDir == fsName)
                        {
                            // Save NtfsFileSystem to *.dat file
                            Save(fsName, ntfsFS.Save());
                            currentDir = string.Empty;
                            Environment.Exit(0);
                        }
                        else if (subDir2 != string.Empty)
                        {
                            var parentFolder = currectFolder.parent;
                            currectFolder = parentFolder;

                            subDir2    = string.Empty;
                            currentDir = subDir1;
                        }
                        else
                        {
                            currectFolder = ntfsFS.Root;
                            subDir1       = string.Empty;
                            currentDir    = fsName;
                        }

                        break;
                    }

                    case choice.cls:
                    {
                        Console.Clear();
                        break;
                    }

                    case choice.exit:
                    {
                        Save(fsName, ntfsFS.Save());
                        Environment.Exit(0);
                        break;
                    }
                    }
                }
                else
                {
                    Console.Write("{0}:\\>{1} {2}\n", fsName, "Unknown command.", message1);
                    continue;
                }
            }
        }
Пример #7
0
        /// <summary>
        /// Process each attributes and gather information when necessary
        /// </summary>
        private unsafe void ProcessAttributes(ref Node node, UInt32 nodeIndex, byte *ptr, UInt64 BufLength, UInt16 instance, int depth, List <Stream> streams, bool isMftNode)
        {
            int currentNameType = -1;

            Attribute *attribute = null;

            for (uint AttributeOffset = 0; AttributeOffset < BufLength; AttributeOffset = AttributeOffset + attribute->Length)
            {
                attribute = (Attribute *)(ptr + AttributeOffset);

                // exit the loop if end-marker.
                if ((AttributeOffset + 4 <= BufLength) && (*(UInt32 *)attribute == 0xFFFFFFFF))
                {
                    break;
                }

                //make sure we did read the data correctly
                if ((AttributeOffset + 4 > BufLength) || attribute->Length < 3 || (AttributeOffset + attribute->Length > BufLength))
                {
                    throw new Exception("Error: attribute in Inode %I64u is bigger than the data, the MFT may be corrupt.");
                }

                //attributes list needs to be processed at the end
                if (attribute->AttributeType == AttributeType.AttributeAttributeList)
                {
                    continue;
                }

                /* If the Instance does not equal the AttributeNumber then ignore the attribute.
                 * This is used when an AttributeList is being processed and we only want a specific
                 * instance. */
                if ((instance != 65535) && (instance != attribute->AttributeNumber))
                {
                    continue;
                }

                if (attribute->Nonresident == 0)
                {
                    ResidentAttribute *residentAttribute = (ResidentAttribute *)attribute;

                    switch (attribute->AttributeType)
                    {
                    case AttributeType.AttributeFileName:
                        AttributeFileName *attributeFileName = (AttributeFileName *)(ptr + AttributeOffset + residentAttribute->ValueOffset);

                        if (attributeFileName->ParentDirectory.InodeNumberHighPart > 0)
                        {
                            throw new NotSupportedException("48 bits inode are not supported to reduce memory footprint.");
                        }

                        if (node.Size == 0)                                  //missing file size
                        {
                            node.Size = attributeFileName->DataSize;         //set file size if not already set
                        }

                        if (node.NameIndex == 0)
                        {
                            currentNameType      = (int)attributeFileName->NameType;
                            node.NameIndex       = GetNameIndex(new string(&attributeFileName->Name, 0, attributeFileName->NameLength));
                            node.ParentNodeIndex = attributeFileName->ParentDirectory.InodeNumberLowPart;
                        }
                        else
                        {
                            int attributeNameType = (int)attributeFileName->NameType;
                            if (attributeNameType == 0 || currentNameType == 2)
                            {
                                currentNameType      = attributeNameType;
                                node.NameIndex       = GetNameIndex(new string(&attributeFileName->Name, 0, attributeFileName->NameLength));
                                node.ParentNodeIndex = attributeFileName->ParentDirectory.InodeNumberLowPart;
                            }
                        }

                        break;

                    case AttributeType.AttributeStandardInformation:
                        AttributeStandardInformation *attributeStandardInformation = (AttributeStandardInformation *)(ptr + AttributeOffset + residentAttribute->ValueOffset);

                        node.Attributes |= (Attributes)attributeStandardInformation->FileAttributes;

                        if ((_retrieveMode & RetrieveMode.StandardInformations) == RetrieveMode.StandardInformations)
                        {
                            _standardInformations[nodeIndex] =
                                new StandardInformation(
                                    attributeStandardInformation->CreationTime,
                                    attributeStandardInformation->FileChangeTime,
                                    attributeStandardInformation->LastAccessTime,
                                    attributeStandardInformation->MftChangeTime
                                    );
                        }

                        break;

                    case AttributeType.AttributeData:
                        node.Size = residentAttribute->ValueLength;
                        break;
                    }
                }
                else
                {
                    NonResidentAttribute *nonResidentAttribute = (NonResidentAttribute *)attribute;

                    //save the length (number of bytes) of the data.
                    if (attribute->AttributeType == AttributeType.AttributeData && node.Size == 0)
                    {
                        node.Size = nonResidentAttribute->DataSize;
                    }

                    if (streams != null)
                    {
                        //extract the stream name
                        int streamNameIndex = 0;
                        if (attribute->NameLength > 0)
                        {
                            streamNameIndex = GetNameIndex(new string((char *)(ptr + AttributeOffset + attribute->NameOffset), 0, (int)attribute->NameLength));
                        }

                        //find or create the stream
                        Stream stream = SearchStream(streams, attribute->AttributeType, streamNameIndex);

                        if (stream == null)
                        {
                            stream = new Stream(streamNameIndex, attribute->AttributeType, nonResidentAttribute->DataSize);
                            streams.Add(stream);
                        }
                        else if (stream.Size == 0)
                        {
                            stream.Size = nonResidentAttribute->DataSize;
                        }

                        //we need the fragment of the MFTNode so retrieve them this time
                        //even if fragments aren't normally read
                        if (isMftNode || (_retrieveMode & RetrieveMode.Fragments) == RetrieveMode.Fragments)
                        {
                            ProcessFragments(
                                ref node,
                                stream,
                                ptr + AttributeOffset + nonResidentAttribute->RunArrayOffset,
                                attribute->Length - nonResidentAttribute->RunArrayOffset,
                                nonResidentAttribute->StartingVcn
                                );
                        }
                    }
                }
            }

            if (streams != null && streams.Count > 0)
            {
                node.Size = streams[0].Size;
            }
        }
Пример #8
0
        private ProviderDocument CreateStandardProviderDocument(CoreProvider provider, StandardInformation standardInformation, List <DeliveryInformation> deliveryInformation)
        {
            try
            {
                var standardProvider = new ProviderDocument(ElasticsearchDocumentTypes.PROVIDER_STANDARD_DOCUMENT)
                {
                    StandardCode      = standardInformation.Code,
                    RegulatedStandard = standardInformation.RegulatedStandard
                };

                PopulateDocumentSharedProperties(standardProvider, provider, standardInformation, deliveryInformation);

                return(standardProvider);
            }
            catch (Exception ex) when(ex is ArgumentNullException || ex is NullReferenceException)
            {
                throw new MappingException("Unable to map to Standard Provider Document", ex);
            }
        }
Пример #9
0
 public ProviderDocument CreateStandardProviderDocument(CoreProvider provider, StandardInformation standardInformation, IEnumerable <DeliveryInformation> deliveryInformation)
 {
     return(CreateStandardProviderDocument(provider, standardInformation, deliveryInformation.ToList()));
 }
Пример #10
0
 public ProviderDocument CreateStandardProviderDocument(CoreProvider provider, StandardInformation standardInformation, DeliveryInformation deliveryInformation)
 {
     return(CreateStandardProviderDocument(provider, standardInformation, new List <DeliveryInformation> {
         deliveryInformation
     }));
 }
Пример #11
0
 /// <summary>
 /// Initializes a new instance of the <see cref="EncryptedFile"/> class.
 /// This constructor is used when encrypted file is created.
 /// </summary>
 /// <param name="fileName">Full name of the original file.</param>
 /// <param name="userId">Id of the file owner.</param>
 /// <param name="algorithmNameSignature">Full name of the algorithm used for file encryption.</param>
 /// <param name="hashAlgorithmName">Name of the hashing algorithm used to create a file signature.</param>
 /// <param name="ownerPublicKey">Public RSA key of the file owner.</param>
 /// <param name="ownerPrivateKey">Private RSA key of the file owner.</param>
 public EncryptedFile(string fileName, uint userId, string algorithmNameSignature, string hashAlgorithmName, RSAParameters ownerPublicKey, RSAParameters ownerPrivateKey)
 {
     Headers[0] = new StandardInformation(userId);
     Headers[1] = new SecurityDescriptor((int)userId, algorithmNameSignature, hashAlgorithmName, ownerPublicKey);
     NameEncryption(fileName, new AesAlgorithm(((SecurityDescriptor)Headers[1]).GetKey((int)userId, ownerPrivateKey), ((SecurityDescriptor)Headers[1]).IV, "OFB"));
 }