Uniformity of file paths in kernel-mode

Dear board writers !

I’m using PsSetCreateProcessNotifyRoutineEx and a minifilter to restrict access to certain kind of files/pcoesses. When my callback of process creation is triggered, the file path received in parameter has the form of something like ??\C:\Users\root\Desktop\Service.exe. When one of the callbacks of the minifilter is triggered, I use the function FltGetFileNameInformation to retrieve the path of the file, which has the form of \Device\HarddiskVolume4\Users\root\Desktop\Service.exe.

Is there an idiomatic way to represent file paths kernel-side ? How can I unify those two data sources to have a same kind of path formatting ?

Thanks for your help !

\??\c: is a symbolic link. There used to be (and may still be) a program called ObjDir to help you understand all that stuff.

Pragmatically the easiest way is to open the file, normalize the name and take what the filter manager gives you.

You might also want to worry about volume guids which are persistent.

1 Like

One way is to open and query the symbolic link with ZwOpenSymbolicLinkObject/ZwQuerySymbolicLinkObject. Another way is to get a handle to the new process and call ZwQueryInformationProcess to get the physical path.

Bill Wandel

1 Like

Hey, many thanks for your answers!

I need the physical path when the callback of PsSetCreateProcessNotifyRoutineEx is triggered, so I can add the process in a collection. As this callback occurs before the finalization of the process creation, ZwQueryInformationProcess does not work unfortunately.

After your suggestion I tried the program WinObj and effectively, it provides a nice GUI to visualize those paths! I tried to convert the symbolic link into its physical path using ZwOpenSymbolicLinkObject/ZwQuerySymbolicLinkObject, but I cannot make it work for a path with the format **??**. Here is the code:

		OBJECT_ATTRIBUTES  objAttr;
		HANDLE f;

		InitializeObjectAttributes(&objAttr, (PUNICODE_STRING)CreateInfo->ImageFileName,
			OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);

		NTSTATUS status = ZwOpenSymbolicLinkObject(&f, GENERIC_READ, &objAttr);

Unfortunately, ZwOpenSymbolicLinkObject returns STATUS_OBJECT_TYPE_MISMATCH. The image file name is equal to ??\C:\Windows\system32\notepad.exe. I tried to use a static string like \SystemRoot and it works. I guess it is something related with my symbolic path ?

@Rod: Do you mean I should rather rely on a volume GUID than storing the first part of the path (\Device\HarddiskVolume4 for example) ?

Thanks for your help !

Actually ZwQueryInformationProcess does work.
Use ObOpenObjectByPointer with the supplied EPROCESS. Use the resulting handle in ZwQueryInrormationProcess.

Bill Wandel

1 Like

Do you mean I should rather rely on a volume GUID than storing the first part of the path (\Device\HarddiskVolume4 for example) ?

I mean that you might want to think about it, depending on your precise requirements…

Mr Wandel,

You ended hours of headaches with a single function, THANK YOU !

My error is that I was passing the process id as an argument to ZwQueryInformationProcess instead of a real handle of the proces (!!).

Thanks again and enjoy your weekend <3

You can also call FltGetFileNameInformationUnsafe on CreateInfo->FileObject. This gives you the ability to normalize the path using standard FltMgr options.