不,据我所知,??\C:\...
没有前导的 a\
是无效的。然而,也许有些库会接受它作为输入,并适当地转换它。或者您可能从复制和粘贴的路径中遗漏了一些内容?
无论哪种方式,我们都会坚持(NT 风格的)Windows 行为。
然而,\??\C:\...
绝对是。您可以在此处找到全面的讨论,并在此处找到官方文档。我们需要了解的一些方面也在这里进行了说明。
一些实现细节
引用上面的 Google Project Zero 页面:
Win32 API 区分了 7 种类型的路径,并且可能会使用不同的方式执行不同的操作。NTDLL 有一个函数,
RtlDetermineDosPathNameType_U
给定一个 Unicode 字符串,它将返回路径类型。我们将在下一节中逐一介绍这些类型。以下原型可用于调用此函数:
enum RTL_PATH_TYPE {
RtlPathTypeUnknown,
RtlPathTypeUncAbsolute,
RtlPathTypeDriveAbsolute,
RtlPathTypeDriveRelative,
RtlPathTypeRooted,
RtlPathTypeRelative,
RtlPathTypeLocalDevice,
RtlPathTypeRootLocalDevice
};
RTL_PATH_TYPE NTAPI RtlDetermineDosPathNameType_U(_In_ PCWSTR Path);
接下来,从 Sysinternals/Microsoft 下载 WinObj并启动它(右键单击 +“以管理员身份运行”)。
您可能会看到的潜在有效路径
您有许多路径表示(如链接文章中深入讨论的那样)。C:\Windows\System32\csrss.exe
让我们考虑一下您给出的路径:
- Win32路径:
C:\Windows\System32\csrss.exe
- NT本机路径:
\??\C:\Windows\System32\csrss.exe
\GLOBAL??\C:\Windows\System32\csrss.exe
\SystemRoot\System32\csrss.exe
- 本地设备路径:
\\.\C:\Windows\System32\csrss.exe
- 根本地设备路径:
\\?\C:\Windows\System32\csrss.exe
- DOS 路径:这与单个路径段长于经典 8.3 DOS 路径名称段的所有路径相关。如果已配置,将生成 8.3 DOS 名称(通常以
C:\LongPathName
->的形式出现C:\LONGPA~1
)...这对于取证目的可能很重要(您引用波动性),但主要是遗留行为。
UNC 路径也存在,事实上,本地设备路径 ( )看起来\\.\...
像带有服务器名称的 UNC 路径.
,考虑到当前目录在路径中的位置更靠后,那么为什么不将当前机器放在顶部呢?无论哪种方式,如果您想更详细地了解这些文章,请阅读这些文章。.
从顶部开始,向下钻取
C:\Windows\System32\csrss.exe
当传递给类似 API 时,对象管理器CreateFile
将转换\??\C:\Windows\System32\csrss.exe
为该 API 进行处理。
- 如果给出了相对路径,则基本上会进行额外的处理以转换为完整路径。
\\.\C:\Windows\System32\csrss.exe
当传递给 API 时,CreateFile
将\??\C:\Windows\System32\csrss.exe
在一些处理后“转换”为。就像没有\\.\
前缀一样,在将此路径传递给对象管理器之前会发生一些额外的处理。
\\?\C:\Windows\System32\csrss.exe
当传递给类似 API 时,CreateFile
将“转换”为\??\C:\Windows\System32\csrss.exe
. 在 Win32 级别不会发生进一步的处理。这基本上是一条直接通往对象管理器的逃生路线(在有趣的事实部分,我将分享一个相关的有趣事实)。
对象管理器视图
接收路径之类\??\C:\Windows\System32\csrss.exe
的对象管理器尝试先查找\??
。
\??
曾经是一个实际的项目,现在它是一个“视图”,\GLOBAL??
覆盖了你的特定会话DosDevices
。
- 特定会话的一个示例
DosDevices
是映射网络共享。
- 对于
F:
映射到的驱动器号\\fileserver\Share
- 在后台,您将拥有一个特定于会话的
DosDevices
对象目录\Sessions\0\DosDevices\00000000-00261e8a
,其中包含一个名为F:
、指向\Device\LanmanRedirector\;F:0000000000261e8a\fileserver\Share
... 或类似名称的符号链接。
- 因此,本质上,
\??
在对象管理器中查找名称时,将查看您的会话特定DosDevices
,然后是\GLOBAL??
(或者相反?)
- 另一个例子是 VeraCrypt 安装的卷。例如,您的驱动器号
T:
可能映射到\Device\VeraCryptVolumeT
- 弄清楚我们
C:
的\GLOBAL??\C:
情况后,对象管理器会检查它是什么C:
。在我的 Windows 10 上,它发现这是一个指向\Device\HarddiskVolume3
.
- 找到设备(以及与其关联的驱动程序)后,对象管理器现在将路径的剩余部分(
\Windows\System32\csrss.exe
)传递给设备\Device\HarddiskVolume3
,其驱动程序有望做正确的事情,创建文件对象等等......
现在您知道了这一点,您可以在您的系统上跟踪任意路径。
怎么样\SystemRoot
?
好吧,在现代 Windows 版本上,这种行为与以前略有不同,但\SystemRoot
在我知道的所有基于 NT 的 Windows 版本上,它是一个解析到 Windows 目录的符号链接。Win32 子系统在%SystemRoot%
环境变量中模仿它(尽管在 Win32 路径表示法中)。
在我的 Windows 10\SystemRoot
上是一个符号链接\Device\BootDevice\windows
,因此驱动程序的路径(这是注册表中的典型用例)对于早期启动驱动程序(对象管理器所需的处理更少)可以更容易地表达。
作为旁注:在我的系统上 - 正如你所期望的那样 -\Device\BootDevice
映射到\Device\HarddiskVolume3
.
有趣的事实
- 谷歌零项目文章中引用的
DosDevices
对象目录不再是一个东西。\??
如今,它是指向( not )的符号链接\GLOBAL??
。
subst
命令行实用程序允许您在特定于会话的对象目录中创建符号链接,以DosDevices
将某些目录路径映射到驱动器号(在后台使用DefineDosDevice()
)。
- 文件是未命名的对象,即它们没有可以由 NT 对象管理器直接处理的名称。取而代之的是文件名的其余部分——在重新解析等之后——将被传递给负责表示文件系统卷(即分区)的设备对象的驱动程序。然后,该驱动程序负责理解名称。
\REGISTRY\MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem
(虽然这没有命名文件,但它是您所看到的完全有效的本机路径HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem
那条逃生路线命名\??\
为\\?\
我之前提到过,前缀\??\
是一条逃生路线。考虑一个带有尾随点的文件/文件夹路径,这是您通常无法从 Win32 子系统创建或访问的内容。类似地,保留的 DOS 设备名称(例如NUL
,COM1
等)通常无法创建或操作。
小实验...
- 开始
cmd.exe
(Win+ R)
- 转到您的桌面文件夹:
cd /d "%USERPROFILE%\Desktop"
- 现在创建一个新文件
test.txt.
(注意尾随点):(echo . > \??\%CD%\test.txt.
指%CD%
当前目录)
- 使用 Windows 资源管理器导航到您的桌面文件夹。尝试
test.txt.
通过双击打开文件。Notepad
当它询问您使用什么程序打开它时选择。
- 您应该看到:
...请注意路径(没有尾随点)。
- 现在尝试从 Windows 资源管理器中删除该文件。它行不通。
注意:一些替代文件管理器,如 Far 或 Speed Commander 不会有这个问题!
- 现在切换回命令行窗口并使用
del /f \\?\%CD%\test.txt.
您注意到什么了吗?我偷偷地从 更改\??\
为\\?\
因为显然执行del
不喜欢前者。
根据您的特定程序的实施,它是否成功可能会有所\??\
不同\\?\
。
另一个实验是创建保留名称,如NUL
orCOM1
或修改WSL2 的 per-directory case-sensitive。
笔记
csrss.exe
Win32 我的声音已经过时了,但是 Win32 子系统和通过其子系统 DLL(和朋友)实现的相应“Windows 个性”kernel32.dll
就是这样称呼的。此外,如果您很挑剔,可能会特别困扰您发现现代 x64 Windows 上的所有本机 64 位二进制文件都驻留在%SystemRoot%\System32
(<-是的,那里是 32 位)。享受!
进一步阅读
除了上面的文章,我还可以推荐这些书:
- 显然是 Windows Internals 丛书。
- Pavel Yosifovich 的 Windows 系统编程也有一些细节