NtOpenFile with error STATUS_ACCESS_VIOLATION

Ask your beginner questions here.
Post Reply
Li Yong
Posts: 28
Joined: Sun Feb 18, 2018 9:49 pm

NtOpenFile with error STATUS_ACCESS_VIOLATION

Post by Li Yong » Sun Apr 01, 2018 1:53 pm

I have this following code, but i'm with trouble of AV in NtOpenFile() (of HandleFile(POBJECT_ATTRIBUTES poa) ) returning 0xC0000005 STATUS_ACCESS_VIOLATION.

Follows: DbgPrint + complete code (tested on Win 7 x86 inside a VirtualBox, listing folders/files of Windows Media Player (off) ).

PS: usermode application sends path name to driver.

How solve?

Image

Code: Select all

#include <ntifs.h>
#include <WinDef.h>

#define ALLOCSIZE PAGE_SIZE

//#define _REAL_DELETE_

#ifdef _REAL_DELETE_
#define USE_DELETE_ON_CLOSE FILE_DELETE_ON_CLOSE
#define FILE_ACCESS FILE_GENERIC_READ|DELETE
#else
#define USE_DELETE_ON_CLOSE FILE_DIRECTORY_FILE
#define FILE_ACCESS FILE_GENERIC_READ
#endif

#define echo(x) x 
#define label(x) echo(x)__LINE__ 
#define RTL_CONSTANT_STRINGW(s) { sizeof( s ) - sizeof( (s)[0] ), sizeof( s ),(PWSTR)(s) } 
#define STATIC_UNICODE_STRING(name, str) static const WCHAR label(__)[] = L##str; static const UNICODE_STRING name = RTL_CONSTANT_STRINGW(label(__))
#define STATIC_OBJECT_ATTRIBUTES(oa, name) STATIC_UNICODE_STRING(label(m), name); static OBJECT_ATTRIBUTES oa = { sizeof oa, 0, (PUNICODE_STRING)&label(m), OBJ_CASE_INSENSITIVE }

NTKERNELAPI NTSTATUS ZwQueryDirectoryFile(IN HANDLE FileHandle, 
										  IN HANDLE Event OPTIONAL, 
										  IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, 
										  IN PVOID ApcContext OPTIONAL, 
										  OUT PIO_STATUS_BLOCK IoStatusBlock, 
										  OUT PVOID FileInformation, 
										  IN ULONG Length, 
										  IN FILE_INFORMATION_CLASS FileInformationClass, 
										  IN BOOLEAN ReturnSingleEntry, 
										  IN PUNICODE_STRING FileName  OPTIONAL, 
										  IN BOOLEAN RestartScan);

NTSYSCALLAPI NTSTATUS NTAPI NtClose(HANDLE);

TSTATUS HandleFile(POBJECT_ATTRIBUTES poa, UNICODE_STRING us)
{
	IO_STATUS_BLOCK iosb;
	HANDLE hFile;
	NTSTATUS status;

	DbgPrint("FileName....: %wZ \n", &us);

	if (0 <= (status = NtOpenFile(&hFile, FILE_READ_ATTRIBUTES, poa, &iosb, FILE_SHARE_VALID_FLAGS, 0)))
	{
		NtClose(hFile);
	}

	DbgPrint("NtOpenFile(): 0x%X \n", status);

	return status;
}

void ntTraverse(POBJECT_ATTRIBUTES poa, ULONG FileAttributes, int nLevel, PSTR prefix)
{

	if (IoGetRemainingStackSize() < PAGE_SIZE)
	{
		DbgPrint("no stack!\n");
		return;
	}

	if (!nLevel)
	{
		DbgPrint("!nLevel\n");
		return;
	}

	NTSTATUS status;
	IO_STATUS_BLOCK iosb;
	UNICODE_STRING ObjectName;
	OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, &ObjectName };

	DbgPrint("DIRECTORY...: %s[<%wZ>]\n", prefix, poa->ObjectName);

#ifdef _REAL_DELETE_
	if (FileAttributes & FILE_ATTRIBUTE_READONLY)
	{
		if (0 <= ZwOpenFile(&oa.RootDirectory, FILE_WRITE_ATTRIBUTES, poa, &iosb, FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT))
		{
			FILE_BASIC_INFORMATION fbi = { 0 };
			fbi.FileAttributes = FILE_ATTRIBUTE_NORMAL;

			ZwSetInformationFile(oa.RootDirectory, &iosb, &fbi, sizeof(fbi), FileBasicInformation);
			NtClose(oa.RootDirectory);
		}
	}
#endif

	if (0 <= (status = ZwOpenFile(&oa.RootDirectory, FILE_ACCESS, poa, &iosb, FILE_SHARE_VALID_FLAGS,
		FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT | FILE_OPEN_FOR_BACKUP_INTENT | USE_DELETE_ON_CLOSE)))
	{
		if (FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
		{
			PVOID buffer = ExAllocatePoolWithTag(PagedPool, ALLOCSIZE, 'tset');

			if (buffer)
			{
				union Data {
					PVOID pv;
					PBYTE pb;
					PFILE_DIRECTORY_INFORMATION DirInfo;
				};

				union Data data;

				while (0 <= (status = ZwQueryDirectoryFile(oa.RootDirectory, NULL, NULL, NULL, &iosb,
					data.pv = buffer, ALLOCSIZE, FileDirectoryInformation, 0, NULL, FALSE)))
				{

					ULONG NextEntryOffset = 0;

					do
					{
						data.pb += NextEntryOffset;

						ObjectName.Buffer = data.DirInfo->FileName;

						switch (ObjectName.Length = (USHORT)data.DirInfo->FileNameLength)
						{
						case 2 * sizeof(WCHAR) :
							if (ObjectName.Buffer[1] != '.') break;
						case sizeof(WCHAR) :
							if (ObjectName.Buffer[0] == '.') continue;
						}

						ObjectName.MaximumLength = ObjectName.Length;

#ifndef _REAL_DELETE_
						if (data.DirInfo->FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
#endif
						{
							ntTraverse(&oa, data.DirInfo->FileAttributes, nLevel - 1, prefix - 1);
						}
#ifndef _REAL_DELETE_
						else
#endif
						{
							//DbgPrint("%s%8I64u <%wZ>\n", prefix, data.DirInfo->EndOfFile.QuadPart, &ObjectName);
							  HandleFile(&oa, ObjectName);
						}

					} while (NextEntryOffset = data.DirInfo->NextEntryOffset);

					if (ALLOCSIZE - iosb.Information > FIELD_OFFSET(FILE_DIRECTORY_INFORMATION, FileName[256]))
					{
						break;
					}
				}

				ExFreePoolWithTag(buffer, 'tset');

				if (status == STATUS_NO_MORE_FILES)
				{
					status = STATUS_SUCCESS;
				}
			}
		}

		NtClose(oa.RootDirectory);
	}

	if (0 > status)
	{
		DbgPrint("---- %x %wZ\n", status, poa->ObjectName);
	}
}

void ntTraverse_()
{
	char prefix[MAXUCHAR + 1];
	memset(prefix, '\t', MAXUCHAR);
	prefix[MAXUCHAR] = 0;

	STATIC_OBJECT_ATTRIBUTES(oa, "\\??\\C:\\Program Files\\Windows Media Player");
	ntTraverse(&oa, FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_READONLY, MAXUCHAR, prefix + MAXUCHAR);
}

Li Yong
Posts: 28
Joined: Sun Feb 18, 2018 9:49 pm

Re: NtOpenFile with error STATUS_ACCESS_VIOLATION

Post by Li Yong » Mon Apr 02, 2018 1:30 am

Here was my last attempt building complete path to file, but still comes STATUS_ACCESS_VIOLATION.

Code: Select all

UNICODE_STRING MyResultString;
OBJECT_ATTRIBUTES myoa;

...

#ifndef _REAL_DELETE_
else
#endif
{
//DbgPrint("%s%8I64u <%wZ>\n", prefix, data.DirInfo->EndOfFile.QuadPart, &ObjectName);

MyResultString.MaximumLength = poa->ObjectName->Length + ObjectName.Length + 100;
MyResultString.Length = poa->ObjectName->Length + ObjectName.Length + 100;
MyResultString.Buffer = ExAllocatePoolWithTag(NonPagedPool, poa->ObjectName->Length + ObjectName.Length + 100, 'TAG');

if (MyResultString.Buffer != NULL) 
{

	RtlCopyUnicodeString(&MyResultString, poa->ObjectName); // DIRECTORY

	status = RtlAppendUnicodeToString(&MyResultString, L"\\"); // DIRECTORY + "\"

	if (!NT_SUCCESS(status)) 
	{
		DbgPrint("RtlAppendUnicodeToString() STATUS...: 0x%X", status);
		ExFreePoolWithTag(MyResultString.Buffer, 'TAG');
		return;
	}
	
	status = RtlUnicodeStringCat(&MyResultString, &ObjectName); // DIRECTORY + FileName.extension

	if (!NT_SUCCESS(status))
	{
		DbgPrint("RtlUnicodeStringCat() STATUS...: 0x%X", status);
		ExFreePoolWithTag(MyResultString.Buffer, 'TAG');
		return;
	}

	InitializeObjectAttributes(&myoa, &MyResultString, OBJ_KERNEL_HANDLE|OBJ_CASE_INSENSITIVE, NULL, NULL);

	HandleFile(&myoa, MyResultString);
	ExFreePoolWithTag(MyResultString.Buffer, 'TAG');
}
else 
{
	DbgPrint("Failed to alloc memory to ResultString");
	ExFreePoolWithTag(MyResultString.Buffer, 'TAG');
	return;
}
}
You do not have the required permissions to view the files attached to this post.

User avatar
EP_X0FF
Global Moderator
Posts: 4812
Joined: Sun Mar 07, 2010 5:35 am
Location: Russian Federation
Contact:

Re: NtOpenFile with error STATUS_ACCESS_VIOLATION

Post by EP_X0FF » Mon Apr 02, 2018 4:25 am

Try ZwOpenFile instead.
Ring0 - the source of inspiration

Li Yong
Posts: 28
Joined: Sun Feb 18, 2018 9:49 pm

Re: NtOpenFile with error STATUS_ACCESS_VIOLATION

Post by Li Yong » Mon Apr 02, 2018 11:19 am

EP_X0FF wrote:
Mon Apr 02, 2018 4:25 am
Try ZwOpenFile instead.
ZwOpenFile also not works, already tested, but thank you by suggestion.

User avatar
EP_X0FF
Global Moderator
Posts: 4812
Joined: Sun Mar 07, 2010 5:35 am
Location: Russian Federation
Contact:

Re: NtOpenFile with error STATUS_ACCESS_VIOLATION

Post by EP_X0FF » Mon Apr 02, 2018 11:55 am

I don't know from where you copy-pasted this piece of code but it clearly not something you should use if you are unable to set a few breakpoints in it and look what is passed to the API.
If you ask me, then I tried it ported to usermode (replaced ExAlloc/Free with VirtualAlloc/Free), and with small tweaks (adding missing declarations) - it works. I would not discuss if this code is "great" or fucked up. It just works even if it looks like shit tbh, however I would never write this in _that_ unfriendly way and there is no difference in case of complier/API usage optimization and result.

The status STATUS_ACCESS_VIOLATION is because Nt routine failed to validate pointer you gave to it, because you are mixing Nt/Zw calls in your code without real understanding difference between them and what is the point anyway, in driver use Zw, in user mode Nt (to clearly divide where what code used). You don't need this mix in driver (unless you are doing some extraordinary things and system hacks) and it makes code look like a mozaic shit.
Last edited by EP_X0FF on Mon Apr 02, 2018 12:09 pm, edited 1 time in total.
Reason: edit: typo
Ring0 - the source of inspiration

Li Yong
Posts: 28
Joined: Sun Feb 18, 2018 9:49 pm

Re: NtOpenFile with error STATUS_ACCESS_VIOLATION

Post by Li Yong » Mon Apr 02, 2018 1:08 pm

EP_X0FF, i changed all Nt calls to Zw and works fine now! thank you very much.

User avatar
Vrtule
Posts: 461
Joined: Sat Mar 13, 2010 9:14 pm
Location: Czech Republic
Contact:

Re: NtOpenFile with error STATUS_ACCESS_VIOLATION

Post by Vrtule » Mon Apr 02, 2018 4:57 pm

Hello,
I am not sure if this is the case, but if you calling NtOpenFile in your driver as a reaction to an IOCTL from your application, you need to pass usermode buffers to it, otherwise, the checks made by the routine fail.

Or use ZwOpenFile instead, as EP is suggesting. If it does not work for you either, it may return a different error (since it does not perform the checks NtOpenFile does).

Li Yong
Posts: 28
Joined: Sun Feb 18, 2018 9:49 pm

Re: NtOpenFile with error STATUS_ACCESS_VIOLATION

Post by Li Yong » Mon Apr 02, 2018 11:00 pm

VrTule, ZwOpenFile solved the trouble. Thank you.

Post Reply