写点什么

基于虚拟化的安全性 - 第 2 篇:内核通信

  • 2017-03-08
  • 本文字数:4407 字

    阅读完需:约 14 分钟

AMOSSYS Security 团队的 Adrien Chevalier 撰写了一系列文章,讲述了基于虚拟化的安全。

作者在文章中使用了 CC 协议,InfoQ 翻译本文。

本文是第二篇文章,涉及基于虚拟化的安全和设备保护功能。在第一篇中,我们介绍了从 Windows 引导加载程序到 VTL0 启动的系统引导过程。在这篇文章中,我们将解释 VTL0 和 VTL1 之间如何进行内核通信。当它们使用超级调用进行通信时,我们将首先描述 Hyper-V 的超级调用实现,然后内核如何使用它们进行通信。为了完成这一描述,我们将列出这项工作中我们发现的所有不同的超级调用和安全服务调用。

Hyper-V 超级调用

VTL0 和 VTL1 之间的内核通信使用 Hyper-V 超级调用。使用 VMCALL 指令执行这些超级调用,其中在 RCX 寄存器中具有超级调用号,并且 RDX 指向包含参数的 Guest 物理页(Guest Physical Page,GPA)。如果设置了 0x10000 RCX 位,超级调用是一个“FAST”超级调用,参数(和返回值)存储在 XMM 寄存器中。为了执行调用,Windows 使用“hypercall trampoline”,这是一个小的 fastcall 例程,用来执行 VMCALL 和 RET。

该例程存储在“超级调用页面”中。此页面包含 5 个 trampoline,由 Hyper-V 在启动时提供给 winload.efi,这将在 VTL0 和 VTL1 地址空间中复制它。这五个 trampoline 之间的主要区别是,第一个只是一个 VMCALL/RET,但是接下来的四个(它们被连续定义)将 RCX 存储到 RAX,并且在 RCX 中强制使用固定值。第二个和第三个将 RCX 强制为 0x11,下一个强制为 0x12。

这四个 trampoline 实际上由不同的 VTL 使用。每个内核可以使用专用的超级调用来“询问”Hyper-V 的 0xD0002 虚拟处理器寄存器值(可以使用其标识符来查询或设置的内部 Hyper-V 值),其将返回两个偏移量。这些偏移量与超级页面相关,并且将被内核用来调用正确的 trampoline。实际上,VTL1 和 VTL0 使用 0x11trampoline 来相互通信,并且 VTL1 使用 0x12trampoline 来完成其初始化。

超级调用页面的内容可以表示为:

复制代码
VMCALL <-- first trampoline
RET
MOV RAX, RCX <-- second one (enforces 0x11)
MOV RCX, 0x11
VMCALL
RET
MOV RAX, RCX <-- third (0x11)
MOV RCX, 0x11
VMCALL
RET
MOV RAX, RCX <-- fourth (0x12)
MOV RCX, 0x12
VMCALL
RET
MOV RAX, RCX <-- fifth (0x12)
MOV RCX, 0x12
VMCALL
RET
db 0x00
db 0x00
db 0x00
db 0x00
db 0x00
db 0x00
...
...
db 0x00

因此,我们有五个 trampoline,偏移量为 0x00、0x04、0x0F、0x1D 和 0x28。注意,可以使用 WinDbg 轻松地在 Windows 崩溃转储中获取其内容,或在 Hyper-V 二进制文件(hvix64.exe/hvax64.exe,适用于 Intel/AMD)的内部代码找到。

备注:几个超级调用可以指定 RCX 最高有效位 DWORD 的 12 个最低有效位中的数据大小。这些大小不是以字节为单位的数据长度,而是与当前调用相关,且可能表示入口计数等。

对于一个超级调用的例子,VTL1 的 ShvlProtectContiguousPageshypercall(12) 参数是遵循此方案的结构体:

复制代码
typedef struct _param {
ULONGLONG infinite; // always 0xFFFFFFFFFFFFFFFF
ULONG protection_asked; // 0xD EXECUTE, 0xF WRITE
ULONG zero_value; // always 0
ULONGLONG pfns[]; // entries count is set in the hypercall number
} param;

为了告诉 Hyper-Vpfns 参数的大小,RCX 的高位 DWORD 必须包含其元素数量。对于只有一个入口和 FAST 超级调用而言,RCX 值因此必须为 0x10010000C。

安全内核的超级调用

两个 VTL 能够执行多个超级调用,以便与 Hyper-V 进行通信。它们可以执行相同的超级调用,但 Hyper-V 将拒绝一些来自 VTL0 调用的超级调用。两个 VTL 还使用一个专用的超级调用来彼此通信。总结见图 1

复制代码
1:Hypercalls 类别

让我们首先描述“VTL1 到 Hyper-V”的超级调用(绿色)。然后我们将描述 0x11 的超级调用。

VTL1 可以使用三种超级 trampoline:

  • ShvlpHypercallCodePage, 相当于 NTOS HvlpHypercallCodePage(偏移 0),并指向第一个 trampoline;
  • ShvlpVtlReturn,它将 RCX 强制为 0x11 并允许 VTL0 和 VTL1 通信;
  • ShvlpVtlCall,它将 RCX 强制为 0x12,并且仅在 VTL1 初始化期间使用。

后两者使用 0xD0002 虚拟寄存器得到(通过 ShvlpGetVpRegisterreturn 返回值的 24 个最低有效位,每个偏移量为 12 位的长度)。这两个偏移指向 0x11 和 0x12trampoline。

顺便说一句,VTL0 NTOS 内核使用同一进程获得其 HvlpVsmVtlCallCodeVa 值(用于 VTL0 到 VTL1 通信的超级 trampoline),但获得是相反的结果。正是因为 Hyper-V 会根据 VTL 所寄宿 VM 的不同而返回不一样的值,所以我们认为任何 VM 使用 trampolines 访问同样的超级调用页面时,都会请求一遍虚拟寄存器的值。

下表是每个 trampoline 可能的 VTL1 超级调用:

ShvlpVtlCall

Hypercall number Caller - usage0x12 ShvlInitSystem – end of VTL1 initialization?

ShvlpVtlReturn (VTL0 returns/calls)

Hypercall number Caller - usage0x11 SkCallNormalMode/SkpPrepareForReturnToNormalMode – returns to NTOS / calls NTOS 返回 NTOS / 调用 NTOSShvlpHypercallCodePage (HyperV)

Hypercall number

Caller - usage

0x2

ShvlFlushEntireTb, etc. - Translation buffer flushs

0x3

Translation buffer flushs

0xB

SkpgPatchGuardCallbackRoutine – (H) HyperGuard delayed routines registering

0x15

0xC

ShvlProtectContiguousPages – Memory protection modification

0xD

ShvlInitSystem – Called just before ShvlEnableVpVtl, seems to send several settings to HV

0xF

ShvlEnableVpVtl – Sends settings to HV, and notably the ShvlpVtl1Entry function pointer

0x50

ShvlGetVpRegister – Gets a virtual processor (VP) register

0x51

ShvlSetVpRegister – Sets a virtual processor register

0x52

SkpgTranslateVa – (H) VTL0 memory access by HyperGuard

0x86

ShvlPrepareForHibernate

0x87

ShvlNotifyRootCrashDump

0x94

BugCheck

0x8E

LiveDumpCollect

0x97

SkpGetPageList

0xAE

ShvlSetGpaPageAttributes – 1607 build: changes a GPA attributes, seems to only been used on VTL1 memory

VTL0 到 VTL1 的转换

几乎所有 NTOS“Vsl”前缀函数最终以 VslpEnterIumSecureMode 结尾,带有安全服务调用号(Secure Service Call Number,SSCN)。此函数调用 HvlSwitchToVsmVtl1,它使用 HvlpVsmVtlCallVa 超级调用 trampoline(常规 hyper-V 超级调用使用 HvcallCodeVatrampoline)。然后将 SSCN 复制到 RAX 中,并将 RCX 值设置为 0x11。

Hyper-V 将 0x11 超级调用分派到 securekernel.exe 函数 SkpReturnFromNormalMode 中,然后调用 IumInvokeSecureService(实际上我们不确定 IumInvokeSecureService 是否被直接调用,我们认为必须首先调用 SkpReturnFromNormalMode,以使 IumInvokeSecureService 在安全服务调用完成后返回到 VTL0)。IumInvokeSecureService 主要是一个大的 switch/case 块,它处理所有的 SSCN。

最后,调用 SkCallNormalMode,以 SkpPrepareForReturnToNormalMode 为结尾。实际上,安全内核的 NTOS 调用可以被认为是对 VTL0 的“伪返回”,因为它们也包含在 0x11 超级调用中。

我们已经从下面的阵列中确认了来自 VTL0 的所有可能的 SSCN。对于每一个,我们指出了被调用的函数,它们的名字通常是不言自明的。相应的参数必须通过逆向 VTL0 调用者或 VTL1 调用源来确定。

SSCN

Called function

1 SkmmInitializeUserSharedData / SkInitSystem2 SkeStartProcessor3 SkpsRegisterSystemDll4 InterlockedCompareExchange(IumSystemProcessRegistered) / PsIumSystemProcess manipulation5 SkmmCreateProcessAddressSpace/SkobCreateHandle6 SkeInitializeProcess7 IumCreateThread8 SkiTerminateAllThreads9 IumTerminateThread10 SkeRundownProcess11 SkpsIsProcessDebuggingEnabled / SkmmDisableProcessMemoryProtection12 Unknown_13 & 14 SkmmMapMdl / IumpGetSetContext15 SkeReferenceProcessByHandle / SkmmMapDataTransfer / SkpEncryptWithTrustletKey16 SkeReferenceProcessByHandle / Unknown_17 SkRetrieveMailbox18 SkIstTrustletRunning19 SkmmCreateSecureAllocation20 SkmmMapDataTransfer / SkmiFillSecureAllocation21 SkmmConvertSecureAllocationToCatalog_22 SkmmCreateSecureImageSection_23 SkmmFinializeSecureImageHash_24_ SkmmFinishSecureImageValidation_25_ SkmmPrepareImageRelocations_26_ SkmmRelocateImage_27_ SkobCloseHandleEx_28_ SkmmValidateDynamicCodePages_29_ SkmmTransferImageVersionResource30 EntropyProvideData / BCryptGenRandom31 SkpEncryptHiberData / SkpSetHiberCrashState32 SkpSetHiberCrashState / SkpgHibernateActive = 0 / SkFinalizePageEncryption33 SkmmConfigureDynamicMemory34 IumConnectSwInterrupt35 Unknown = 0x300036 SkLiveDumpStart37 SkpLiveDumpContext / _Unknown_38 SkLiveDumpSetupBuffer39 SkLiveDumpFinalize40 SkpLiveDumpFreeContext / SkpReleaseLiveDumpLock41 SkNotifyPowerState42 IumDispatchQueryProfileInformation192 SkeReferenceProcessByHandle193 SkmmValidateSecureImagePages208 SkmmInitSystem / IumpInitializeSystem209 SkpWorkItemList / _Unknown_210 SkmiReleaseUnprivilegedPagesInRange / SmiReserveNtAddressRange211 SkmmApplyDynamicRelocations212 SkEtwEnableCallback224 SkiAttachProcess / SkmiFlushAddressRange225 SkmmFastFlushRangeList226 SkmmSlowFlushRangeList227 SkmmRemoveProtectedPage228 SkmmCopyProtectedPage229 SkmmMakeProtectedPageWritable230 SkmmMakeProtectedPageExecutable231 (H) Gets *Skmi *flags232 SkhalEfiInvokeRuntimeService233 SkLiveDumpCOllect234 SkmmRegisterFailureLog235 SkPrepareForHibernate236 SkPrepareForCrashDump237 SkhalpEfiRuntimeInitialize / SkhalpReportBugCheckInProgress238 & 240 Returns an error code241 SkKsrCallOtherwise SkeBugCheckEx(0x121, 0xFFFFFFFFC000001C, , 0, 0)

正如你所见,几个被调用的函数是未知的。这是因为它们没有执行明显的调用,我们没有花时间去继续分析。

结论

本文描述了基于虚拟化的安全 VTL0-VTL1 如何进行内核通信。

如果你想要更多的 Hyper-V 相关信息,你也可以阅读这两篇文章:

我们计划将发表第三篇关于 VBS 的文章,将重点介绍 HVCI 内部,特别是 * W^X *VTL0 内核保护。


感谢魏星对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们。

2017-03-08 16:424429
用户头像

发布了 375 篇内容, 共 187.1 次阅读, 收获喜欢 945 次。

关注

评论

发布
暂无评论
发现更多内容

推进媒体深度融合:腾讯与上海文广集团达成战略合作,腾讯云、SMT成立联合实验室

科技热闻

微众银行 TiDB HTAP 和自动化运维实践

PingCAP

TiDB 自动化运维

一张图看懂CodeArts TestPlan 5大特性,带你玩转测试服务

华为云PaaS服务小智

JVM参数:带你认识-X和-XX参数

华为云开发者联盟

开发 华为云 企业号 2 月 PK 榜 华为云开发者联盟

Dubbo 3 之 Triple 流控反压原理解析

阿里巴巴中间件

阿里云 微服务 云原生

云原生微服务技术趋势解读

阿里巴巴中间件

阿里云 开源 微服务 云原生

大数据编程培训课程怎么选择

小谷哥

MASA Stack 1.0 发布会讲稿——趋势篇

MASA技术团队

.net 云原生 dapr blazor MASA

新泰山众筹SUN4.0系统开发模式详情

开发微hkkf5566

java培训技术学习对学历有什么要求

小谷哥

从焊接角度聊一聊,设计PCB的5个建议

华秋PCB

工具 PCB PCB设计 焊接

从理论到实践:MySQL性能优化和高可用架构,一次讲清

做梦都在改BUG

Java MySQL 数据库 性能优化

web前端培训班口碑比较好有哪些

小谷哥

快速上手python的简单web框架flask

程序那些事

Python flask Web Web框架 程序那些事

Spring Cloud Alibaba 在 Proxyless Mesh 上的探索

阿里巴巴中间件

阿里云 S而vice Mesh Spring Cloud Aliababa

落地DevOps的路线图

老张

DevOps 软件工程

2023计算机领域顶会(A类)以及ACL 2023自然语言处理(NLP)研究子方向领域汇总

汀丶人工智能

人工智能 自然语言处理 2月日更 计算语言学协

AR Engine毫秒级平面检测,带来更准确的呈现效果

HarmonyOS SDK

HMS Core

参加大数据开发培训机构怎么样

小谷哥

大数据开发技术如何选择培训机构

小谷哥

JVM 如何获取当前容器的资源限制?

阿里巴巴中间件

Java 阿里云 云原生 中间件

婚庆LED显示屏打造梦幻婚礼

Dylan

LED显示屏 led显示屏厂家 户内led显示屏

C++数据结构

老浩

写给go开发者的gRPC教程-通信模式

凉凉的知识库

golang 微服务 gRPC 服务治理

一文梳理 Code Review 方法论与实践总结

阿里巴巴中间件

阿里云 云原生 Code Review

SAP的良好业绩,能否敲响国内厂商的警钟?

ToB行业头条

盘点2022:开源热度居高,技术思考与经验分享是开发者的最爱

阿里巴巴中间件

阿里云 中间件

亚马逊云科技核心服务之计算服务(Part1:Amazon EC2 星巴克为什么横向排队)

亚马逊云科技 (Amazon Web Services)

云原生 亚马逊云科技 Builder 专栏

数据库日常实操优质文章分享(含Oracle、MySQL等) | 2023年1月刊

墨天轮

数据库 oracle postgresql MySQL 运维 故障处理

技术交错革新,移动开发平台机会和挑战并存

FinFish

移动开发 移动开发平台 移动应用开发

共赴元宇宙新纪元,华为云VR开发应用大赛总决赛倒计时7天!

华为云开发者联盟

人工智能 华为云 VR开发应用 企业号 2 月 PK 榜 华为云开发者联盟

基于虚拟化的安全性 - 第2篇:内核通信_安全_Adrien Chevalier_InfoQ精选文章