2

I'm using this MSDN link to read USN records programatically. https://learn.microsoft.com/en-us/windows/win32/fileio/walking-a-buffer-of-change-journal-records

Error: Exception thrown at 0x00007FFD58682666 (ucrtbased.dll) in Project1.exe: 0xC0000005: Access violation reading location 0x00000000FFFFFD7F.

#include <Windows.h>
#include <WinIoCtl.h>
#include <stdio.h>

#define BUF_LEN 4096

void main()
{
    HANDLE hVol;
    CHAR Buffer[BUF_LEN];

    USN_JOURNAL_DATA JournalData;
    READ_USN_JOURNAL_DATA_V1 ReadData = { 0, 0xFFFFFFFF, FALSE, 0, 0, 0, 2, 3 };
    PUSN_RECORD UsnRecord;

    DWORD dwBytes;
    DWORD dwRetBytes;
    int I;

    hVol = CreateFile(TEXT("\\\\.\\c:"),
        GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        0,
        NULL);

    if (hVol == INVALID_HANDLE_VALUE)
    {
        printf("CreateFile failed (%d)\n", GetLastError());
        return;
    }

    if (!DeviceIoControl(hVol,
        FSCTL_QUERY_USN_JOURNAL,
        NULL,
        0,
        &JournalData,
        sizeof(JournalData),
        &dwBytes,
        NULL))
    {
        printf("Query journal failed (%d)\n", GetLastError());
        return;
    }

    ReadData.UsnJournalID = JournalData.UsnJournalID;

    printf("Journal ID: %I64x\n", JournalData.UsnJournalID);
    printf("FirstUsn: %I64x\n\n", JournalData.FirstUsn);

    for (I = 0; I <= 10; I++)
    {
        memset(Buffer, 0, BUF_LEN);

        if (!DeviceIoControl(hVol,
            FSCTL_READ_USN_JOURNAL,
            &ReadData,
            sizeof(ReadData),
            &Buffer,
            BUF_LEN,
            &dwBytes,
            NULL))
        {
            printf("Read journal failed (%d)\n", GetLastError());
            return;
        }

        dwRetBytes = dwBytes - sizeof(USN);

        // Find the first record
        UsnRecord = (PUSN_RECORD)(((PUCHAR)Buffer) + sizeof(USN));
        NTFS_FILE_RECORD_OUTPUT_BUFFER * FileRef = (NTFS_FILE_RECORD_OUTPUT_BUFFER *)(UsnRecord);

        printf("****************************************\n");

        // This loop could go on for a long time, given the current buffer size.
        while (dwRetBytes > 0)
        {
            printf("USN: %I64x\n", UsnRecord->Usn);
            printf("File name: %.*S\n",
                UsnRecord->FileNameLength / 2,
                UsnRecord->FileName);
            wprintf(UsnRecord->FileName);
            fputws(UsnRecord->FileName, stdout);
            printf("file record found\n%.*S\n",
                FileRef->FileReferenceNumber);
            //added
            /*rootdir_usn = (USN_RECORD *)buffer;
            show_record(rootdir_usn, FALSE);
            rootdir = rootdir_usn->FileReferenceNumber;*/
            //stopped


            printf("Reason: %x\n", UsnRecord->Reason);
            printf("\n");

            dwRetBytes -= UsnRecord->RecordLength;

            // Find the next record
            UsnRecord = (PUSN_RECORD)(((PCHAR)UsnRecord) +
                UsnRecord->RecordLength);
        }
        // Update starting USN for next call
        ReadData.StartUsn = *(USN *)&Buffer;
    }

    CloseHandle(hVol);

}
priyalsoni
  • 49
  • 9

1 Answers1

0

Here it looks like its missing a sanity check

UsnRecord = (PUSN_RECORD)(((PUCHAR)Buffer) + sizeof(USN));    
NTFS_FILE_RECORD_OUTPUT_BUFFER * FileRef = (NTFS_FILE_RECORD_OUTPUT_BUFFER *)(UsnRecord);
if (!FileRef) {
  printf("This was not the FileRef I was looking for\n");
  return;
}

and if this fails then UsnRecord is bad and the error occurred previously, a guess could be

for (I = 0; I <= 10; I++)

And the error occurs on the 11th iteration.

Surt
  • 15,501
  • 3
  • 23
  • 39
  • No, the USN record is fine. I checked this out. The error is that it's not printing filenames for USN Records. As in, for Filename, there's an empty string printed. It doesn't parse the value. Is there any way to read filenames from USNRecords? – priyalsoni May 18 '20 at 04:57