如何从NTFS中的$ MFT文件访问文件的每个块的文件指针

How to access the file pointer of each blocks of a file from the $MFT file in NTFS?

本文关键字:文件 访问 指针 MFT NTFS 中的      更新时间:2023-10-16

我正在从事文件虚拟化和版本控制项目。为此,我需要直接访问文件内容的逻辑块,而无需复制内存。有人可以帮助我使用在我64位Windows上使用的代码段吗?

我尝试了以下代码访问MFT文件。但是,即使我拥有管理员特权,它也会像"访问被拒绝"一样。

#include<windows.h>
#include<stdio.h>
#include<winioctl.h>
// Format the Win32 system error code to string
void ErrorMessage(DWORD dwCode);
int wmain(int argc, WCHAR **argv){
    HANDLE hVolume;
    WCHAR lpDrive[] = L"\\.\C:";
    PNTFS_VOLUME_DATA_BUFFER ntfsVolData = {0};
    BOOL bDioControl = FALSE;
    DWORD dwWritten = 0;
    hVolume = CreateFile(lpDrive, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
    if(hVolume == INVALID_HANDLE_VALUE){
        wprintf(L"CreateFile() failed!n");
        ErrorMessage(GetLastError());
        if(CloseHandle(hVolume) != 0)
            wprintf(L"hVolume handle was closed successfully!n");
        else{
            wprintf(L"Failed to close hVolume handle!n");
            ErrorMessage(GetLastError());
            }
        }
        else
            wprintf(L"CreateFile() is pretty fine!n");
            ntfsVolData = (PNTFS_VOLUME_DATA_BUFFER)malloc(sizeof(NTFS_VOLUME_DATA_BUFFER)+sizeof(NTFS_EXTENDED_VOLUME_DATA));
        bDioControl = DeviceIoControl(hVolume, FSCTL_GET_NTFS_VOLUME_DATA, NULL, 0, ntfsVolData,sizeof(NTFS_VOLUME_DATA_BUFFER)+sizeof(NTFS_EXTENDED_VOLUME_DATA), &dwWritten, NULL);
        if(bDioControl == 0){
            wprintf(L"DeviceIoControl() failed!n");
            ErrorMessage(GetLastError());
            if(CloseHandle(hVolume) != 0)
                wprintf(L"hVolume handle was closed successfully!n");
            else{
                wprintf(L"Failed to close hVolume handle!n");
                ErrorMessage(GetLastError());
                }
        }

    getchar();
}
void ErrorMessage(DWORD dwCode){
    DWORD dwErrCode = dwCode;
    DWORD dwNumChar;
    LPWSTR szErrString = NULL;  // will be allocated and filled by FormatMessage
    dwNumChar = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM, 0, dwErrCode, 0,     (LPWSTR)&szErrString, 0,0 );               // since getting message from system tables
    if(dwNumChar == 0)wprintf(L"FormatMessage() failed, error %un", GetLastError());//else//wprintf(L"FormatMessage() should be fine!n");
    wprintf(L"Error code %u:n  %sn", dwErrCode, szErrString) ;// This buffer used by FormatMessage()
    if(LocalFree(szErrString) != NULL)
    wprintf(L"Failed to free up the buffer, error %un", GetLastError());//else//wprintf(L"Buffer has been freedn");
    }
CreateFile() failed!
Error code 5:
  Access is denied.
hVolume handle was closed successfully!
DeviceIoControl() failed!
Error code 6:
  The handle is invalid.
hVolume handle was closed successfully!

谢谢

管理员特权还不够。您需要做的是请求备份并恢复流程的特权。MSDN具有示例代码。请记住,您可能需要SE_BACKUP_NAMESE_RESTORE_NAME

这个过程有点麻烦:

  1. 使用TOKEN_ADJUST_PRIVILEGES
  2. 在过程中使用OpenProcessToken
  3. 使用LookupPrivilegeValue根据字符串常数获得特权(一个用于SE_BACKUP_NAME,一个用于SE_RESTORE_NAME(
  4. 使用AdjustTokenPrivileges获取备份并恢复特权

如果正确执行此操作,则代码的其余部分应起作用。要实际列举MFT,您需要使用DeviceIOControlFSCTL_ENUM_USN_DATA变体。