cwinapint-native-api

NtCreateFile returning STATUS_OBJECT_NAME_NOT_FOUND even if the file exists in the directory


I have been trying to open an existing file using NtCreateFile, although it cannot find the file that I am looking for even if it is present in the directory I am trying to open the file in.

The file I am trying to open.

NtCreateFile returns the error code 0x34, aka STATUS_OBJECT_NAME_NOT_FOUND.

I triple checked if the path is in the correct format, I also made sure that both the UNICODE_STRING's Length and MaximumLength are even and not odd since it causes NtCreateFile to throw the error code 0x33 (more information here: NtOpenFile returns STATUS_OBJECT_NAME_INVALID).

I noticed though that with another .png file in the same folder it works fine, I can get a handle to the file successfully, using a different flag being FILE_DIRECTORY_FILE instead of FILE_NON_DIRECTORY_FILE.

THis is the .png file I managed to open with NtCreateFile

Here's the code:

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

}```

Solution

  •  NtPath.Length = (USHORT)(wcslen(NtPath.Buffer));
    

    Nope. That field is length in bytes.

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

    In additon, as you're not passing the string to something that will write to it, I recommend making NtPath.MaximumLength the same as Length.

    A little warning if you continue using these APIs, file handles are opened asynchronously by default, and the IO_STATUS_BLOCK structure wants 16 byte alignment.