利用显示器控制命令集(MCCS)破解HP显示器(CVE-2023-5449)

本文详细介绍了通过显示器控制命令集(MCCS)协议在HP显示器中发现并利用CVE-2023-5449漏洞的过程。包括MCCS协议基础、HP专有VCP代码实现、防盗机制漏洞分析以及利用ddcset工具进行实际攻击的步骤。

利用显示器控制命令集(MCCS)破解HP显示器(CVE-2023-5449)

显示器软件

有一天,我将电脑连接到一台HP显示器。令人烦恼的是,我注意到Windows自动安装了HP Display Center软件,没有任何提示,这可能是因为它是一个受信任的Windows Store应用程序。后来,我注意到即使在使用不同制造商的显示器时,HP Display Center仍然可以交互并控制某些基本设置,如亮度。

出于好奇,我决定查看该软件的内部结构。幸运的是,它是一个.NET Framework应用程序,可以轻松反编译为接近原始的C#代码。在代码中,我注意到一些有趣的函数,每当更改显示设置时就会调用这些函数,例如ExecuteSetVcp。这些函数又调用了更低层的Windows API,这些API可能处理实际的硬件级通信。

经过一些搜索,我发现Vcp指的是虚拟控制面板。在显示器控制命令集(MCCS)协议中,每个VCP对应一个特定的显示器设置,例如亮度VCP、对比度VCP等。但首先,我需要更好地理解MCCS。

显示器控制命令集(MCCS)

我们之所以可以相当互换地使用显示器,而无需更换电缆、驱动程序等,是因为视频电子标准协会(VESA)开发了各种标准。是的,那个VESA behind the VESA mount,但除了物理标准外,VESA还指定了固件和软件标准,如MCCS。

顾名思义,MCCS指定了连接到显示器的主机如何通过各种命令控制显示器。MCCS运行在更低层的显示数据通道命令接口(DDC/CI)标准之上,该标准可以在各种电缆(如HDMI)上实现。

特别是,MCCS定义了三种类型的VCP控制:

  • 连续:值从0到指定的最大值,例如亮度(0到100)。
  • 非连续:值在有限集合内(换句话说,枚举/布尔值),例如颜色预设。
  • 表:数据块(自定义结构)。例如,“源时序模式”VCP有一个5字节的数据结构:DMT时序模式标志(0)、CEA DTV时序模式标志(1)、CVT描述符字节(2-4)。是的,这是很多我没有费心去查找的首字母缩写词。

此外,这些控制可以是只读、只写或读写(这在后面很重要)。您可以查看发布的MCCS文档以获取完整的VCP代码列表。

要设置可写的VCP控制,Windows提供了以下API:

1
2
3
4
5
_BOOL SetVCPFeature(
  [in] HANDLE hMonitor,     // 显示器实例的句柄
  [in] BYTE   bVCPCode,     // VCP控制代码
  [in] DWORD  dwNewValue    // 新的VCP控制代码值
);

尽管MCCS已经预定义了许多常见的VCP控制,从控制代码0x00到0xDF,但它也为制造商特定的控制留出了空间:

32个控制代码E0h到FFh已被分配,允许制造商发布自己的特定控制,无论是在定义的VCP代码不提供所需功能的情况下,还是在添加的功能被认为是专有的情况下。

注意:使用这些代码有可能导致不兼容和/或不可预测的行为。示例:考虑两个显示制造商选择对不同的功能(或同一功能的不同实现)使用相同的“制造商VCP代码”,但用户选择不使用为其特定显示器提供或推荐的特定软件支持——他可能使用通用的MCCS支持应用程序、操作系统内置的本机支持或用于不同显示器型号的MCCS支持应用程序。在这种情况下, resulting behavior is unpredictable,从对使用“制造商VCP代码”的功能没有支持到对功能的错误控制和调整。在所有情况下,这都可能导致用户烦恼和服务呼叫,在极端情况下,可能导致用户无法将显示器恢复到正常操作的情况。

建议谨慎使用这些代码,并且仅在严格必要时使用。

尽管有这个可怕的警告,正如我在iCalendar标准中发现的那样,供应商往往倾向于在谨慎的另一边犯错,以便区分基于共同标准构建的产品。例如,您会发现显示器远远超出了仅仅显示漂亮图片的范围——它们可以包括集成网络摄像头、麦克风等。

显示器支持的某些信息在初始化期间通过能力字符串发送,该字符串允许软件了解该显示器支持哪些VCP控制。

HP的专有VCP代码

您可能会注意到,只有16个不同的VCP代码分配给制造商特定的控制,实际上没有太多空间来添加新控制。

然而,HP对此有一个巧妙的解决方案。

对于连续控制,它们的代码遵循通常的范式:<VCP代码> <值>。

然而,这对于非连续控制来说是浪费字节,因为枚举通常只占用少数可能的值。例如,可能有一些颜色配置文件对应于特定的字节值:游戏(0)、电影(1)、温暖(2)、冷(3)。然而,一个字节最多可以占用256个值。

相反,对于专有的非连续控制,HP创建了包含在一个全能VCP代码中的子VCP代码。设置此VCP控制时,值范围可以从SetColorProfileGaming(0)、SetColorProfileMovie(1)、SetColorProfileWarm(2)、SetColorProfileCool(3),然后包括其他非连续控制,如SetScreenOrientation0(4)、SetScreenOrientation90(5)、SetScreenOrientation180(6)等。这样,而不是X个非连续控制占用X个宝贵的专有控制代码,它们可以只占用1个。

防盗

从固件中反编译这些代码很困难,固件主要包含显示器芯片组特定(Genesis)指令。Red Balloon Security之前已经对在DDC上运行的专有“GProbe”协议进行了一些研究,这说服了我不要走那条路。

相反,由于显示器控制软件的现成可用性,反编译客户端并从函数名称、使用GUI时的动态调试和日志消息中找出VCP控制代码的功能要容易得多。

我从GUI中注意到的一个有趣功能是HP的防盗机制。用户可以在显示器上设置一个4到6位的PIN,这样如果显示器被盗并连接到新计算机而没有输入PIN,5分钟后屏幕会变暗并显示消息“防盗模式已启用”。

为了支持此功能,HP实现了以下控制命令:

  • TheftTimeOut(251):连续值,表示在未输入PIN的情况下触发防盗机制之前的时间(分钟)。
  • TheftLowPin(252):连续值,表示PIN的低3位。
  • TheftHighPin(253):连续值,表示PIN的高3位。
  • TheftDeterrence(250):非连续值,表示防盗机制的状态。可以是TheftDisabled(0)、TheftEnabledConsumer(1)或TheftEnabledEnterprise(2)。

当打开防盗机制时,HP Display Center软件接受用户输入的PIN,然后发送以下写MCCS命令:

  • TheftLowPin = LowPin:显示器设置LowPin。
  • TheftHighPin = HighPin:显示器设置HighPin。
  • TheftDeterrence = TheftEnabledConsumer:显示器打开防盗机制。

当关闭防盗机制时,它发送以下写MCCS命令:

  • TheftLowPin = LowPin:显示器检查LowPin。
  • TheftHighPin = HighPin:显示器检查HighPin。
  • TheftDeterrence = TheftDisabled:如果前两个步骤正确检查,显示器关闭防盗机制。

在固件端,TheftDeterrence被正确配置为在显示器尚未收到正确的TheftLowPin和TheftHighPin命令时为只读(RO)。不幸的是,TheftLowPin和TheftHighPin控制命令值未设置为只写(WO),而是实际上是读写(RW)。这允许攻击者即使在防盗机制已触发时也能实际读取PIN的值。

需要注意的是,HP的实现对读写解释相当宽松。例如,当尝试解锁显示器时,使用写命令发送PIN值,但这些值实际上不会覆盖存储的PIN值。仅仅是为了通过MCCS发送值,必须发送写命令。

MCCS模糊测试和利用

当然,为了实际发送恶意系列控制命令,您仍然需要使用低层API与显示器通信。在C++中自定义编码这可能相当麻烦。幸运的是,通过ddcset项目(https://github.com/arcnmx/ddcset-rs)在Rust中已经完成了一些工作,使得操作通过DDC/CI发送的消息变得容易。这是开发您自己的自定义工具和模糊测试器的良好基础。

对于像防盗这样的简单错误,可以通过直接发送消息来利用。

使用HP Display Center软件,转到“高级”选项卡,将PIN设置为123123并启用防盗机制。 将显示器插入另一台计算机。您有5分钟的时间 before the anti-theft deterrence is triggered。 运行ddcset -b winapi getvcp 252以读取TheftLowPin。它应该返回:

1
2
3
Display on winapi:
        ID: Generic PnP Monitor
        Feature 0xfc = 123 / 65535

运行ddcset -b winapi getvcp 253以读取TheftHighPin。它也应该返回相同的值。 这证明您已成功从“被盗”显示器中读取了PIN。如果防盗机制被触发,只需使用HP Display Center输入泄漏的PIN。

结论

我与HP协调披露了CVE-2023-5449。观察修补硬件,尤其是像显示器这样的专用硬件,有多么困难,是很有趣的。

这个简单的漏洞只是触及了在专有MCCS VCP控制中可以发现的更有趣错误的表面,特别是如果使用表类型值,这些值更可能触发内存损坏问题。正如VESA警告的那样,这可能导致显示器的永久损坏。

随着显示器在硬件和软件中添加更多功能,如集成网络摄像头,我怀疑我们可能会开始看到在这一领域出现更严重的漏洞。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计