1

I am going to check loading and memory path of process to find malicious processes. for example if csrss.exe is executed from other path than Windows\System32 would be considered malicious. But the result of Volatility for common process such as csrss.exe is as follows:

  • loading path : \??\C:\WINDOWS\system32\csrss.exe
  • mapped path : \WINDOWS\system32\csrss.exe

or for smss.exe I have

  • loading path : \SystemRoot\System32\smss.exe
  • mapped path : \WINDOWS\system32\smss.exe

So are these two paths equal in these two examples or not ? I.e. is \??\C:\WINDOWS == \WINDOWS
or \SystemRoot\System32 == \WINDOWS\system32

0xC0000022L
  • 20,597
  • 9
  • 86
  • 152
user2092506
  • 21
  • 1
  • 5

1 Answers1

0

No, a ??\C:\... without the leading \ is not valid, to the best of my knowledge. Perhaps some libraries will accept this as input, however, and convert it appropriately. Or perhaps you missed some bits from the paths you copied and pasted?

Either way we'll stick to the (NT flavored) Windows behavior.

However, \??\C:\... definitely is. You can find a comprehensive discussion here and the official documentation here. Some of the aspects we need to know are also explained here.

Some implementation details

Quoting from the Google Project Zero page above:

There are 7 types of path that the Win32 API distinguishes between, and potentially does different things with. NTDLL has a function, RtlDetermineDosPathNameType_U, which, given a Unicode string will return you the path type. We’ll go through each one of these types in the next section. The following prototype can be used to call this function:

enum RTL_PATH_TYPE {
  RtlPathTypeUnknown,
  RtlPathTypeUncAbsolute,
  RtlPathTypeDriveAbsolute,
  RtlPathTypeDriveRelative,
  RtlPathTypeRooted,
  RtlPathTypeRelative,
  RtlPathTypeLocalDevice,  
  RtlPathTypeRootLocalDevice
};

RTL_PATH_TYPE NTAPI RtlDetermineDosPathNameType_U(_In_ PCWSTR Path);

To follow along, download WinObj from Sysinternals/Microsoft and start it elevated (right-click + "Run as Administrator").

Potentially valid paths you may see

You have a number of path representations (as discussed in-depth in the linked articles). Let's consider the path C:\Windows\System32\csrss.exe you gave:

  • Win32 path: C:\Windows\System32\csrss.exe (\Windows\System32\csrss.exe would be a variation that depends on the current directory at the time the path is processed, if it is somewhere on C: they should be identical)
  • NT native path:
    • \??\C:\Windows\System32\csrss.exe
    • \GLOBAL??\C:\Windows\System32\csrss.exe
    • \SystemRoot\System32\csrss.exe
  • Local device path: \\.\C:\Windows\System32\csrss.exe
  • Root local device path: \\?\C:\Windows\System32\csrss.exe
  • DOS paths: this is relevant for all paths whose individual path segments are longer than the classic 8.3 DOS path name segments. If configured, a 8.3 DOS name will be generated (usually something in the form of C:\LongPathName -> C:\LONGPA~1) ... this may be important for forensic purposes (you quote ), but is mostly legacy behavior.

UNC paths also exist and in fact a local device path (\\.\...) looks like a UNC path with server name . which could even be a thing, considering . is the current directory further down in paths, so why not the current machine up top? Either way, go read the articles if you want to know about those in more detail.

Starting at the top, drilling down

  • C:\Windows\System32\csrss.exe when passed to an API like CreateFile will be converted to \??\C:\Windows\System32\csrss.exe which the object manager then takes in for processing.
    • If a relative path was given, there will be additionally processing to convert to a full path, basically.
  • \\.\C:\Windows\System32\csrss.exe when passed to an API like CreateFile will be "converted" to \??\C:\Windows\System32\csrss.exe after some processing. Just like without the \\.\ prefix some additional processing happens before this path is passed down to the object manager.
  • \\?\C:\Windows\System32\csrss.exe when passed to an API like CreateFile will be "converted" to \??\C:\Windows\System32\csrss.exe. No further processing happens at the Win32 level. This is basically an escape route straight to the object manager (and in the Fun facts section I'll share a related fun fact).

The object manager view

Receiving a path like \??\C:\Windows\System32\csrss.exe the object manager attempts to find \?? first.

  • \?? used to be an actual item, these days it is a "view" of \GLOBAL?? overlaid with your session-specific DosDevices.
    • An example of session-specific DosDevices would be mapped network shares.
      • For a drive letter F: mapped to \\fileserver\Share
      • Under the hood you will have a session-specific DosDevices object directory like \Sessions\0\DosDevices\00000000-00261e8a which would contain a symbolic link named F:, pointing to \Device\LanmanRedirector\;F:0000000000261e8a\fileserver\Share ... or similar.
    • So in essence when looking up names in \?? the object manager will look in your session specific DosDevices, followed by \GLOBAL?? (or was it the other way around? )
    • Another example would be VeraCrypt mounted volumes. For example your drive letter T: may map to \Device\VeraCryptVolumeT
  • Having figured out that C: is \GLOBAL??\C: in our case, the object manager checks what C: is. On my Windows 10 it figures out that this is a symbolic link pointing to \Device\HarddiskVolume3.
  • Having found the device (and implicitly the driver associated with it) the object manager now will pass the remainder of the path (\Windows\System32\csrss.exe) to the device \Device\HarddiskVolume3, whose driver will hopefully do the right thing, create a file object and so on ...

And now that you know this you can follow along on your system for arbitrary paths.

What about \SystemRoot?

Well, on modern Windows versions the behavior differs a little from how it used to be, but \SystemRoot is a symbolic link resolving to the Windows directory on all NT-based Windows versions I am aware of. The Win32 subsystem parrots this in the %SystemRoot% environment variable (albeit in Win32 path notation).

On my Windows 10 \SystemRoot is a symbolic link to \Device\BootDevice\windows and so the path to a driver (which is the typical use case in the registry) can be expressed much more easily for early boot drivers (less processing needed by the object manager).

As a side note: on my system - as you'd expect - \Device\BootDevice maps to \Device\HarddiskVolume3.

Fun facts

  • The DosDevices object directory cited in the Google Project Zero article is no longer a thing. These days it's a symbolic link to \?? (not \GLOBAL??).
  • The subst command line utility allows you to create symbolic links inside your session-specific DosDevices object directory to map some directory path to a drive letter (under the hood uses DefineDosDevice()).
  • Files are unnamed objects, that is they have no name that could be directly processed by the NT object manager. Instead the remainder of a file name - after reparsing etc - will be passed to the driver responsible for the device object representing the file system volume (i.e. partition). That driver then takes care of making sense of the name.
  • \REGISTRY\MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem (while this doesn't name a file, it is a perfectly valid native path to what you would see as HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem

That escape routes named \??\ and \\?\

I mentioned before that the prefix \??\ is an escape route. Consider a file/folder path with a trailing dot, something you will not be able to create or access ordinarily from the Win32 subsystem. Similarly the reserved DOS device names (e.g. NUL, COM1 etc.) cannot be created or manipulated ordinarily.

Little experiment ...

  1. start cmd.exe (Win+R)
  2. go to your desktop folder: cd /d "%USERPROFILE%\Desktop"
  3. Now create a new file test.txt. (note the trailing dot): echo . > \??\%CD%\test.txt. (the %CD% refers to the current directory)
  4. Use Windows Explorer to navigate to your desktop folder. Try to open the file test.txt. by double-clicking. Pick Notepad when it asks you what program to use to open it.
  5. You should see:
    Error message from Notepad
    ... please note the path (without trailing dot).
  6. Now try to delete the file from Windows Explorer. It won't work.
    NB: Some alternative file managers like Far or Speed Commander won't have trouble with this!
  7. Now switch back to the command line window and use del /f \\?\%CD%\test.txt.
    Did you notice something? I sneakily changed from \??\ to \\?\ because apparently the implementation of del doesn't like the former.

Depending on the implementation of your specific program it can vary whether \??\ or \\?\ is successful.

Another experiment would be to create reserved names like NUL or COM1 or tinker with WSL2's per-directory case-sensitivity.

Note

  • Win32 may sound outdated, but the Win32 subsystem and the respective "Windows personality" implemented through csrss.exe and its subsystem DLLs (kernel32.dll and friends) was called just that. Besides, if you're picky it may bother you particularly to find out that all the native 64-bit binaries on a modern x64 Windows reside in %SystemRoot%\System32 (<- yes, that's a 32 right there ). Enjoy!

Further reading

In addition to the articles from the top, I can recommend these books:

  • Obviously the Windows Internals book series.
  • Windows System Programming by Pavel Yosifovich also has some details
0xC0000022L
  • 20,597
  • 9
  • 86
  • 152