2

我正在使用这个 MSDN 链接以编程方式读取 USN 记录。 https://docs.microsoft.com/en-us/windows/win32/fileio/walking-a-buffer-of-change-journal-records

错误:在 Project1.exe 中的 0x00007FFD58682666 (ucrtbased.dll) 处引发异常:0xC0000005:访问冲突读取位置 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);

}
4

1 回答 1

0

在这里,它看起来像是缺少健全性检查

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;
}

如果这失败了,那么 UsnRecord 是坏的并且错误发生在之前,一个猜测可能是

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

错误发生在第 11 次迭代。

于 2020-05-15T10:45:04.853 回答