1

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;

}```
Yung Lew
  • 81
  • 10

1 Answers1

1
 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.

Joshua
  • 40,822
  • 8
  • 72
  • 132
  • `(USHORT)(wcslen(NtPath.Buffer) ) << 1;` must be. without `+1` - the terminated 0 must not be including in length – RbMm Nov 12 '20 at 18:04
  • i mean that `NtPath.Length = (USHORT)(wcslen(NtPath.Buffer) + 1) << 1;` - wrong. and correct must be `NtPath.Length = (USHORT)wcslen(NtPath.Buffer) << 1;` – RbMm Nov 12 '20 at 18:06
  • *and the IO_STATUS_BLOCK structure wants 16 byte alignment.* this is also not true. this is pointer size aligned. 8 or 4 bytes – RbMm Nov 12 '20 at 18:07
  • 2
    in most case most simply use `RtlInitUnicodeString` for object name. for example `RtlInitUnicodeString(&NtPath, L"***");` – RbMm Nov 12 '20 at 18:10
  • @RbMm: I remember having to fix the IO_STATUS_BLOCK alignment. At least one function was really mad about it being only 8 byte aligned. – Joshua Nov 12 '20 at 18:18
  • about 16 byte align iosb - this is 100% not true. if this structure need be 16 byte aligned - it will be declared with `DECLSPEC_ALIGN(16)`, like `SLIST_ENTRY` for example. i am almost every day use `IO_STATUS_BLOCK` many years. and this structure exactly not need more then native align on pointer size. i think your problem was not in iosb align but in something else. without additional info not possible say more – RbMm Nov 12 '20 at 18:23
  • Well then, how do I align it? Do I need to place "__declspec(align(0x8)) in front of it? – Yung Lew Nov 12 '20 at 19:50
  • @YungLew: I fixed it by allocating it on the heap. – Joshua Nov 12 '20 at 19:57
  • `IO_STATUS_BLOCK` is already suitably aligned without you doing anything. It's first member is a union that contains a pointer, causing the entire structure to inherit at least pointer alignment requirements. – IInspectable Nov 12 '20 at 21:22