【问题标题】:Why do files, which are not deleted, point to invalid NTFS MFT records?为什么未删除的文件指向无效的 NTFS MFT 记录?
【发布时间】:2020-08-07 06:20:00
【问题描述】:

我最近一直在弄乱 NTFS,以便执行快速搜索(通过解析 MFT),它应该显示具有特定扩展名的文件(即使它们已被删除)并找到它们的路径。我遇到的第一个奇怪的事情是,在我见过的所有情况下(3)驱动器 C 包含很多无效的 MFT 记录(超过 3/4)。其中大多数(如果不是全部)未通过签名验证。

我通常会认为这些记录没有被使用,但还有另一个问题让我认为有些地方出了问题:当找到所有具有所需扩展名的文件记录时,一些记录指向未通过验证的父 MFT 记录由于同样的原因。但是这些文件被标记为“正在使用”,我在资源管理器中看到它们。另外,另一个奇怪的事情是它们所在的目录是有效的,因为在相同的目录/子目录中存在指向有效目录的文件(例如,我在桌面上有文件 log.txt,它指向一个无效的文件记录。还有一个文件夹数据(在桌面上也是如此),其中包含一个文件 info.txt 和“数据”指向一个有效的文件记录)。

签名验证(简化):

struct FILE_RECORD_HEADER  
{
    uint32      Magic;          //Should match FILE_RECORD_SIGNATURE
    uint16      OffsetOfUS;     //Offset of Update Sequence
    uint16      SizeOfUS;       //Size in 2-byte ints of Update Sequence Number & Array
    uint64      LSN;            //$LogFile Sequence Number
    uint16      SeqNo;          //Sequence number
    uint16      Hardlinks;      //Hard link count
    uint16      OffsetOfAttr;   //Offset of the first Attribute
    uint16      Flags;          //Flags
    uint32      RealSize;       //Real size of the FILE record
    uint32      AllocSize;      //Allocated size of the FILE record
    uint64      RefToBase;      //File reference to the base FILE record. Low 6B - file reference, high 2B - MFT record sequence number
    uint16      NextAttrId;     //Next Attribute Id
    uint16      Align;          //Align to 4 uint8 boundary
    uint32      RecordNo;       //Number of this MFT Record
};

#define FILE_RECORD_SIGNATURE       'ELIF'

FILE_RECORD_HEADER * header = (FILE_RECORD_HEADER *)rawFileRecord; //where rawFileRecord is a pointer to a block of memory in which a file record is stored
if(header->Magic != FILE_RECORD_SIGNATURE) //The file record is invalid

获取父级的LCN:

struct ATTR_FILE_NAME
{
    uint64  ParentRef;      //File reference to the parent directory. Low 6B - file reference, high 2B - MFT record sequence number
    uint64  CreateTime;     //File creation time
    uint64  AlterTime;      //File altered time
    uint64  MFTTime;        //MFT changed time
    uint64  ReadTime;       //File read time
    uint64  AllocSize;      //Allocated size of the file
    uint64  RealSize;       //Real size of the file
    uint32  Flags;          //Flags
    uint32  ER;             //Used by EAs and Reparse
    uint8   NameLength;     //Filename length in characters
    uint8   NameSpace;      //Filename space
    uint16  Name[1];        //Filename
};

ATTR_FILE_NAME * attr = (ATTR_FILE_NAME*)filenameAttr; //where filenameAttr is a pointer to the beginning of filename attribute somewhere in the rawFileRecord
uint64 parentLCN = attr->ParentRef & 0x0000FFFFFFFFFFFF;

是否有可能由于这种签名不匹配而丢失(就搜索而言)文件(我认为是的,但我想确定一下)?为什么有些文件记录指向无效的父母,而另一些指向有效的父母(他们应该有相同的父母)?

【问题讨论】:

  • Stack Overflow 用于编程问题。这个问题跑题了。
  • @IInspectable NTFS 结构及其内部工作如何与编程无关?
  • 不,他们不是。这个问题是关于通用计算软件和硬件的。见help center
  • @IInspectable 那么为什么这个站点上有大约 600 个关于 ntfs 的问题得到解答?为什么我在尝试编写 NTFS 解析器时遇到奇怪行为的问题突然离题了?
  • 如果您对实现有疑问,请发布minimal reproducible example,包括观察到的和预期的行为。如所写,您只是在询问协议的技术细节。这不是编程问题。我已经发布了指向help center 的链接。

标签: c++ windows ntfs ntfs-mft


【解决方案1】:

您要搜索的参考是 FILE_RECORD_HEADER 中的 RecordNo。

ParentRef 中的 Low 6B - 文件引用应该与之匹配。

如果这两个匹配,您就有正确的文件。

这是 NTFS 只能包含 4'294'967'295 个文件的主要原因,因为它存储在 uint32 中。

就个人而言,我发现使用 $INDEX_ROOT_ATTR 和 $INDEX_ALLOCATION_ATTR 映射所有内容更容易,因为您可以找到相同类型的引用,并且它允许您更轻松地遵循树结构,因为您可以从根开始(他的记录号是总是 5)。

【讨论】:

    猜你喜欢
    • 2012-07-23
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 2018-04-14
    • 1970-01-01
    • 2017-01-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多