当前位置: 首页 > news >正文

剑和沙盒 3 - 深度使用和解析Windows Sandbox

介绍

两年前,微软作为Insiders build 18305的一部分发布了一项新功能- Windows Sandbox。

该沙箱具有一些有用的规格:

  • Windows 10(Pro/Enterprise)的集成部分。
  • 在 Hyper-V 虚拟化上运行。
  • 原始且可抛弃 – 每次运行时都干净地开始并且没有持久状态。
  • 可通过具有专用格式(WSB 格式)的配置文件进行配置。您可以配置网络、vGPU、映射文件夹、用户登录时运行的自动脚本以及许多其他选项。
  • 该部署基于 Windows Containers 技术。

微软实现了一个重大的技术里程碑。由此产生的沙盒兼具了两方面的优点:一方面,沙盒基于 Hyper-V 技术,这意味着它继承了 Hyper-V 严格的虚拟化安全性。另一方面,沙盒包含多项功能,允许与主机共享资源以减少 CPU 和内存消耗。

其中一个有趣的特征特别重要,我们将在这里详细说明。

动态生成的图像

客户磁盘和文件系统是动态创建的,并使用主机文件系统中的文件实现。

图 1 – 动态生成的图像(来自 Microsoft 官方文档)。

出于多种原因,我们决定深入研究这项技术。

  • 缺乏关于其内部技术细节的文档,无论是官方文档还是社区文档。虽然它结合了两种广泛记录的技术(Windows 容器和 Hyper-V),但我们仍然不知道它们是如何协同工作的。例如,技术博客提到了Windows 容器技术,但在官方文档中,Windows 容器的创建和管理是使用 Windows 的Docker实用程序完成的,而 Windows Sandbox 中并未使用该实用程序。
  • 不幸的是,除了调整 WSB 文件之外,微软不允许对沙盒进行任何自定义。这意味着我们无法安装任何需要重新启动的程序,也无法为沙盒创建自己的基础映像。

在本文中,我们将分解动态图像功能的多个组件、执行流程、驱动程序支持和实现设计。我们展示了其中涉及的几种内部技术,例如 NTFS 自定义重新解析标记、VHDx 分层、用于正确隔离的容器配置、虚拟存储驱动程序、VMBus 上的 vSMB 等。我们还创建了一个自定义FLARE VM沙盒用于恶意软件分析,其启动时间仅为 10 秒。

通用组件

Hyper-V 及其模块的复杂生态系统已经得到了广泛的研究。发现了几个漏洞,例如下一个 VmSwitch RCE,它可能导致完全的客户机到主机逃逸。几年前,微软推出了 Windows 容器(主要用于服务器),该功能允许在 Windows 上本地运行 Docker,以简化软件部署。

这两项技术也以两个组件的形式引入了 Windows 10 端点平台:WDAG(Windows Defender 应用程序防护)以及最近的Windows Sandbox。最近,WDAG 和另一项令人兴奋的 Office 隔离功能合并为MDAG – Microsoft Defender 应用程序防护。  

POC2018大会上,张云海做了一个演讲,深入介绍了 WDAG 的架构和内部原理。正如我们所展示的,Windows Sandbox 的底层实现采用了相同的技术。

沙箱可以分为三个组件:两个服务——CmService.dllvmcompute.exe——以及创建的工作进程vmwp.exe

图 2 – Windows Sandbox 通用组件

准备沙箱

每个基于 Hyper-V 的虚拟机背后都有一个VHDx文件,即机器使用的虚拟磁盘。为了了解磁盘是如何创建的,我们查看了一个正在运行的沙箱的工作文件夹:%PROGRAMDATA%\Microsoft\Windows\Containers。令人惊讶的是,我们发现了 8 个以上的 VHDx 文件。

图 3 – 工作文件夹结构。

我们可以通过下一个路径中的动态大小来跟踪主 VHDx 文件 –Sandboxes\29af2772-55f9-4540-970f-9a7a9a6387e4\sandbox.vhdx其中 GUID 是在每次沙盒运行时随机生成的。

当我们手动挂载 VHDx 文件时,我们发现它的大部分文件系统都丢失了(这种现象在前面提到的张的 WDAG 研究中也能看到)。

图 4 – 安装的沙盒 VHDx。

我们可以立即看到文件夹图标上的“ X ”符号。如果我们打开文件资源管理器中的“属性”列,我们可以看到两个不寻常的 NTFS 属性。这些解释如下:

O——离线

L——重新解析点

重新解析点是 NTFS 的一个扩展,允许它创建指向另一条路径的“链接”。它还在其他功能中发挥作用,例如卷安装。在我们的例子中,使用此功能是有意义的,因为大多数文件并非“物理”存在于 VHDx 文件中。

为了了解重新解析指向的位置以及其中的内容,我们深入研究了 NTFS 结构。

解析MFT记录

主文件表( MFT) 存储从 NTFS 分区检索文件所需的信息。一个文件可能有一个或多个 MFT 记录,并且可以包含一个或多个属性。我们可以运行流行的取证工具Volatility,并可以mftparser选择解析底层文件系统中的所有 MFT 记录。这可以使用以下命令行完成:

volatility.exe -f sandbox.vhdx mftparser --output=body -D output --output-file=sandbox.body

当我们kernel32.dll在输出中搜索(示例系统文件)记录时,我们遇到以下文本:
0| [ MFT FILE_NAME ] Windows\System32\kernel32. dll (偏移量:0x3538c00 )| 1251 |---a---S--o----| 0 | 0 | 764456 | 1604310972 | 1596874670 | 1603021550 | 1596874670
0 | [ MFT STD_INFO ] Windows\System32\kernel32. dll (偏移量:0x3538c00 )| 1251 |---a---Sr-o----| 0 | 0 | 764456 | 1606900209 | 1596874670 | 1603021550 | 1596874670

我们可以看到与之前类似的重新解析(“ S ”)和离线(“ o0x3538c00 ”)属性,但 Volatility 没有提供任何其他信息。我们可以使用 MFT 记录的偏移量来启动我们自己的手动解析。

我们使用下一个 NTFS 文档来执行解析过程。我们没有提供 MFT 格式的完整规范,但简单地说,MFT 记录包含可变数量的属性,每个属性都有自己的标头和有效负载。我们正在寻找$REPARSE_POINT由序数 标识的属性0xC0

图 5 – MFT 属性头结构。

图 6 –$REPARSE_POINT属性有效载荷结构。

我们对上面列出的结构进行解析,得到以下数据:
$REPARSE_POINT 属性
--------------- 属性标题 ---------------
C0 00 00 00 -类型($REPARSE_POINT )
78 00 00 00 - 长度
00—— 非居民旗帜
00—— 名称长度
00 00 - 名称偏移量
00 00—— 旗帜
03 00 - 属性ID (a )
5C 00 00 00 -属性的长度
18 00 - 属性偏移量
00—— 索引标志
00—— 填充
---------------- 属性数据 ----------------
18 10 00 90 - 重新解析标签
54 00 - 重新解析数据长度
00 00—— 填充
----------------- 重新解析数据 -----------------
01 00 00 00-版本?
00 00 00 00——保留?
77 F6 64 82 B0 40 A5 4C BF 9A 94 4A C2 DA 80 87 - 参考 GUID
3A 00 - 路径字符串大小
57 00 69 00 6E 00 64 00 6F 00 77 00 73 00 5C 00
53 00 79 00 73 00 74 00 65 00 6D 00 33 00 32 00
5C 00 6B 00 65 00 72 00 6E 00 65 00 6C 00 33 00
32 00 2E 00 64 00 6C 00 6C 00 - 路径字符串

一些重要说明:

  • 我们没有找到有关微软重新解析数据结构的任何公开文档,但进行逆向工程并不太难。
  • 重新解析标签在此处0x90001018定义如下:IO_REPARSE_TAG_WCI_1
“由 Windows 容器隔离过滤器使用。仅供服务器端解释,无意义。”
  • 在这项研究中对 Windows 模块进行逆向工程时,我们多次发现引用的 GUID77 F6 64 82 B0 40 A5 4C BF 9A 94 4A C2 DA 80 87是硬编码值。此值表示对主机基础层的引用,我们稍后会讨论它。
  • 重新解析数据中的路径显示了我们的示例文件的相对路径:Windows\System32\kernel32.dll

根据以上信息,我们可以得出结论,文件是由底层文件系统“链接”的(可能是链接到指定的 FS 过滤器),但许多问题仍然没有答案:VHDx 是如何构建的,其他 VHDx 的用途是什么,以及哪个组件负责链接到主机文件。

VHDx 分层

如果我们在沙箱创建期间跟踪Procmon日志,我们会注意到一系列 VHDx 访问尝试:

图 7 – VHDx 分层引线。

虽然第一个是我们之前解析过的“真实” VHDx,但后面还有 3 个其他 VHDx 访问。我们怀疑 Microsoft 对虚拟磁盘模板使用了某种分层。

通过使用二进制编辑器检查 VHDx 文件,可以轻松验证我们的理论:

图 8 – parent_linkage010 编辑器中的标签。

VHDx 格式的父定位器可以使用多种方法给出:绝对路径、相对路径和卷路径。文档可在此处找到。

有了这些知识,我们可以构建下一层:

  • Sandboxes\<new_sandbox_guid>\sandbox.vhdx– “真正的” VHDx。
  • Sandboxes\<constant_guid_per_installation>\sandbox.vhdx– 每个沙箱安装创建一次。
  • BaseImages\0949cec7-8165-4167-8c7d-67cf14eeede0\Snapshot\SnapshotSandbox.vhdx– 可能与基础层快照相关。
  • PortableBaseLayer\SystemTemplateBase.vhdx– 基础模板。

当我们浏览这些虚拟磁盘时,我们注意到文件仍然丢失;一些系统文件夹是空的,以及用户/程序文件和其他各种文件的文件夹。

使用 Procmon 让我们了解到缺少另一个重要层:操作系统基础层。

操作系统基础层

操作系统基础层主文件位于下一个路径的沙盒工作文件夹中:BaseImages\0949cec7-8165-4167-8c7d-67cf14eeede0\BaseLayer.vhdx。通过 Procmon 查看安装过程,我们可以看到下一个.wim(Windows 映像格式)文件C:\Windows\Containers\serviced\WindowsDefenderApplicationGuard.wim被提取到PortableBaseLayer同名文件夹中,并被复制并重命名到上面的基础层文件中。这又显示了 WDAG 和 Windows Sandbox 之间的另一个相似之处。

当我们浏览BaseLayer.vhdx磁盘时,我们可以看到创建的沙箱的完整结构,但系统文件仍然“物理”缺失。像kernel32.dll我们之前所做的那样解析 MFT 记录会产生相同的$REPARSE_POINT属性,但标签不同:0xA0001027IO_REPARSE_TAG_WCI_LINK_1记住这个标签以备后用。

图 9 – 基础层用户文件夹。

此外,当我们运行mountvol命令时,我们会看到基础层 VHDx 被挂载到其所在的同一目录中:

图 10 – 已安装的操作系统基础层。

负责安装该卷的服务以及我们到目前为止提到的所有功能都是容器管理服务 CmService.dll

此服务运行一个名为的可执行文件cmimageworker.exe,并使用下一个命令行参数之一expandpbl/deploy/clean来执行这些操作。

图 11 —CmService基础层创建。

computestorage!HcsSetupBaseOSLayer我们可以在 中观察到对 的调用cmimageworker.exe,以及在 中基础层的实际创建部分computestorage.dll

图 12 –cmimageworker!Container::Manager::Hcs::ProcessImage启动基础层创建。

图 13 – 中基础层创建的一部分computestorage!OsImageUtilities::ProcessOsLayer

微软就沙盒发表了以下声明:

Windows 的一部分– 此功能所需的一切都随 Windows 10 Pro 和 Enterprise 一起提供。无需下载 VHD!

到目前为止,我们了解了有关该功能的关键实现细节。让我们继续看看容器是如何执行的。

运行沙盒

运行 Windows Sandbox 应用程序会触发执行流程,我们在此不再赘述。我们只提到该流程通过 RPC 调用导致CmService执行。另一项关键服务运行并协调主机上的所有计算系统(容器)。vmcompute!HcsRpc_CreateSystemvmcompute.exe

在我们的例子中,CreateSystem命令还接收描述所需机器的下一个配置 JSON:

注意:为了便于阅读,JSON 已被截断。您可以在附录 A中查看完整的 JSON 。
{
“所有者” :“马德里” ,
...
“虚拟机” :{
...
“设备” :{
“Scsi” :{
“基本的” :{
“附件” :{
"0" :{
“类型” :“虚拟磁盘” ,
“路径” :“C:\\ProgramData\\Microsoft\\Windows\\Containers\\Sandboxes\\025b00c8-849a-4e00-bcb2-c2b8ec698bab\\sandbox.vhdx” ,
...
}
}
}
} ,
...
“虚拟Smb” :{
“分享” :[{
“名称” :“os” ,
“路径” :“C:\\ProgramData\\Microsoft\\Windows\\Containers\\BaseImages\\0949cec7-8165-4167-8c7d-67cf14eeede0\\BaseLayer\\Files” ,
...
}] ,
` } ,
...
} ,
...
“运行在Silo” :{
“SiloBaseOsPath” :“C:\ProgramData\Microsoft\Windows\Containers\BaseImages\0949cec7-8165-4167-8c7d-67cf14eeede0\BaseLayer\Files” ,
“通知SiloJob创建” :true ,
"文件系统层" : [{
“ID” :“8264f677-40b0-4ca5-bf9a-944ac2da8087” ,
"路径" :“C:\\” ,
“路径类型” :“绝对路径”
}]
} ,
...
} ,
...
}

此 JSON 是在 处创建的CmService!Container::Manager::Hcs::Details::GenerateCreateComputeSystemJson。我们未能追踪任何有助于构建该配置的文件。

在开始分析 JSON 中有趣的字段之前,我们想提一下 Palo Alto Networks 的这篇文章。该文章解释了容器内部结构以及JobSilo对象之间的关系。

第一个有趣的配置标签是RunInSilo。此标签触发代码流,vmcompute引导我们进入下一个堆栈跟踪:
3: kd > k
# Child-SP ReAddr 调用站点
00 ffff9a00`8da57648 fffff806`85d2b7fb wcifs!WcPortMessage
01 ffff9a00`8da57650 fffff806`85d63499 FLTMGR!FltpFilterMessage+ 0xdb
... (减少)
0b 0000004d`4218dbf0 00007ffa`08c5363d FLTLIB!FilterSendMessage+ 0x31
0c 0000004d`4218dc40 00007ffa`08c48686 wc_storage!WciSetupFilter+ 0x195
0d 0000004d`4218dcf0 00007ffa` 22e06496 wc_storage!WcAttachFilterEx+ 0x156
0e 0000004d`4218dee0 00007ffa`22de5a66 容器!容器::FilesystemProvider::Setup+ 0x15e
0f 0000004d`4218dfc0 00007ffa`22ded4ad 容器!container_runtime::CreateContainerObject+ 0x106
10 0000004d` 4218e010 00007ffa`22decf3c 容器!容器::CreateContainer+ 0x10d
11 0000004d` 4218e4 a0 00007ff6`fcf0bc7f 容器!WcCreateContainer+ 0x1c
12 0000004d` 4218e4 d0 00007ff6`fcf0c5c4 vmcompute!计算服务::JobUtilities::ConvertJobObjectToContainer+ 0xcb
13 0000004d` 4218e590 00007ff6`fce8573f vmcompute!ComputeService::JobUtilities::CreateSiloForIsolatedWorkerProcess+ 0x4dc
14 0000004d` 4218e8 c0 00007ff6`fce875c5 vmcompute!ComputeService::Management::Details::PrepareJobForWorkerProcess+ 0x17b
15 0000004d` 4218e9 a0 00007ff6`fcee6cbb vmcompute!计算服务::管理::详细信息::ConstructVmWorker+ 0xfd5
... (减少)

从堆栈中,我们可以了解到,每当计算系统收到 Silo 配置时,它都会通过调用创建并配置一个容器container!WcCreateContainer。作为其配置的一部分,它还wcifs.sys通过 与驱动程序进行通信FLTLIB!FilterSendMessage。我们简要介绍一下这个驱动程序及其用途。

第二个有趣的特性是VirtualSmb用于为之前提到的已安装基础层路径创建相应共享的标签。我们稍后也会讨论这一点。

容器隔离

从堆栈跟踪中我们可以看到,容器创建包括\WcifsPort使用wcifs.sys驱动程序Windows Container Isolation FS Filter Driver打开端口上的过滤器通信通道。这是用户模式代码与过滤器驱动程序通信的 常用方法。

此微过滤驱动程序在容器文件系统虚拟化的实现中起着重要作用。此驱动程序在客户机和主机中都充当此角色。

文件系统过滤驱动程序通常非常复杂,这个也不例外。幸运的是, Google Project Zero 的James Forshaw最近写了一篇很棒的文章,解释了 Windows FS 过滤驱动程序的低级设计,这有助于我们理解我们案例中的逻辑。

我们可以将驱动逻辑分为两部分:

  • 驱动程序配置——配置取决于驱动程序是在客户机还是主机系统上运行。
  • 处理操作回调,例如WcPreCreateWcPostCreateWcPreReadWcPostRead。这些回调包含主要逻辑、数据操作和适当的重定向。

我们将解释该驱动程序用来了解沙盒生态系统的一些方法。

初始配置

来宾配置

正如我们之前所说,主机和客户机都使用该驱动程序,但方式不同。

客户机通过注册表接收一组参数,用于其初始配置。其中一些参数位于,HKLM\SYSTEM\CurrentControlSet\Control如下HKLM\SYSTEM\CurrentControlSet\Control\BootContainer所示:

图 14 –HKLM\SYSTEM\CurrentControlSet\Control配置值。

图 15 –HKLM\SYSTEM\CurrentControlSet\Control\BootContainer配置值。

您可能会注意到我们之前在“真实” VHDx 文件中看到的IO_REPARSE_TAG_WCI_1(代码)。此标记与我们在中看到的重新解析标记一起被硬编码到方法中:0x90001018IO_REPARSE_TAG_WCI_LINK_1BaseLayer.vhdxwcifs!WcSetBootConfiguration

图 16 – 中的硬编码重新解析标签值WcSetBootConfiguration

客户机配置的第二个更重要的部分是wcifs!WcSetupVsmbUnionContext,它在其中设置了一个称为Union ContextFltGetInstanceContext的虚拟化层。在后台,驱动程序将自定义数据存储在多个上下文对象上,并使用适当的 NT API( 、PsGetSiloContext和 )访问它们FltGetFileContext。这些自定义对象包含 AVL 树和哈希表,以高效查找虚拟化层。

WcSetupVsmbUnionContext方法还有两个有趣的工件。一个是属于层的 vSMB 路径,另一个是HOST_LAYER_ID我们之前在解析的 MFT 和描述虚拟机的 JSON 中看到的 GUID:

图 17 – 中的硬编码 vSMB 路径WcSetupVsmbUnionContext

图 18 – 的硬编码 GUID HOST_LAYER_ID

随着我们深入研究,我们发现有迹象表明虚拟 SMB方法用于在客户机和主机之间共享文件。很快我们就会发现 vSMB 是基础层实现和映射文件夹共享的主要方法。

主机配置

对于主机系统,主要配置发生在父计算进程vmcompute启动容器创建并向发送自定义消息时\WcifsPort。这会触发wcifs!WcPortMessage发送到该特定端口的任何消息的回调例程。

下面是服务向过滤驱动发送的消息的部分重构:
WcifsPortMsg结构
{
DWORD 消息代码;
DWORD 消息大小;
WcifsPortMsgSetUnion 消息;
} ;

WcifsPortMsgSetUnion结构
{
DWORD 消息版本或代码;
DWORD 消息大小;
DWORD 数字联合;
wchar_t 实例名称[ 50 ] ;
DWORD 实例名称长度;
DWORD 重新解析标签;
DWORD 重新解析标签链接;
DWORD 不确定;
处理工作;
BYTE 上下文数据[ 1 ] ;
} ;

ContextData字段还包含联合应映射的设备路径。

操作回调

在注册期间,过滤驱动程序会为其想要拦截的每项操作提供一组回调。过滤管理器会在每项文件操作之前/之后调用这些回调,如下所示。

图 19 –迷你过滤器架构,由James Forshaw提供。

无需过多探讨技术细节,驱动程序定义并处理两个自定义重新解析标签:

  • IO_REPARSE_TAG_WCI_1 – 这是指示磁盘上的文件实例是虚拟的,真实路径可以在其内部结构中找到的主要标记。此“转换”的示例用法如下:
    • 客户机将文件从其本机路径转换C:\Windows\system32\kernel32.dll为 ​​vSMB 路径\Device\vmsmb\VSMB-{dcc079ae-60ba-4d07-847c-3493609c0870}\os\Windows\System32\kernel32.dll
    • 主机将文件从基础层设备路径转换C:\ProgramData\Microsoft\Windows\Containers\BaseImages\0949cec7-8165-4167-8c7d-67cf14eeede0\BaseLayer\Files\Windows\System32\en-US\apphelp.dll.mui为真实路径C:\Windows\System32\en-US\apphelp.dll.mui
      这种转换非常有趣,因为它主要发生在基础层中包含此重新解析标记的空系统文件夹中(例如文件en-US夹)。
  • IO_REPARSE_TAG_WCI_LINK_1 – 据我们所知,此标签仅在主机上使用,并将系统文件从基础层设备路径链接C:\ProgramData\Microsoft\Windows\Containers\BaseImages\0949cec7-8165-4167-8c7d-67cf14eeede0\BaseLayer\Files\Windows\System32\kernel32.dll到真实路径C:\Windows\System32\kernel32.dll。与上一点相比,此示例 DLL 文件条目确实存在于基础层中,并且具有此重新解析标签。

发现 vSMB 是操作系统基础层共享的主要方法,这令人颇感意外。既然我们知道它是生态系统中一种至关重要的通信方法,那么下一步自然就是进一步深入挖掘。

(v)SMB 文件共享

在沙盒安装过程中,我们注意到通过调用存储提供程序设备vmcompute创建了多个虚拟共享,并发送了 IOCTL 。此类调用的示例路径可能如下所示:。CreateFileW0x240328\??\STORVSP\VSMB\??\C:\ProgramData\Microsoft\Windows\Containers\BaseImages\0949cec7-8165-4167-8c7d-67cf14eeede0\BaseLayer\Files

创建这些共享的方法是vmcompute!ComputeService::Storage::OpenVsmbRootShare。我们可以在下一个堆栈跟踪中看到它的流程:
3: kd > k
# Child-SP ReAddr 调用站点
00 ffff9a00`8d48a178 fffff806`85fd6af8 storvsp!VspFileCreate
01 (内联函数)--------`-------- Wdf01000!FxFileObjectFileCreate::Invoke+ 0x29 [ minkernel\wdf\framework\shared\inc\private\common\ FxFileObjectCallbacks.hpp @ 58 ]
... (减少)
11 0000004d`4210d690 00007ff6`fcf33700 KERNELBASE!CreateFileW+ 0x66
12 0000004d`4210d6f0 00007ff6`fceb8180 vmcompute!计算服务::存储::OpenVsmbRootShare+ 0x3ac
13 0000004d`4210d850 00007ff6`fceba0fc vmcompute!计算服务::虚拟机::详细信息::配置VSMB+ 0x598
14 0000004d`4210da30 00007ff6`fceba908 vmcompute!计算服务::虚拟机::详细信息::初始化设备设置+ 0x918
15 0000004d`4210eb90 00007ff6`fce86abd vmcompute!计算服务::虚拟机::创建虚拟机配置+ 0x68
16 0000004d`4210ebe0 00007ff6`fcee6cbb vmcompute!计算服务::管理::详细信息::ConstructVmWorker+ 0x4cd
... (减少)

此外,当我们使用 WSB 文件配置将主机文件夹映射到客户机时,也会调用相同的方法。例如,映射Sysinternals文件夹会导致对驱动程序的下一个调用:\??\STORVSP\VSMB\??\C:\Users\hyperv-root\Desktop\SysinternalsSuite

通过 (v)SMB 访问文件

创建这些共享后,我们可以通过创建的别名在客户机中访问它们。我们可以使用该type命令打印kernel32.dll主机的以下路径\\.\vmsmb\VSMB-{dcc079ae-60ba-4d07-847c-3493609c0870}\os\Windows\System32\kernel32.dll

图 20 – 访问 vSMB 共享。

为了提供 vSMB 文件,vmusrv作为 VM 工作进程一部分的模块会创建一个工作线程。该模块是一个用户模式 ​​vSMB 服务器,它在例程中直接从 VMBus 请求数据包vmusrv!VSmbpWorkerRecvLoop,然后继续处理这些数据包。

服务创建文件操作

每当vmusrv收到创建SMB 请求时,它都会向存储提供程序驱动程序发起新请求。这样的调用可能如下所示:
2:kd >;k
# Child-SP ReAddr 调用站点
... (减少)
0c ffff9a00`8d9522e0 fffff806`892c4741 storvsp!VspVsmbCommonRelativeCreate+ 0x369
0d ffff9a00`8d952510 fffff806`892c3b7e storvsp!VspVsmbHandleRelativeCreateFileRequest+ 0x321
0e ffff9a00`8d952790 fffff806`892c0f85 storvsp!VspVsmbDispatchIoControlForProcess+ 0x11e
0f ffff9a00`8d9527e0 fffff806` 8100e522 storvsp!VspFastIoDeviceControl+ 0x175
... (减少)
13 000000ae`9c0ff298 00007ffa`110c0c0a ntdll!NtDeviceIoControlFile+ 0x14
14 000000ae`9c0ff2a0 00007ffa`110c0456 vmusrv!CShare::OpenFileRelativeToShareRootInternal+ 0x306
15 000000ae`9c0ff3e0 00007ffa`110b9381 vmusrv!CShare::OpenFileRelativeToShareRoot+ 0x356
16 000000ae`9c0ff510 00007ffa`110b4451 vmusrv!CFSObject::CreateFileW+ 0x185
17 000000ae`9c0ff690 00007ffa`1109a568 vmusrv!CShare::创建+ 0x91
18 000000ae`9c0ff740 00007ffa`1109d74d vmusrv!ProviderCallback_Create+ 0x30
19 000000ae`9c0ff780 00007ffa`1109c299 vmusrv!SrvCreateFile+ 0x331
1a 000000ae`9c0ff860 00007ffa`1109c6f0 vmusrv!Smb2ExecuteCreateReal+ 0x111
1b 000000ae`9c0ff940 00007ffa`110a08da vmusrv!Smb2ExecuteCreate+ 0x30
1c 000000ae`9c0ff970 00007ffa` 11098907 vmusrv!Smb2ExecuteProviderCallback+ 0x7e
1d 000000ae`9c0ff9d0 00007ffa` 11088311 vmusrv!Smb2PacketProcessing+ 0x97
1e 000000ae`9c0ffa40 00007ffa` 11087225 vmusrv!Smb2PacketProcessingCallback+ 0x11
... (减少)

与存储提供程序的通信是通过代码中的IOCTL完成的0x240320,而引用的句柄是在初始化阶段打开的vSMB路径:

图 21 – 引用 IOCTL 的句柄。

如果我们仔细观察storvsp!VspVsmbCommonRelativeCreate,就会发现每次执行后都会调用nt!IoCreateFileEx。此调用包含所需文件的相对路径,以及一个附加RootDirectory字段,该字段表示\Files已安装的基础层 VHDx 中的文件夹:

IoCrateFileEx22 – 执行storvsp.sys

提供读/写操作

中的工作线程执行读/写操作vmusrv!CFSObject::Read/vmusrv!CFSObject::Write。如果文件足够小,线程只需ReadFile/WriteFile在句柄上执行。否则,它将文件映射到内存,并通过VMBus 上的RDMAvmusrv!SrvConnectionExecuteRdmaTransfer高效传输。此传输在 执行,而 RDMA 通信是使用 IOCTL或 与RootVMBus设备(主机 VMBus 设备名称)进行的。0x3EC0D30x3EC08C
2:kd >;k
... (减少)
06 ffffad0e`3bee7650 fffff800`36225b62 vmbusr!RootIoctlRdmaFileIoHandleMappingComplete+ 0x10f
07 ffffad0e`3bee7690 fffff800`361fee21 vmbusr!RootIoctlRdmaFileIo+ 0xf2
08 ffffad0e`3bee76f0 fffff800`339da977 vmbusr!RootIoctlDeviceControlPreprocess+ 0x191
... (减少)
12 00000009 `ae27f7e8 00007ffe`281ce773 ntdll!NtDeviceIoControlFile+ 0x14
13 00000009 `ae27f7f0 00007ffe`281dcbd2 vmusrv!SrvConnectionExecuteRdmaTransfer+ 0x24f
14 00000009 `ae27f940 00007ffe`281d4874 vmusrv!CFile::ReadFileRdma+ 0xc2
15 00000009 `ae27f9c0 00007ffe`281c218e vmusrv!CFSObject::Read+ 0x94
16 00000009 `ae27fa00 00007ffe`281c08da vmusrv!Smb2ExecuteRead+ 0x1be
17 00000009 `ae27fa60 00007ffe`281b8907 vmusrv!Smb2ExecuteProviderCallback+ 0x7e
18 00000009 `ae27fac0 00007ffe`281a6a4e vmusrv!Smb2PacketProcessing+ 0x97
19 00000009 `ae27fb30 00007ffe`3bba6fd4 vmusrv!SmbWorkerThread+ 0xce
... (减少)

图 23\Device\RootVmBus\rdma\494 –读/写操作的通信。

访客到主人的流程

根据本文解释关系的一些见解,我们Storvsc.sys/Storvsp.sys可以将所有先前的技术块结合到下一个文件访问流中。 

图 24 – 文件访问流程。

  1. 我们用命令type打开并打印文件内容kernel32.dll。这是一个系统文件,因此沙盒不拥有它的副本,而是使用主机的副本。
  2. 客户机不知道该文件不存在,因此它通过文件系统驱动程序堆栈直到存储驱动程序堆栈执行正常的文件访问。
  3. Hyper-V 存储消费者Storvsc.sys是一个微型端口驱动程序,这意味着它充当来宾的虚拟存储。它通过 VMBus 接收和转发 SCSI 请求。
  4. 存储提供程序Storvsp.sys有一个工作线程,正在通过 VMBus 监听新消息storvsp!VspPvtKmclProcessingComplete
  5. 提供程序解析 VMBus 请求,并将其传递给vhdparser!NVhdParserExecuteScsiRequestDisk执行vhdmp.sysVHD 解析器驱动程序。
  6. 最后,通过过滤管理器vhdmp.sys访问的物理实例sandbox.vhdx,并执行读/写操作。在这种情况下,它读取客户文件系统过滤管理器请求的数据。该数据返回给过滤管理器进行进一步分析。
  7. 如前所述,返回的条目带有 WCI 重解析标记和主机层 GUID。在wcifs.sys对文件执行创建后操作时,它会查找该设备的联合上下文,并用下一个文件对象替换该文件对象:\Device\vmsmb\VSMB-{dcc079ae-60ba-4d07-847c-3493609c0870}\os\Windows\System32\kernel32.dll
  8. \Device\vmsmb设备被创建为 SMB 共享,因此筛选器管理器可以像访问任何其他普通共享一样访问它。在后台,它通过 VMBus 向主机执行 SMB 请求。
  9. vSMB 用户模式服务器在其工作线程方法中vmusrv.dll轮询\\.\VMbus\设备以获取新消息vmusrv!SmbWorkerThread
  10. 正如我们之前所展示的,在创建操作中,服务器通过已安装的 OS 基础层的句柄上的 IOCTL 与存储提供程序进行通信:\Device\STORVSP\VSMB\??\C:\ProgramData\Microsoft\Windows\Containers\BaseImages\0949cec7-8165-4167-8c7d-67cf14eeede0\BaseLayer\Files
  11. 存储提供程序通过 执行文件请求IoCreateFileEx。该请求是相对的,并且包含RootDirectory已安装操作系统层的 。这会触发筛选器管理器在已安装操作系统层中打开文件。
  12. 与步骤(7)类似,返回的条目包含 WCI 重解析标记,这会导致wcifs.sys在 post-create 方法中更改文件对象。它将文件对象更改为其物理路径:C:\Windows\System32\kernel32.dll
  13. 访问主机kernel32.dll文件,并返回给客户机。
  14. 对于ReadFile操作,wcifs.sys驱动程序会在文件对象顶部保存上下文状态,以帮助其执行读/写操作。此外,工作线程vmusrv要么直接访问文件,要么通过 VMBus 顶部的 RDMA 执行读取请求。

实际过程要复杂得多,因此我们试图专注于虚拟化的关键组件。

沙盒还允许通过其配置将文件夹从主机映射到客户机。此类文件夹会收到 vSMB 路径的唯一别名,并且访问方式与 OS 层类似。唯一的区别是,路径在客户机过滤器管理器中由 更改bindflt.sys

例如,如果我们将SysinternalsSuite文件夹映射到客户机桌面文件夹,则路径C:\Users\WDAGUtilityAccount\Desktop\SysinternalsSuite\Procmon.exe将更改为\Device\vmsmb\VSMB-{dcc079ae-60ba-4d07-847c-3493609c0870}\db64085bcd96aab59430e21d1b386e1b37b53a7194240ce5e3c25a7636076b67\Procmon.exe,而其余过程保持不变。

玩沙盒

这项研究的目标之一是根据我们的需求修改基础层内容。现在我们了解了生态系统,这似乎相当容易。

修改有几个简单的步骤:

  1. 停止CmService,创建并维护基础层的服务。当服务卸载时,也会移除基础层的挂载。
  2. 安装基础层(它在C:\ProgramData\Microsoft\Windows\Containers\BaseImages\0949cec7-8165-4167-8c7d-67cf14eeede0\BaseLayer.vhdx文件中)。这可以通过双击或使用diskmgmt.msc实用程序来完成。
  3. 对基础层进行修改。在我们的例子中,我们添加了所有 FLARE 安装后文件。
  4. 卸下基础层。
  5. 开始CmService

当我们启动沙箱时,我们就有了超棒的 FLARE VM!

图 25 – Windows Sandbox 上的 FLARE VM。

概括

当我们开始研究 Windows Sandbox 时,我们并不知道这样一个“简单”的操作会归结为一个复杂的流程,其中包含多项 Microsoft 内部未记录的技术,例如 vSMB 和容器隔离。

链接

Hyper-V VmSwitch RCE 漏洞

https://www.youtube.com/watch?v=025r8_TrV8I

Windows 沙盒

Windows Sandbox - Microsoft Community Hub

Windows 沙盒 WSB 配置

Windows Sandbox configuration - Windows Security | Microsoft Learn

Windows 容器

  • About Windows containers | Microsoft Learn
  • What I Learned from Reverse Engineering Windows Containers

NTFS 属性

SOLVED: All NTFS Attributes Defined – Up & Running Inc – Tech How To's

重新解析点

Reparse Points - Win32 apps | Microsoft Learn

NTFS 文档

http://dubeyko.com/development/FileSystems/NTFS/ntfsdoc.pdf

NTFS 重新解析标签

[MS-FSCC]: Reparse Tags | Microsoft Learn

VHDx 父级定位器

[MS-VHDX]: VHDX Parent Locator | Microsoft Learn

FS 过滤驱动 – 用户态与内核态之间的通信

https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/communication- Between-user-mode-and-kernel-mode

寻找 Windows Mini-Filter 驱动程序中的错误

https://googleprojectzero.blogspot.com/2021/01/hunting-for-bugs-in-windows-mini-filter.html

Hyper-V Storvsp.sys-Strovsc.sys 流程

https://www.linkedin.com/pulse/hyper-v-architecture-internals-pravin-gatale/

微软对 RDMA 的解释

Host network requirements for Azure Stack HCI - Azure Stack HCI | Microsoft Learn

相关文章:

剑和沙盒 3 - 深度使用和解析Windows Sandbox

介绍 两年前&#xff0c;微软作为Insiders build 18305的一部分发布了一项新功能- Windows Sandbox。 该沙箱具有一些有用的规格&#xff1a; Windows 10&#xff08;Pro/Enterprise&#xff09;的集成部分。在 Hyper-V 虚拟化上运行。原始且可抛弃 – 每次运行时都干净地开…...

深度学习loss

pytorch模型训练demo代码 在PyTorch中&#xff0c;模型训练通常涉及几个关键步骤&#xff1a;定义模型、定义损失函数、选择优化器、准备数据加载器、编写训练循环。以下是一个简单的PyTorch模型训练演示代码&#xff0c;该代码实现了一个用于手写数字识别&#xff08;使用MNIS…...

编写一个Chrome插件,网页选择文字后,右键出现菜单“search with bing”,选择菜单后用bing搜索文字

kimi ai 生成&#xff0c;测试可用&#xff0c;需要自行准备图标文件 创建一个简单的Chrome插件来实现选择文本后的搜索功能&#xff0c;你需要完成以下几个步骤&#xff1a; 创建插件的基础文件夹和文件&#xff1a; 创建一个文件夹用于存放插件的所有文件。在该文件夹中创建以…...

【算法】分割回文串

难度:中等 题目: 给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串。返回 s 所有可能的分割方案。 示例 1: 输入:s = “aab” 输出:[[“a”,“a”,“b”],[“aa”,“b”]] 示例 2: 输入:s = “a” 输出:[[“a”]] 提示: 1 <= s.length <…...

lua 游戏架构 之 游戏 AI (三)ai_attack

这段Lua脚本定义了一个名为 ai_attack 的类&#xff0c;继承自 ai_base 类。 lua 游戏架构 之 游戏 AI &#xff08;一&#xff09;ai_base-CSDN博客文章浏览阅读119次。定义了一套接口和属性&#xff0c;可以基于这个基础类派生出具有特定行为的AI组件。例如&#xff0c;可以…...

大数据之Oracle同步Doris数据不一致问题

数据同步架构如下&#xff1a; 出现的问题&#xff1a; doris中的数据条数 源库中的数据条数 总数完全不一致。 出现问题的原因&#xff1a; 在Dinky中建立表结构时&#xff0c;缺少对主键属性的限制 primary key(ID) not enforced 加上如上语句&#xff0c;数据条数解决一致 …...

visual studio 问题总结

一. Visual Studio: 使用简体中文&#xff08;GB2312&#xff09;编码加载文件, 有些字节已用Unicode替换字符更换 解决方法&#xff1a;vs 工具-》选项-》文本编辑器...

go-错误码的最佳实践

一、背景 在工程开发中&#xff0c;我们有以下场景可以用错误码解决 我们不太方便直接将内部的错误原因暴露给外部&#xff0c;可以根据错误码得到对应的外部暴露消息通过设定错误码判断是客户端或者服务端的问题&#xff0c;避免不必要的排障浪费方便查找日志&#xff0c;定…...

Python面试题:使用Matplotlib和Seaborn进行数据可视化

使用Matplotlib和Seaborn进行数据可视化是数据分析中非常重要的一部分。以下示例展示了如何使用这两个库来创建各种图表&#xff0c;包括基本的线图、柱状图、散点图和高级的分类数据可视化图表。 安装 Matplotlib 和 Seaborn 如果你还没有安装这两个库&#xff0c;可以使用以…...

模拟实现c++中的vector模版

目录 一vector简述&#xff1a; 二vector的一些接口函数&#xff1a; 1初始化&#xff1a; 2.vector增长&#xff1a; 3vector增删查改&#xff1a; 三vector模拟实现部分主要函数&#xff1a; 1.size,capacity,empty,clear接口&#xff1a; 2.reverse的实现&#xff1…...

uniapp安卓通过绝对路径获取文件

uniapp安卓通过绝对路径获取文件 在uniapp中&#xff0c;如果你想要访问安卓设备上的文件&#xff0c;你需要使用uniapp提供的plus.io API。这个API允许你在应用内访问设备的文件系统。 以下是一个示例代码&#xff0c;展示了如何使用plus.io API来获取文件&#xff1a; fun…...

Known框架实战演练——进销存业务单据

本文介绍如何实现进销存管理系统的业务单据模块&#xff0c;业务单据模块包括采购进货单、采购退货单、销售出货单、销售退货单4个菜单页面。由于进销单据字段大同小异&#xff0c;因此设计共用一个页面组件类。 项目代码&#xff1a;JxcLite开源地址&#xff1a; https://git…...

解决npm依赖树冲突的方法以及npm ERR! code ERESOLVE错误的解决方案

一、问题描述 在使用ng new myapp --skip-install 构建Angular 项目后&#xff0c;尝试用npm install 安装依赖的时候报了以下错误。 (base) PS C:\Users\Administrator\Desktop\agtest\myapp> npm i npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to resolve dependenc…...

Spring Boot + Spring Batch + Quartz 整合定时批量任务

​ 博客主页: 南来_北往 系列专栏&#xff1a;Spring Boot实战 前言 最近一周&#xff0c;被借调到其他部门&#xff0c;赶一个紧急需求&#xff0c;需求内容如下&#xff1a; PC网页触发一条设备升级记录&#xff08;下图&#xff09;&#xff0c;后台要定时批量设备更…...

C++STL简介(二)

目录 1.模拟实现string 1.string基本属性和大体框架 2.基本函数 2.1size&#xff08;&#xff09; 2.2 [] 2.3 begin() 和end() 2.4capacity&#xff08;&#xff09; 2.5 reserve 2.6push_back 2.7 append 2.8 2.9insert 2.10find 2.11substr 2.12 2.12 < …...

嵌入式高频面试题100道及参考答案(3万字长文)

目录 解释嵌入式系统的定义和主要特点 描述微处理器与微控制器的主要区别 什么是ARM体系结构?它在嵌入式系统中有哪些优势? 解释GPIO(通用输入输出)的工作原理 什么是ADC和DAC?它们在嵌入式系统中的作用是什么? 解释中断的概念及其在实时系统中的重要性 描述SPI(串…...

python爬虫-事件触发机制

今天想爬取一些政策&#xff0c;从政策服务 (smejs.cn) 这个网址爬取&#xff0c;html源码找不到链接地址&#xff0c;通过浏览器的开发者工具&#xff0c;点击以下红框 分析预览可知想要的链接地址的id有了&#xff0c;进行地址拼接就行 点击标头可以看到请求后端服务器的api地…...

LeetCode-day27-3106. 满足距离约束且字典序最小的字符串

LeetCode-day27-3106. 满足距离约束且字典序最小的字符串 题目描述示例示例1&#xff1a;示例2&#xff1a;示例3&#xff1a; 思路代码 题目描述 给你一个字符串 s 和一个整数 k 。 定义函数 distance(s1, s2) &#xff0c;用于衡量两个长度为 n 的字符串 s1 和 s2 之间的距…...

C++中的static_cast函数

static_cast 是 C 中的一个类型转换操作符&#xff0c;用于在编译时进行类型转换。它主要用于基本数据类型之间的转换&#xff0c;以及类的指针或引用之间的向上转换&#xff08;将派生类指针或引用转换为基类指针或引用&#xff09;和某些情况下的向下转换&#xff08;将基类指…...

从零开始学习网络安全渗透测试之基础入门篇——(二)Web架构前后端分离站Docker容器站OSS存储负载均衡CDN加速反向代理WAF防护

Web架构 Web架构是指构建和管理Web应用程序的方法和模式。随着技术的发展&#xff0c;Web架构也在不断演进。当前&#xff0c;最常用的Web架构包括以下几种&#xff1a; 单页面应用&#xff08;SPA&#xff09;&#xff1a; 特点&#xff1a;所有用户界面逻辑和数据处理都包含…...

2679. 矩阵中的和

两种方法&#xff1a; 第一种&#xff1a;先对二维列表的每一列进行排序&#xff0c;然后对每一列的数据进行逐个比较&#xff0c;找出最大值。 class Solution:def matrixSum(self, nums: list[list[int]]) -> int:result0mlen(nums)nlen(nums[0])for i in range(m):nums…...

Unity Playables:下一代动画与音频序列

Unity的Playables API是一种灵活的系统&#xff0c;用于创建和控制动画、音频以及其他形式的连续媒体序列。它为开发者提供了一种全新的方法来处理游戏中的时间序列&#xff0c;包括动画、音频、特效等。本文将探讨Playables的基本概念、如何使用Playables API实现动画&#xf…...

matlab仿真 模拟调制(下)

&#xff08;内容源自详解MATLAB&#xff0f;SIMULINK 通信系统建模与仿真 刘学勇编著第五章内容&#xff0c;有兴趣的读者请阅读原书&#xff09; clear all ts0.001; t0:ts:10-ts; fs1/ts; dffs/length(t); msgrandi([-3 3],100,1); msg1msg*ones(1,fs/10); msg2reshape(ms…...

RabbitMQ是什么?

RabbitMQ是一个开源的消息代理软件&#xff08;Message Broker&#xff09;&#xff0c;它实现了高级消息队列协议&#xff08;AMQP&#xff0c;Advanced Message Queuing Protocol&#xff09;&#xff0c;并支持多种消息传递协议。它最初由英国的Rabbit Technologies开发&…...

追问试面试系列:分布式id

hi 大家好,欢迎来到追问试面试系列:分布式id 面试中可能面试官不会直接问你分布式id问题,基本上都是因为你在某些面试题回答中提到了,所以就开始追问分布式id相关问题。 先看面试题 ● 面试官:什么是分布式id? ● 面试官:举个例子说说 ● 面试官:什么叫分库分表? ●…...

护网紧急情况应对指南:Linux 应急响应手册

继上一篇&#xff1a;护网紧急情况应对指南&#xff1a;Windows版v1.2全新升级版 之后 收到小伙伴后台要Linux应急手册&#xff0c;今天给大家安排上。 《Linux应急手册》是一本为Linux系统管理员和运维工程师量身打造的实用指南&#xff0c;旨在帮助他们快速应对各种突发状况…...

WEB攻防-通用漏洞-SQL 读写注入-MYSQLMSSQLPostgreSQL

什么是高权限注入 高权限注入指的是攻击者通过SQL注入漏洞&#xff0c;利用具有高级权限的数据库账户&#xff08;如MYSQL的root用户、MSSQL的sa用户、PostgreSQL的dba用户&#xff09;执行恶意SQL语句。这些高级权限账户能够访问和修改数据库中的所有数据&#xff0c;甚至执行…...

【前端学习笔记】CSS基础一

一、什么是CSS 1.CSS 介绍 CSS&#xff08;Cascading Style Sheets&#xff0c;层叠样式表&#xff09;是一种用来控制网页布局和设计外观的样式语言。它使得开发者可以分离网页的内容&#xff08;HTML&#xff09;和表现形式&#xff08;样式&#xff09;&#xff0c;提高了…...

Github遇到的问题解决方法总结(持续更新...)

1.github每次push都需要输入用户名和token的解决方法 push前&#xff0c;执行下面命令 &#xff1a; git config --global credential.helper store 之后再输入一次用户名和token之后&#xff0c;就不用再输入了。 2.git push时遇到“fatal: unable to access https://githu…...

数字信封+数字签名工具类测试样例(Java实现)

加解密过程 加密&#xff1a; 生成加密方SM2密钥对用于签名使用生成的SM2私钥生成数字签名生成SM4对称密钥对明文进行对称加密使用与解密方提前约定好的SM2公钥对第三步中的SM4对称密钥进行非对称加密把【加密方SM2公钥】、【数字签名】、【SM4对称加密后的密文】和【SM2非对…...

The Schematic workflow failed. See above.

在使用 ng new 新建Angular项目的时候会报一个错误&#xff1a;The Schematic workflow failed. See above. 解决办法&#xff1a; 只需要在后面加上 --skip-install 参数&#xff0c;就不会报错了。 ng new myapp --skip-install...

操作系统面试知识点总结4

#来自ウルトラマンメビウス&#xff08;梦比优斯&#xff09; 1 文件系统基础 1.1 文件的相关概念 文件是以计算机硬盘为载体的存储在计算机上的信息集合&#xff0c;可以是文本文档、图片、程序。 文件的结构&#xff1a;数据项、记录、文件&#xff08;有结构文件、无结构式…...

Lua实现面向对象以及类的继承

0.简单前言 1、面向对象主要四个特征&#xff1a;封装&#xff0c;继承&#xff0c;多态&#xff0c;抽象 2、Lua是种简单精致小巧的语言&#xff0c;其本质是个表&#xff08;table&#xff09;&#xff0c;变量和方法皆可看作为该表的元素。 P.S. 该博客和代码为个人编写习…...

机器学习课程学习周报五

机器学习课程学习周报五 文章目录 机器学习课程学习周报五摘要Abstract一、机器学习部分1.1 向量序列作为模型输入1.1.1 文字的向量表达1.1.2 语音的向量表达 1.2 自注意力机制原理1.2.1 自注意力机制理论1.2.2 矩阵运算自注意力机制 1.3 多头自注意力1.4 位置编码1.5 截断自注…...

vue3.0学习笔记(二)——生命周期与响应式数据(ref,reactive,toRef,toRefs函数)

1. 组合API-setup函数 使用细节&#xff1a; setup 是一个新的组件选项&#xff0c;作为组件中使用组合API的起点。从组件生命周期来看&#xff0c;它的执行在组件实例创建之前vue2.x的beforeCreate执行。这就意味着在setup函数中 this 还不是组件实例&#xff0c;this 此时是…...

C++——QT:保姆级教程,从下载到安装到用QT写出第一个程序

登录官网&#xff0c;在官网选择合适的qt版本进行下载 这里选择5.12.9版本 点击exe文件下载&#xff0c;因为服务器在国外&#xff0c;国内不支持&#xff0c;所以可以从我的网盘下载 链接: https://pan.baidu.com/s/1XMILFS1uHTenH3mH_VlPLw 提取码: 1567 --来自百度网盘超级…...

掌握互联网路由选择协议:从基础入门到实战

文章目录 路由选择协议的基本概念路由选择算法的分类分层次的路由选择协议路由信息协议&#xff08;RIP&#xff09;内部网关协议&#xff1a;OSPF外部网关协议&#xff1a;BGP互联网中的实际应用总结 互联网的路由选择协议是网络通信的核心&#xff0c;它决定了数据包如何在网…...

[笔记]ONVIF服务端实现[进行中...]

1.文档搜索&#xff1a; 从&#xff1a;https://www.cnblogs.com/liwen01/p/17337916.html 跳转到了&#xff1a;ONVIF协议网络摄像机&#xff08;IPC&#xff09;客户端程序开发&#xff08;1&#xff09;&#xff1a;专栏开篇_onvif 许振坪-CSDN博客 1.1原生代码支持&…...

深度强化学习 ②(DRL)

参考视频&#xff1a;&#x1f4fa;王树森教授深度强化学习 前言&#xff1a; 最近在学习深度强化学习&#xff0c;学的一知半解&#x1f622;&#x1f622;&#x1f622;&#xff0c;这是我的笔记&#xff0c;欢迎和我一起学习交流~ 这篇博客目前还相对比较乱&#xff0c;后面…...

线性代数重要知识点和理论(下)

奇异值分解 奇异值分解非常重要且有趣。首先对于 n n n\times n nn对称矩阵 A A A&#xff0c;可以通过对角化得到其对角化形式 A P D P − 1 APDP^{-1} APDP−1&#xff0c;但是如果 A A A不是对称矩阵或者不是方阵&#xff0c;则不能进行对角化&#xff0c;但是可以通过奇…...

独立开发者系列(35)——python环境的理解

新手阶段&#xff0c;为了快速入门&#xff0c;基本都是直接开始写python代码实现自己想要的效果&#xff0c;类似搭建博客&#xff0c;写个web服务器&#xff0c;搭建简易聊天室&#xff0c;偶尔也写些爬虫&#xff0c;或者使用pygame写个简单小游戏&#xff0c;也有tk库做点简…...

中小企业常见的网络安全问题及防范措施

在数字化浪潮的推动下&#xff0c;我国中小企业的信息化建设取得了显著成就。然而&#xff0c;随着网络安全形势的日益严峻&#xff0c;中小企业在网络安全方面的短板逐渐暴露出来。本文将从中小企业网络安全现状出发&#xff0c;深入剖析其存在的问题&#xff0c;并提出针对性…...

Android 线程并发:线程通信:Handler机制

文章目录 API源码分析操作总结 API Handler相关 Handler对象.sendMessage(Message) 发送消息 Handler对象.handleMessage()空方法 自定义Handler重写handleMessage方法&#xff0c;处理Message Looper相关 Looper.getMainLooper() 获取App的UI线程的Looper对象 Looper…...

搭建自己的金融数据源和量化分析平台(三):读取深交所股票列表

深交所的股票信息读取比较简单&#xff1a; 看上图&#xff0c;爬虫读取到下载按钮的链接之后发起请求&#xff0c;得到XLS文件后直接解析就可以了。 这里放出深交所爬虫模块的代码&#xff1a; # -*- coding: utf-8 -*- # 深圳交易所爬虫 import osimport pandas as pd imp…...

企业级视频拍摄与编辑SDK的全面解决方案

视频已成为企业传播信息、展示品牌、连接用户的重要桥梁&#xff0c;如何高效、专业地制作高质量视频内容&#xff0c;成为众多企业面临的共同挑战。美摄科技&#xff0c;作为视音频技术领域的创新先锋&#xff0c;以其强大的视频拍摄与编辑SDK&#xff0c;为企业量身打造了一站…...

后端返回列表中包含图片id,如何将列表中的图片id转化成url

问题描述 如果我有一个列表数据&#xff0c;列表中每个对象都包含一个图片id&#xff0c;现在我需要将列表中的图片id转化成图片&#xff0c;然后再页面上显示出来 如果你有一个列表数据&#xff0c;列表中每个对象都包含一个图片 ID&#xff0c;并且你想将这些图片 ID 转化为…...

Python学习笔记44:游戏篇之外星人入侵(五)

前言 上一篇文章中&#xff0c;我们成功的设置好了游戏窗口的背景颜色&#xff0c;并且在窗口底部中间位置将飞船加载出来了。 今天&#xff0c;我们将通过代码让飞船移动。 移动飞船 想要移动飞船&#xff0c;先要明白飞船位置变化的本质是什么。 通过上一篇文章&#xff0…...

export在linux中的作用

在某些项目中常常使用export命令。该命令的作用是设置环境变量&#xff0c;并且该环境变量为当前shell进程与其启动的子进程共享。 export MODEL_NAME"stable-diffusion-v1-4"比如以上命令&#xff0c;如果不采用export&#xff0c;设置的变量仅在当前shell命令/进程…...

FFmpeg解复用器如何从封装格式中解析出不同的音视频数据

目录 1、ffmpeg介绍 2、FFMPEG的目录结构 3、FFmpeg的格式封装与分离 3.1、数据结构 3.2、封装和分离(muxer和demuxer) 3.2.1、Demuxer流程 3.2.2、Muxer流程 4、总结 4.1、播放器 4.2、转码器 C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续…...

测试-常见问题

目录 1、测试报告中有哪些内容? 2、如何保证用例的覆盖度 3、测试用例和测试脚本的关系 4、Android和iOS测试的区别 5、小程序和App测试的区别 6、Web和App测试的区别 7、Alpha和Beta测试的区别 8、测试计划包括哪些? 9、Jmeter 、 monkey 10、设计用例的考虑点 …...