探索NTFS
D:\>copy con file
testforntfs^Z
已复制 1 个文件。
D:\>nfi d:\file
NTFS File Sector Information Utility.
Copyright (C) Microsoft Corporation 1999. All rights reserved.
\file
$STANDARD_INFORMATION (resident)
$FILE_NAME (resident)
$DATA (resident)
D:\>echo testforattr>file:ATTR
D:\>nfi d:\file
NTFS File Sector Information Utility.
Copyright (C) Microsoft Corporation 1999. All rights reserved.
\file
$STANDARD_INFORMATION (resident)
$FILE_NAME (resident)
$DATA (resident)
$DATA ATTR (resident)
nfi的输出结果$STANDARD_INFORMATION、$FILE_NAME、$DATA等在NTFS中称为属性(Attribute)。属性分为常驻属性(Resident Attribute)与非常驻属性(Nonresident Attribute)。文件的数据也包含在属性中,似乎与属性这个名称有点混谣。不过这又让NTFS有了更加统一的组织文件的形式。这也同时让NTFS有MultiStreams的特性(上面也演示了这个特性)。通过指定的File Record定位给定的Attribute的实现代码如下:
template inline
T1* Padd(T1* p, T2 n) { return (T1*)((char *)p + n); }
PATTRIBUTE FindAttribute(PFILE_RECORD_HEADER file,
ATTRIBUTE_TYPE type, PWSTR name)
{
for (PATTRIBUTE attr = PATTRIBUTE(Padd(file, file->AttributesOffset));
attr->AttributeType != -1;
attr = Padd(attr, attr->Length)) {
if (attr->AttributeType == type) {
if (name == 0 && attr->NameLength == 0) return attr;
if (name != 0 && wcslen(name) == attr->NameLength
&& _wcsicmp(name, PWSTR(Padd(attr, attr->NameOffset))) == 0) return attr;
}
}
return 0;
}
Gary Nebbett提供的这个FindAttribute函数在Attribute name(即第三个参数)不为空串时可能会出现bug,主要原因是_wcsicmp对UNICODE字符串比较时应该是以\0结束的标准的C字符串。我在提供的代码中已经纠正了这个错误。
下面我将通过使用SoftICE来分析这段代码得到$MFT的$FILE_NAME属性来得到$MFT的file name。这个示例同样适用于得到其它文件的$FILE_NAME(如上面的file)、还有其它的属性如$DATA等等。
:bpx FindAttribute
Break due to BPX FindAttribute (ET=6.89 seconds)
:locals
[EBP-4] +struct ATTRIBUTE * attr = 0x00344D68 <{...}>
[EBP+8] +struct FILE_RECORD_HEADER * file = 0x00344D38 <{...}>
[EBP+C] enum ATTRIBUTE_TYPE type = AttributeFileName (30)
[EBP+10] +unsigned short * name = 0x004041BC <"$MFT">
:?file
struct FILE_RECORD_HEADER * = 0x00344D38 <{...}>
struct NTFS_RECORD_HEADER Ntfs = {...}
unsigned short SequenceNumber = 0x1, "\0\x01"
unsigned short LinkCount = 0x1, "\0\x01"
unsigned short AttributesOffset = 0x30, "\00"
unsigned short Flags = 0x1, "\0\x01"
unsigned long BytesInUse = 0x2D8, "\0\0\x02\xD8"
unsigned long BytesAllocated = 0x400, "\0\0\x04\0"
unsigned quad BaseFileRecord = 0x0, "\0\0\0\0\0\0\0\0" |