【问题标题】:NtCreateFile returning STATUS_OBJECT_NAME_NOT_FOUND even if the file exists in the directoryNtCreateFile 返回 STATUS_OBJECT_NAME_NOT_FOUND 即使文件存在于目录中
【发布时间】:2020-11-12 17:34:59
【问题描述】:

我一直在尝试使用 NtCreateFile 打开现有文件,尽管它无法找到我正在寻找的文件,即使它存在于我尝试打开文件的目录中。

NtCreateFile 返回错误代码 0x34,即 STATUS_OBJECT_NAME_NOT_FOUND。

我三次检查路径是否格式正确,我还确保 UNICODE_STRING 的 Length 和 MaximumLength 都是偶数而不是奇数,因为它会导致 NtCreateFile 抛出错误代码 0x33(更多信息在这里:NtOpenFile returns STATUS_OBJECT_NAME_INVALID) .

我注意到,虽然在同一个文件夹中使用另一个 .png 文件可以正常工作,但我可以成功获取文件的句柄,使用不同的标志是 FILE_DIRECTORY_FILE 而不是 FILE_NON_DIRECTORY_FILE。

代码如下:

#define DLL_FILE_OPEN                       1
#define DLL_NON_DIRECTORY_FILE              0x40
#define DLL_OPEN_BY_FILE_ID                 0x2000
#define DLL_DIRECTORY_FILE                  1
#define DLL_FILE_OPENED                     1
#define DLL_SYNCRONIZE                      0x00100000L
#define DLL_FILE_READ_ATTRIBUTES            0x0080
#define DLL_FILE_OPEN_FOR_BACKUP_INTENT     0x00004000


#define OBJ_CASE_INSENSITIVE                0x00000040L


void main()
{

    OBJECT_ATTRIBUTES oa;
    IO_STATUS_BLOCK isb;
    UNICODE_STRING NtPath;
    HANDLE FileHandle;
    NTSTATUS status;
    ULONG FileAttributes, Flags = 0;
    PVOID EaBuffer = 0;
    ULONG EaLength = 0;

    Flags |= DLL_NON_DIRECTORY_FILE;
    Flags |= DLL_FILE_OPEN_FOR_BACKUP_INTENT;

    NtPath.Buffer = (PWSTR)L"\\??\\C:\\Users\\MyUsername\\Downloads\\verifica.txt";
    NtPath.Length = (USHORT)(wcslen(NtPath.Buffer) + 1);  // +1 to avoid it being an odd value.
    NtPath.MaximumLength = (USHORT)(sizeof(PWSTR) + 1);

    InitializeObjectAttributes(&oa, &NtPath, OBJ_CASE_INSENSITIVE, 0, 0);

    status = NewNtCreateFile(&FileHandle, FILE_GENERIC_READ, &oa, &isb, NULL, NULL, FILE_SHARE_READ, DLL_FILE_OPEN, Flags, EaBuffer, EaLength);

    if (status != 0)
        printf("status: 0x%08X\n", status);
    else
        if (!FileHandle || FileHandle == INVALID_HANDLE_VALUE)
            printf("Invalid handle.\n");
        else
            printf("file opened successfully\n");

    return;

}```

【问题讨论】:

    标签: c winapi nt-native-api


    【解决方案1】:
     NtPath.Length = (USHORT)(wcslen(NtPath.Buffer));
    

    不。该字段是以字节为单位的长度。

     NtPath.Length = (USHORT)(wcslen(NtPath.Buffer)) << 1;
    

    此外,由于您没有将字符串传递给将写入它的内容,因此我建议将 NtPath.MaximumLengthLength 相同。

    如果您继续使用这些 API,请注意一点警告,默认情况下文件句柄是异步打开的,IO_STATUS_BLOCK 结构需要 16 字节对齐。

    【讨论】:

    • (USHORT)(wcslen(NtPath.Buffer) ) &lt;&lt; 1; 必须是。没有+1 - 终止的 0 不能包含在长度中
    • 我的意思是NtPath.Length = (USHORT)(wcslen(NtPath.Buffer) + 1) &lt;&lt; 1; - 错了。正确的必须是NtPath.Length = (USHORT)wcslen(NtPath.Buffer) &lt;&lt; 1;
    • 而 IO_STATUS_BLOCK 结构需要 16 字节对齐。 这也不正确。这是指针大小对齐。 8 或 4 个字节
    • 在大多数情况下最简单地使用RtlInitUnicodeString作为对象名称。例如RtlInitUnicodeString(&amp;NtPath, L"***");
    • @RbMm:我记得必须修复 IO_STATUS_BLOCK 对齐。至少有一个函数对它只有 8 个字节对齐感到非常生气。
    猜你喜欢
    • 1970-01-01
    • 2016-09-27
    • 2011-11-29
    • 2014-02-10
    • 2023-03-17
    • 2015-02-01
    • 2014-03-16
    • 2019-08-08
    • 1970-01-01
    相关资源
    最近更新 更多