探索NTFS
0023:00344E18 00000006 00000000 00240304 0046004D ..........$.M.F.
-- --------
| |___找到$MFT的FileName了吧。
|_NameLength
0023:00344E28 00000054 00000000 00000080 00000190 T...............
0023:00344E38 00400001 00010000 00000000 00000000 ..@.............
这儿给出了Dump Attribute的一个具体方法。最后我将给出遍历File Record的代码,在给出代码前应该说明一下$MFT中$BITMAP属性。NTFS的这个Attribute相当于LINUX EXT2的s_inode_bitmap数组(Linux 2.0版本)。所以很容易明白$BITMAP的作用,即每bit指出相应File Record的在用情况。以下是DumpAllFileRecord的代码:
BOOL bitset(PUCHAR bitmap, ULONG i)
{
return (bitmap[i >> 3] & (1 << (i & 7))) != 0;
}
VOID DumpAllFileRecord()
{
PATTRIBUTE attr = FindAttribute(MFT, AttributeBitmap, 0);
PUCHAR bitmap = new UCHAR[AttributeLengthAllocated(attr)];
ReadAttribute(attr, bitmap);
ULONG n = AttributeLength(FindAttribute(MFT, AttributeData, 0)) / BytesPerFileRecord;
PFILE_RECORD_HEADER file = PFILE_RECORD_HEADER(new UCHAR[BytesPerFileRecord]);
for (ULONG i = 0; i < n; i++) {
if (!bitset(bitmap, i)) continue;
ReadFileRecord(i, file);
if (file->Ntfs.Type == 'ELIF' && (file->Flags & 3 )) {
attr = FindAttribute(file, AttributeFileName, 0);
if (attr == 0) continue;
PFILENAME_ATTRIBUTE name
= PFILENAME_ATTRIBUTE(Padd(attr, PRESIDENT_ATTRIBUTE(attr)->ValueOffset));
printf("%8lu %.*ws\n", i, int(name->NameLength),name->Name)
}
}
}
本文引用Gary Nebbett的些定义可能对Windows 2000版本有些很小的出入,不过Internet有其神奇的地方,虽然Microsoft不提供这些信息,但诸如linux-ntfs GNU工程等均是学习NTFS的一个很好的资料,本文也参考了很多它提供的文档。另外Mark Russinovich的《Inside Win2K NTFS》、《Inside NTFS》、《Exploring NTFS On-disk Structures》等也是很好的NTFS资料。本文仍未涉及NTFS中目录的组织(B+树)等等,可能的话我会另行介绍。文中介绍的完整代码可到http://webcrazy.yeah.net下载。出现的错误也欢迎来信指教(tsu00@263.net)!
最后感谢Anton Altaparmakov,感谢我的同事在出差时抽空给我买到Gary Nebbett的书。感谢我看到的所有资料的原作者们。感谢他们!
参考资料:
1.Gary Nebbett《Windows NT/2000 Native API Reference》
2.Linux-NTFS Project NTFS Documentation Version 0.4
3.Mark Russinovich相关文档
4.David Solomom《Inside Windows NT,2nd Edition》
|