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