【问题标题】:is ??\c:\windows path legitimate??\c:\windows 路径是否合法
【发布时间】:2014-08-27 14:15:32
【问题描述】:

我将检查进程的加载和内存路径以查找恶意进程。例如,如果 csrss.exe 从 windows/system32 以外的其他路径执行,则将被视为恶意。但是对于csrss.exe等常用进程的波动结果如下:

加载路径:\??\C:\WINDOWS\system32\csrss.exe

映射路径:\WINDOWS\system32\csrss.exe

或者对于 sms.exe 我有

加载路径:\SystemRoot\System32\smss.exe

映射路径:\WINDOWS\system32\smss.exe

那么在这两个例子中这两条路径是否相等?即是 \??\C:\WINDOWS==\WINDOWS
或 \SystemRoot\System32 == \WINDOWS\system32

【问题讨论】:

    标签: process operating-system volatility


    【解决方案1】:

    不,据我所知,??\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 的形式出现)......这可能对于取证目的很重要(你引用 ) ,但主要是遗留行为。

    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.)也无法正常创建或操作。

    小实验...

    1. 开始cmd.exe (Win+R)
    2. 转到您的桌面文件夹:cd /d "%USERPROFILE%\Desktop"
    3. 现在创建一个新文件test.txt.(注意尾随点):echo . > \??\%CD%\test.txt.(%CD% 指的是当前目录)
    4. 使用 Windows 资源管理器导航到您的桌面文件夹。尝试通过双击打开文件test.txt.。当它询问您使用什么程序打开它时选择Notepad。
    5. 你应该看到:

      ...请注意路径(不带尾随点)。
    6. 现在尝试从 Windows 资源管理器中删除该文件。它不会工作。
      注意:一些替代文件管理器,如 Far 或 Speed Commander 不会有这个问题!
    7. 现在切换回命令行窗口并使用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 系统编程也有一些细节

    【讨论】:

      猜你喜欢
      • 2010-09-19
      • 2018-06-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-02
      • 1970-01-01
      • 2011-04-24
      • 1970-01-01
      相关资源
      最近更新 更多