0

I am working on file virtualization and versioning project. For that, I need to access the logical blocks of file contents directly without copying into memory. Anyone could you help me with code snippets that works on my 64 bit windows?

I tried the following code to access the MFT file. But it responds like 'Access denied' even though I ran with administrator privileges.

#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!

Thank you

1 Answers1

0

Admin privileges aren't enough. What you need to do is request backup and restore privileges for your process. MSDN has sample code. Keep in mind that you probably need both SE_BACKUP_NAME and SE_RESTORE_NAME.

The process is a bit cumbersome:

  1. Use OpenProcessToken on your process with TOKEN_ADJUST_PRIVILEGES
  2. Use LookupPrivilegeValue to get the privilege based on the string constants (one for SE_BACKUP_NAME, one for SE_RESTORE_NAME)
  3. Use AdjustTokenPrivileges to acquire the backup and restore privileges

If you do this properly, the rest of your code should work. To actually enumerate the MFT, you'll want to use the FSCTL_ENUM_USN_DATA variant of DeviceIOControl.

Luaan
  • 62,244
  • 7
  • 97
  • 116