不,据我所知,??\C:\... 没有前导 \ 无效。然而,也许有些库会接受它作为输入,并适当地转换它。或者您在复制和粘贴的路径中遗漏了一些内容?
无论哪种方式,我们都会坚持(NT 风格的)Windows 行为。
但是,\??\C:\... 绝对是。您可以找到a comprehensive discussion here 和the official documentation here。我们需要知道的一些方面也是explained here。
一些实现细节
引用the Google Project Zero page above:
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);
接下来,download WinObj from Sysinternals/Microsoft 并启动它(右键单击 +“以管理员身份运行”)。
您可能会看到的潜在有效路径
您有许多路径表示(如链接文章中深入讨论的那样)。让我们考虑一下您提供的路径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 的形式出现)......这可能对于取证目的很重要(你引用 volatility) ,但主要是遗留行为。
UNC 路径也存在,事实上,本地设备路径 (\\.\...) 看起来像服务器名称为 . 的 UNC 路径,考虑到 . 是当前目录在路径的下方,那么为什么不是当前机器在顶部呢?无论哪种方式,如果您想更详细地了解这些文章,请阅读文章。
从顶部开始向下钻取
-
C:\Windows\System32\csrss.exe 当传递给像CreateFile 这样的API 时,将被转换为\??\C:\Windows\System32\csrss.exe,然后对象管理器将其用于处理。
- 如果给出了相对路径,则基本上会进行额外处理以转换为完整路径。
-
\\.\C:\Windows\System32\csrss.exe 当传递给像CreateFile 这样的API 时,经过一些处理后将“转换”为\??\C:\Windows\System32\csrss.exe。就像没有 \\.\ 前缀一样,在将此路径传递给对象管理器之前会发生一些额外的处理。
-
\\?\C:\Windows\System32\csrss.exe 当传递给像 CreateFile 这样的 API 时,将被“转换”为 \??\C:\Windows\System32\csrss.exe。在 Win32 级别不会发生进一步的处理。这基本上是一条直接通往对象管理器的逃生路线(在有趣的事实部分,我将分享一个相关的有趣事实)。
对象管理器视图
对象管理器收到\??\C:\Windows\System32\csrss.exe 之类的路径后,首先尝试查找\??。
-
\?? 曾经是一个实际项目,现在它是 \GLOBAL?? 的“视图”,上面覆盖了特定于会话的 DosDevices。
- 会话特定
DosDevices 的一个示例是映射网络共享。
- 对于映射到
\\fileserver\Share 的驱动器号 F:
- 在后台,您将拥有一个特定于会话的
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。
趣事
- Google 零项目文章中引用的
DosDevices 对象目录已不再存在。现在它是\?? 的符号链接(不是 \GLOBAL??)。
-
subst 命令行实用程序允许您在特定于会话的 DosDevices 对象目录中创建符号链接,以将某些目录路径映射到驱动器号(在后台使用 DefineDosDevice())。
- 文件是未命名的对象,即它们没有可以由 NT 对象管理器直接处理的名称。相反,文件名的其余部分 - 在重新解析等之后 - 将传递给负责表示文件系统卷(即分区)的设备对象的驱动程序。然后,该驱动程序负责理解名称。
-
\REGISTRY\MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem(虽然它没有命名 文件,但它是您所看到的 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem 的完全有效的本地路径
名为\??\ 和\\?\ 的逃生路线
我之前提到前缀\??\ 是一条逃生路线。考虑一个带有尾随点的文件/文件夹路径,这是您通常无法从 Win32 子系统创建或访问的内容。同样the reserved DOS device names (e.g. NUL, COM1 etc.)也无法正常创建或操作。
小实验...
- 开始
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 或 COM1 或修改 WSL2's per-directory case-sensitivity。
注意
- Win32 我的声音已经过时了,但是 Win32 子系统和通过
csrss.exe 及其子系统 DLL(kernel32.dll 和朋友)实现的相应“Windows 个性”就是这样称呼的。此外,如果您很挑剔,可能会特别困扰您发现现代 x64 Windows 上的所有本机 64 位二进制文件都位于 %SystemRoot%\System32(
进一步阅读
除了上面的文章,我还可以推荐这些书:
- 显然是 Windows Internals 丛书。
- Pavel Yosifovich 的 Windows 系统编程也有一些细节