2025年2月24日 星期一 甲辰(龙)年 腊月廿四 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > VC/VC++

NTFS格式 读取MFT信息

时间:09-21来源:作者:点击数:29

NTFS格式 读取MFT信息

  • #include "ntfs.h"
  • #include <iostream>
  • #include <fstream>
  • #include <map>
  • #include <vector>
  • using namespace std;
  • //管理员权限运行
  • typedef struct {
  • ULONGLONG index;
  • ULONGLONG parent;
  • WCHAR name[1024];
  • int type; //0 file 1 dir
  • } FILE_INFO, *PFILE_INFO;
  • //枚举盘符
  • void OpenNtfsVolume()
  • {
  • WCHAR tDrivers[26*4+1] = {};
  • GetLogicalDriveStrings(26*4+1,tDrivers);
  • WCHAR fileSysBuf[8];
  • DWORD dwDri; //0~25
  • WCHAR szRootName[40];
  • WCHAR szVolumeName[32];
  • int iFilterRoot=0;
  • for(WCHAR *p=tDrivers;*p!='\0';p+=4)
  • {
  • if(*p>=L'a') *p-=32;//
  • dwDri=*p-L'A';
  • if(DRIVE_FIXED==GetDriveTypeW(p))
  • {
  • DWORD dwMaxComLen,dwFileSysFlag;
  • GetVolumeInformationW(p,szVolumeName,32,NULL,&dwMaxComLen,&dwFileSysFlag,fileSysBuf,8);
  • if(fileSysBuf[0]==L'N' && fileSysBuf[1]==L'T' && fileSysBuf[2]==L'F' && fileSysBuf[3]==L'S')
  • {
  • swprintf(szRootName,L"%s (%c:)",szVolumeName,*p);
  • WCHAR szVolumePath[10];
  • swprintf(szVolumePath,L"\\\\.\\%c:",*p);
  • wcout<<szVolumePath<<endl;
  • }
  • }
  • }
  • }
  • int main()
  • {
  • //wcout.imbue(locale(locale(),"",LC_CTYPE));
  • char szACP[16];
  • sprintf(szACP, ".%d", GetACP());
  • //setlocale(LC_CTYPE, szACP);
  • wcout.imbue(locale(locale(),szACP,LC_CTYPE));
  • OpenNtfsVolume();
  • WCHAR driveletter[] = L"\\\\.\\D:";
  • HANDLE hVol = CreateFile(driveletter, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
  • NTFS_VOLUME_DATA_BUFFER ntfsVolData;
  • DWORD dwWritten = 0;
  • BOOL bDioControl = DeviceIoControl(hVol, FSCTL_GET_NTFS_VOLUME_DATA, NULL, 0, &ntfsVolData, sizeof(ntfsVolData), &dwWritten, NULL);
  • if (!bDioControl) {wcout<<L"error"<<endl; return 1;}
  • LARGE_INTEGER num;
  • num.QuadPart = 1024;
  • LONGLONG total_file_count = (ntfsVolData.MftValidDataLength.QuadPart/num.QuadPart);
  • wcout<<L"total_file_count:"<<total_file_count<<endl;
  • PNTFS_FILE_RECORD_OUTPUT_BUFFER ntfsFileRecordOutput = (PNTFS_FILE_RECORD_OUTPUT_BUFFER)malloc(sizeof(NTFS_FILE_RECORD_OUTPUT_BUFFER)+ntfsVolData.BytesPerFileRecordSegment-1);
  • for( LONGLONG i = 0; i < total_file_count && i < 10;i++)
  • {
  • NTFS_FILE_RECORD_INPUT_BUFFER mftRecordInput;
  • mftRecordInput.FileReferenceNumber.QuadPart = i;
  • memset(ntfsFileRecordOutput, 0, sizeof(NTFS_FILE_RECORD_OUTPUT_BUFFER)+ntfsVolData.BytesPerFileRecordSegment-1);
  • DeviceIoControl(hVol, FSCTL_GET_NTFS_FILE_RECORD, &mftRecordInput, sizeof(mftRecordInput), ntfsFileRecordOutput, sizeof(NTFS_FILE_RECORD_OUTPUT_BUFFER)+ntfsVolData.BytesPerFileRecordSegment-1, &dwWritten, NULL);
  • PFILE_RECORD_HEADER pfileRecordheader=(PFILE_RECORD_HEADER)ntfsFileRecordOutput->FileRecordBuffer;
  • if(pfileRecordheader->Ntfs.Type != 'ELIF')
  • continue;
  • for(PATTRIBUTE pAttribute = (PATTRIBUTE)((PBYTE)pfileRecordheader +pfileRecordheader->AttributeOffset);pAttribute->AttributeType != -1;pAttribute=(PATTRIBUTE)((PBYTE)pAttribute +pAttribute->Length))
  • {
  • switch (pAttribute->AttributeType)
  • {
  • case AttributeFileName:
  • {
  • if((0x0002 & pfileRecordheader->Flags) && (0x0001 & pfileRecordheader->Flags));
  • PFILENAME_ATTRIBUTE pFileNameAttr=PFILENAME_ATTRIBUTE((PBYTE)pAttribute+PRESIDENT_ATTRIBUTE(pAttribute)->ValueOffset);
  • }
  • break;
  • case AttributeStandardInformation:
  • break;
  • case AttributeAttributeList:
  • break;
  • case AttributeObjectId:
  • break;
  • }
  • }
  • }
  • free(ntfsFileRecordOutput);
  • USN_JOURNAL_DATA journalData;
  • READ_USN_JOURNAL_DATA readData = {0, 0xFFFFFFFF, FALSE, 0, 0};
  • PUSN_RECORD usnRecord;
  • DWORD dwBytes;
  • DWORD dwRetBytes;
  • char buffer[USN_PAGE_SIZE];
  • bDioControl = DeviceIoControl(hVol, FSCTL_QUERY_USN_JOURNAL, NULL,0,&journalData,sizeof(journalData),&dwBytes,NULL);
  • if (!bDioControl) {wcout<<L"error"<<endl; return 1;}
  • readData.UsnJournalID = journalData.UsnJournalID;
  • wprintf(L"Journal ID: %I64x\n", journalData.UsnJournalID );
  • wprintf(L"FirstUsn: %I64x\n\n", journalData.FirstUsn );
  • MFT_ENUM_DATA med;
  • med.StartFileReferenceNumber = 0;
  • med.LowUsn = 0;
  • med.HighUsn = journalData.NextUsn;
  • map<ULONGLONG,wstring> namemap;
  • map<ULONGLONG,ULONGLONG> frnmap;
  • vector<FILE_INFO> fileVect;
  • for (;;)
  • {
  • memset(buffer, 0, sizeof(USN_PAGE_SIZE));
  • //FSCTL_ENUM_USN_DATA FSCTL_READ_USN_JOURNAL
  • //DeviceIoControl( hVol, FSCTL_READ_USN_JOURNAL, &readData,sizeof(readData),&buffer,USN_PAGE_SIZE,&dwBytes,NULL);
  • bDioControl = DeviceIoControl( hVol, FSCTL_ENUM_USN_DATA, &med, sizeof(med),&buffer,USN_PAGE_SIZE,&dwBytes,NULL);
  • if (!bDioControl) {wcout<<L"error"<<endl; break;}
  • if(dwBytes<=sizeof(USN)) break;//结束!
  • dwRetBytes = dwBytes - sizeof(USN);//跳过了1个USN,此USN是下一论查询起点
  • usnRecord = (PUSN_RECORD)(((PUCHAR)buffer) + sizeof(USN));
  • while(dwRetBytes > 0)
  • {
  • FILE_INFO fi;
  • fi.index = usnRecord->FileReferenceNumber;
  • fi.parent = usnRecord->ParentFileReferenceNumber;
  • //wprintf(L"USN: %I64x\n", usnRecord->Usn );
  • //wprintf(L"File name: %.*s\n", (int)(usnRecord->FileNameLength/2),usnRecord->FileName );
  • //wprintf(L"Reason: %x\n", usnRecord->Reason );
  • memset(fi.name,0,sizeof(fi.name));
  • swprintf(fi.name,L"%.*ws", (int)(usnRecord->FileNameLength/2),usnRecord->FileName);
  • namemap[fi.index] = wstring(fi.name);
  • fileVect.push_back(fi);
  • frnmap[fi.index] = fi.parent;
  • dwRetBytes -= usnRecord->RecordLength;
  • usnRecord = (PUSN_RECORD)(((PCHAR)usnRecord) + usnRecord->RecordLength);
  • }
  • med.StartFileReferenceNumber=*(DWORDLONG*)buffer;
  • //readData.StartUsn = *(USN *)&buffer;
  • }
  • wcout<<fileVect.size()<<endl;
  • map<ULONGLONG,wstring>::iterator it;
  • /*for ( it=namemap.begin() ; it != namemap.end(); it++ )
  • {
  • wcout << (*it).first << " => " << ((*it).second).c_str() <<"==>"<<namemap[(*it).first].c_str()<< endl;
  • }*/
  • //wofstream ofs(L"data.txt");
  • for (LONGLONG i = 0; i < fileVect.size(); i++)
  • {
  • FILE_INFO fi = fileVect[i];
  • wcout<<i<<": "<<fi.name<<"===>";
  • ULONGLONG parent = fi.parent;
  • while (namemap.find(parent) != namemap.end())
  • {
  • wstring dir = namemap[parent];
  • wcout<<L"\\"<<dir.c_str();
  • if (frnmap.find(parent) != frnmap.end())
  • {
  • parent = frnmap[parent];
  • }
  • else
  • {
  • break;
  • }
  • }
  • wcout<<endl;
  • }
  • wcout<<"done"<<endl;
  • CloseHandle(hVol);
  • return 0;
  • }
  • /*typedef struct {
  • DWORD RecordLength;
  • WORD MajorVersion;
  • WORD MinorVersion;
  • DWORDLONG FileReferenceNumber;
  • DWORDLONG ParentFileReferenceNumber;
  • USN Usn;
  • LARGE_INTEGER TimeStamp;
  • DWORD Reason;
  • DWORD SourceInfo;
  • DWORD SecurityId;
  • DWORD FileAttributes;
  • WORD FileNameLength;
  • WORD FileNameOffset;
  • WCHAR FileName[1];
  • } USN_RECORD, *PUSN_RECORD;*/

下面是ntfs.h的内容,编译使用UNICODE编码

  • #include <Windows.h>
  • #include <WinIoCtl.h>
  • typedef struct {
  • ULONG Type; //4B 'ELIF','XDNI','DAAB','ELOH','DKHC'
  • USHORT UsaOffset; //2B 更新序列号数组偏移,校验值地址
  • USHORT UsaCount; //1+n 1为校验值个数 n为待替换值个数 fixup
  • USN Usn; //8B 每次记录被修改 USN都变化
  • } NTFS_RECORD_HEADER, *PNTFS_RECORD_HEADER;
  • typedef struct { //sizeof(FILE_RECORD_HEADER)==48
  • NTFS_RECORD_HEADER Ntfs; //16B Ntfs.Type总是'ELIF'
  • USHORT SequenceNumber; //File Reference Number的高16位 i是低48位 0~total_file_count-1
  • //用于记录主文件表记录被重复使用的次数
  • USHORT LinkCount; //记录硬连接的数目,只出现在基本文件记录中
  • USHORT AttributeOffset; //第一个属性的偏移
  • USHORT Flags; // 0x0001 = InUse, 0x0002 = Directory
  • ULONG BytesInUse; //记录头和属性的总长度,即文件记录的实际长度文件,即记录在磁盘上实际占用的字节空间。
  • ULONG BytesAllocated; //总共分配给记录的长度
  • ULONGLONG BaseFileRecord; //基本文件记录中的文件索引号,
  • //对于基本文件记录,其值为0,如果不为0,则是一个主文件表的文件索引号,
  • //指向所属的基本文件记录中的文件记录号,
  • //在基本文件记录中包含有扩展文件记录的信息,存储在“属性列表ATTRIBUTE_LIST”属性中。
  • USHORT NextAttributeNumber; //下一属性ID
  • } FILE_RECORD_HEADER, *PFILE_RECORD_HEADER;
  • //文件记录中按属性非降序(因为有时连续多个相同的属性)排列,
  • //属性的值即为 字节流
  • typedef enum {
  • //诸如只读、存档等文件属性;
  • //时间戳:文件创建时、最后一次修改时;
  • //多少目录指向该文件(硬链接计数hard link count)
  • AttributeStandardInformation = 0x10, //Resident_Attributes 常驻属性
  • //?????????????????????????????????
  • //当一个文件要求多个MFT文件记录时 会有该属性
  • //属性列表,包括构成该文件的这些属性,以及每个属性所在的MFT文件记录的文件引用
  • //?????????????????????????????????
  • AttributeAttributeList = 0x20,//由于属性值可能会增长,可能是非驻留属性
  • //文件名属性可以有多个:
  • //1.长文件名自动为其短文件名(以便MS-DOS和16位程序访问)
  • //2.当该文件存在硬链接时
  • AttributeFileName = 0x30, //常驻
  • //一个文件或目录的64字节标识符,其中低16字节对于该卷来说是唯一的
  • //链接-跟踪服务将对象ID分配给外壳快捷方式和OLE链接源文件。
  • //NTFS提供了相应的API,因为文件和目录可以通过其对象ID,而不是通过其文件名打开
  • AttributeObjectId = 0x40, //常驻
  • //为与NTFS以前版本保持向后兼容
  • //所有具有相同安全描述符的文件或目录共享同样的安全描述
  • //以前版本的NTFS将私有的安全描述符信息与每个文件和目录存储在一起
  • AttributeSecurityDescriptor = 0x50,//出现于$Secure元数据文件中
  • //保存了该卷的版本和label信息
  • AttributeVolumeName = 0x60, //仅出现于$Volume元数据文件中
  • AttributeVolumeInformation = 0x70,//仅出现于$Volume元数据文件中
  • //文件内容,一个文件仅有一个未命名的数据属性,但可有额外多个命名数据属性
  • //即一个文件可以有多个数据流,目录没有默认的数据属性,但可有多个可选的命名的数据属性
  • AttributeData = 0x80,//由于属性值可能会增长,可能是非驻留属性
  • //以下三个用于实现大目录的文件名分配和位图索引
  • AttributeIndexRoot = 0x90,//常驻
  • AttributeIndexAllocation = 0xA0,
  • AttributeBitmap = 0xB0,
  • //存储了一个文件的重解析点数据,NTFS的交接(junction)和挂载点包含此属性
  • AttributeReparsePoint = 0xC0,
  • //以下两个为扩展属性,现已不再被主动使用,之所以提供是为与OS/2程序保持向后兼容
  • AttributeEAInformation = 0xD0,
  • AttributeEA = 0xE0,
  • AttributePropertySet = 0xF0,
  • AttributeLoggedUtilityStream = 0x100,
  • AttributeEnd=0xFFFFFFFF
  • } ATTRIBUTE_TYPE, *PATTRIBUTE_TYPE;
  • typedef struct {
  • ATTRIBUTE_TYPE AttributeType;
  • ULONG Length; //本属性长度(包含属性值)
  • BOOLEAN Nonresident; //本属性不是 驻留 属性么?
  • UCHAR NameLength; //属性名的名称长度
  • USHORT NameOffset;//属性名偏移
  • USHORT Flags; // 0x0001 压缩 0x4000 加密 0x8000稀疏文件
  • USHORT AttributeNumber;
  • } ATTRIBUTE, *PATTRIBUTE;
  • typedef struct {
  • ATTRIBUTE Attribute;
  • ULONG ValueLength; //属性值长度
  • USHORT ValueOffset; //属性值偏移
  • USHORT Flags; // 索引标志 0x0001 = Indexed
  • } RESIDENT_ATTRIBUTE, *PRESIDENT_ATTRIBUTE;
  • typedef struct {
  • ATTRIBUTE Attribute;
  • ULONGLONG LowVcn;
  • ULONGLONG HighVcn;
  • USHORT RunArrayOffset;
  • UCHAR CompressionUnit;
  • UCHAR AlignmentOrReserved[5];
  • ULONGLONG AllocatedSize;
  • ULONGLONG DataSize;
  • ULONGLONG InitializedSize;
  • ULONGLONG CompressedSize; // Only when compressed
  • } NONRESIDENT_ATTRIBUTE, *PNONRESIDENT_ATTRIBUTE;
  • typedef struct { //文件名属性的值区域
  • ULONGLONG DirectoryFileReferenceNumber; //父目录的FRN
  • ULONGLONG CreationTime;
  • ULONGLONG ChangeTime;
  • ULONGLONG LastWriteTime; // 最后一次MFT更新时间
  • ULONGLONG LastAccessTime;
  • ULONGLONG AllocatedSize; // 未明
  • ULONGLONG DataSize; // 偶尔与文件大小GetFileSize不同
  • ULONG FileAttributes;
  • ULONG AlignmentOrReserved;
  • UCHAR NameLength;
  • UCHAR NameType; //POSIX 0x0 WIN32 0x01 DOS 0x02 WIN32&DOS 0x3
  • WCHAR Name[1];
  • } FILENAME_ATTRIBUTE, *PFILENAME_ATTRIBUTE;
  • typedef struct {
  • ATTRIBUTE_TYPE AttributeType; //属性类型
  • USHORT Length; //本记录长度
  • UCHAR NameLength; //属性名长度
  • UCHAR NameOffset; //属性名偏移
  • ULONGLONG LowVcn; //起始VCN
  • ULONGLONG FileReferenceNumber; //属性的文件参考号
  • USHORT AttributeNumber; //标识
  • WCHAR Name[1];
  • } ATTRIBUTE_LIST, *PATTRIBUTE_LIST;
  • #pragma pack(push,1)
  • typedef struct { //512B
  • UCHAR Jump[3];//跳过3个字节
  • UCHAR Format[8]; //‘N’'T' 'F' 'S' 0x20 0x20 0x20 0x20
  • USHORT BytesPerSector;//每扇区有多少字节 一般为512B 0x200
  • UCHAR SectorsPerCluster;//每簇有多少个扇区
  • USHORT BootSectors;//
  • UCHAR Mbz1;//保留0
  • USHORT Mbz2;//保留0
  • USHORT Reserved1;//保留0
  • UCHAR MediaType;//介质描述符,硬盘为0xf8
  • USHORT Mbz3;//总为0
  • USHORT SectorsPerTrack;//每道扇区数,一般为0x3f
  • USHORT NumberOfHeads;//磁头数
  • ULONG PartitionOffset;//该分区的便宜(即该分区前的隐含扇区数 一般为磁道扇区数0x3f 63)
  • ULONG Reserved2[2];
  • ULONGLONG TotalSectors;//该分区总扇区数
  • ULONGLONG MftStartLcn;//MFT表的起始簇号LCN
  • ULONGLONG Mft2StartLcn;//MFT备份表的起始簇号LCN
  • ULONG ClustersPerFileRecord;//每个MFT记录包含几个簇 记录的字节不一定为:ClustersPerFileRecord*SectorsPerCluster*BytesPerSector
  • ULONG ClustersPerIndexBlock;//每个索引块的簇数
  • ULONGLONG VolumeSerialNumber;//卷序列号
  • UCHAR Code[0x1AE];
  • USHORT BootSignature;
  • } BOOT_BLOCK, *PBOOT_BLOCK;
  • #pragma pack(pop)
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐