Как получить доступ к указателю файла каждого блока файла из файла $ MFT в NTFS?

Я работаю над проектом виртуализации файлов и управления версиями. Для этого мне нужно получить доступ к логическим блокам содержимого файла напрямую, без копирования в память. Кто-нибудь может помочь мне с фрагментами кода, которые работают на моих 64-битных окнах?

Я попробовал следующий код для доступа к файлу 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 %u\n", GetLastError());//else//wprintf(L"FormatMessage() should be fine!\n");
    wprintf(L"Error code %u:\n  %s\n", dwErrCode, szErrString) ;// This buffer used by FormatMessage()
    if(LocalFree(szErrString) != NULL)
    wprintf(L"Failed to free up the buffer, error %u\n", GetLastError());//else//wprintf(L"Buffer has been freed\n");
    }
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!

Спасибо


person loghi aha    schedule 06.08.2019    source источник
comment
без копирования в память - это как?   -  person RbMm    schedule 06.08.2019


Ответы (1)


Прав администратора недостаточно. Что вам нужно сделать, так это запросить резервное копирование и восстановление привилегий для вашего процесса. В MSDN есть пример кода. Имейте в виду, что вам, вероятно, понадобятся и SE_BACKUP_NAME, и SE_RESTORE_NAME.

Процесс немного громоздкий:

  1. Используйте OpenProcessToken в своем процессе с TOKEN_ADJUST_PRIVILEGES
  2. Используйте LookupPrivilegeValue, чтобы получить привилегию на основе строковых констант (одна для SE_BACKUP_NAME, одна для SE_RESTORE_NAME)
  3. Используйте AdjustTokenPrivileges для получения привилегий резервного копирования и восстановления.

Если вы сделаете это правильно, остальная часть вашего кода должна работать. Чтобы на самом деле перечислить MFT, вы захотите использовать FSCTL_ENUM_USN_DATA вариант DeviceIOControl.

person Luaan    schedule 06.08.2019
comment
Я попробовал ваше решение, но оно снова отказывает в доступе, даже если привилегия была успешно изменена. - person loghi aha; 06.08.2019