图 1.瘀伤但未破裂。 Windows计算器的代码最近在Github上发布 ,结果证明它是两个经过测试的应用程序之一,这些应用程序没有挂起,并且没有与2000年开发的窗口消息模糊不清相对。 窗口尺寸专门放大以显示模糊的伪像现在是时候进行第二部分的工作了,以便在现代系统上测试古老的模糊测试技术。 如果您错过了,这是
第一部分 。 这次,我们将在2000年由Justin Forrester和Barton Miller撰写的文章“使用随机测试对Windows NT应用程序的可靠性进行实证研究”(aka“ NT Fuzzing Report”)中尝试Windows 10模糊技术。
研究人员测试了Windows NT和早期版本的Windows 2000的33种应用程序是否容易受到扭曲的窗口消息以及随机的鼠标和键盘事件的影响。 自从Miller博士发布模糊器代码以来,我们使用与原始作者
完全相同的工具来查找现代Windows应用程序中的错误。
结果几乎是相同的:19年前,经过测试的应用程序100%崩溃或崩溃时遇到了扭曲的窗口消息。 如今,相同的模糊器下降或挂起了93%的测试应用程序。 只有两个人站立,包括我们的老朋友
计算器 (图1)。 我们还在Windows上发现了一个错误(但不是安全问题)。
Windows简介
那么什么是窗口消息,为什么它们会导致程序崩溃?
Windows GUI应用程序是事件驱动的:鼠标移动,按钮按下,击键等。事件驱动的应用程序在收到事件之前将不执行任何操作。 接收到事件后,应用程序将基于事件执行操作,然后期待其他事件。 听起来很熟悉? 这种架构
在诸如node.js的平台上获得了新生。窗口消息是Windows事件通知方法 。 它们每个都有
与特定事件关联的
数字代码 。 每个消息都有一个或多个参数,
按照惯例 ,这些参数
称为lParam和wParam 。 他们定义了有关事件的更多详细信息。 此类信息的示例是鼠标移动的坐标,按下的键或要在窗口中显示的文本。 这些消息可以由程序本身,操作系统或其他程序发送。 它们可以在任何时间以任何顺序到达,并且必须由接收方的应用程序处理。
安全隐患
在Windows Vista之前,低特权进程可以向高特权进程发送消息。 使用正确的消息组合,您可以在该过程中执行代码。 在Vista中,
UIPI以及在单独的会话中隔离系统服务在很大程度上保护了这些
“颠覆性攻击” 。
错误的窗口消息处理不太可能影响现代Windows系统的安全,原因有两个。 首先,窗口消息无法通过网络发送。 其次,使应用程序崩溃或以相同的特权级别执行代码对攻击者不是很有用。 对于NT模糊测试报告的作者来说,这很明显。 他们没有发表安全声明,但是正确地指出处理窗口消息失败意味着缺乏严格的测试。
在某些区域,以相同的特权执行代码可能会损害安全性。 某些应用程序结合了各种安全性原语,以创建人为的特权级别,而该特权级别最初在操作系统中找不到。 一个典型的示例是在浏览器中呈现的沙箱。 浏览器制造商已充分意识到这些问题,并
已采取措施加以解决 。 另一个例子是防病毒产品。 在那里,控制面板具有普通特权,但与其他防病毒模块隔离。
测试方法
为了模糊测试套件中的所有应用程序,我们使用了原始NT报告中描述的相同基本代码和模糊技术。 特别是,在
SendMessage和
PostMessage模式下,fazzer都使用了500,000条消息的3次迭代(带有42个种子)和500,000条消息的3次迭代(带有1,337个种子)。 每种方法仅执行一次迭代后,结果就会出现。
由于时间限制以及只专注于窗口消息的需求,我们错过了随机的鼠标和键盘输入。 我们也鼓励那些希望重复测试并确认结果的人。
陷阱
对于Windows 10中的模糊器,必须进行两个小的更改。 首先,将其调整为适用于64位平台。 第二个更改允许Fuzzer使用命令行参数选择特定的窗口句柄。 模糊化特定描述符是对
通用Windows平台(UWP)应用程序模糊化的快速修复。 原始程序专注于属于某个进程的模糊窗口,但是所有UWP应用程序都通过相同的进程显示其用户界面(图2)。 这意味着模糊器无法定向到UWP应用程序主窗口。
图 2.在UWP平台上,所有应用程序都属于一个进程( ApplicationFrameHost.exe
)。 要模糊这些应用程序,我必须更改原始的NT模糊器并将其定向到特定的窗口句柄模糊器修改存在一个严重缺陷:为随机输入的两个主要来源(用于
SendMessage
和
PostMessage
的参数
lParam
和
wParam
选择的值限制为16位整数。 这两个参数在32位Windows上都是32位,在64位Windows上是64位。 该问题发生在
Fuzz.cpp
,其中
wParam
lParam
和
wParam
:
wParam = (UINT) rand(); lParam = (LONG) rand();
rand()函数返回范围为[0,2
16 ]的数字,这极大地限制了测试值的设置。 我们在测试过程中有意保存了此错误,以使结果与原始工作准确匹配。
经过测试的应用
在原始的NT报告中,测试了33个程序。 我们只有28个,因为每个程序仅使用一个版本进行测试。 自2000年以来,Windows软件生态系统发生了显着变化,尽管令人惊讶的是,许多变化没有改变。 Microsoft Office套件包含与原始测试相同的程序。 Netscape Communicator已演变为Firefox。 Adobe Acrobat已重命名为Adobe Reader,但仍然有效。 甚至Winamp在2018年也发布了一个新版本,可以与原始报告进行合理比较。 但是,必须替换一些过时的程序。 有关更改及其原因的列表,请参见下文:
- CD播放器⇨Windows Media Player:新程序中包含CD播放器功能。
- Eudora⇨Windows Mail:高通现在正在处理芯片,而不是电子邮件客户端。 由于Eudora不再存在,因此已对默认的Windows邮件客户端进行了测试。
- Command AntiVirus⇨Avast Free Edition: Command AntiVirus不再可用。 它已被Avast取代,成为最受欢迎的第三方防病毒软件。
- GSView⇨照片:不再支持GSView。 它已替换为默认的Windows照片查看器。
- JavaWorkshop Net NetBeans IDE:不再支持JavaWorkshop IDE。 NetBeans似乎是一个不错的免费替代品,它与需要检查的内容相匹配。
- 安全CRT⇨BitVise SSH:安全CRT仍然存在,但是需要很长的Web表格才能下载试用版。 BitVise SSH提供了快速启动。
- Telnet⇨Putty: telnet应用程序在Windows上仍然存在,但现在是控制台应用程序。 为了使GUI模糊,我们用Putty(一种流行的Windows开源终端模拟器)代替了它。
- 我们从Windows App Store应用程序目录的Microsoft Solitaire Collection中找到了Freecell和Solitaire 。
应用程序的特定版本显示在结果表中。 所有模糊测试都是在64位系统Windows 10 Pro版本1809(内部版本17763.253)上进行的。
结果
如原始报告中所述,结果不应被视为安全漏洞,而应视为软件可靠性和质量的指标。
“最后,我们的结果形成了一个定量的起点,从中可以判断软件可靠性的相对提高。”
-摘自Justin Forrester和Barton Miller的“使用随机测试的Windows NT应用程序可靠性的经验研究”
尽管情况正在改善,但人数并不特别令人鼓舞。 在最初的NT报告中,所有应用程序崩溃或模糊不清。 现在,两个程序:计算器和Avast Antivirus,在分阶段设置窗口消息的过程中都没有受到任何负面影响。 我们赞扬Avast和Windows计算器团队的错误窗口消息处理方法。 计算器团队在打开源代码和演示如何创建高质量UWP应用程序方面赢得了更多的尊重。 有关所有模糊测试结果以及所使用软件的特定版本,请参见表1。
表1.在Windows 10上播放原始模糊测试的结果。19年后,几乎所有应用程序仍无法正确处理扭曲的窗口消息Windows错误?
不幸的是,好奇心盛行,我们不得不例外。 似乎几个不相关的应用程序遇到了一个常见问题。 调试显示该问题与
WM_DEVICECHANGE
消息有关。 当模糊器发送此消息时,即使是最简单的应用程序也崩溃
了-Windows API的官方示例HelloWorld (图3)。
图 3.接收到来自Fuzzer的窗口消息时,32位HelloWorld.exe崩溃。 由于程序非常简单,因此不应发生这种情况。 据了解,问题出在Windows中在HelloWorld崩溃之后,我们立即意识到该问题仅影响32位应用程序,而不影响64位应用程序。 一些快速调试显示,崩溃发生在
wow64win.dll中,wow64win.dll是64位的32位应用程序兼容性层 。 我对该问题的肤浅的(可能是不正确的)分析得出的结论是
wow64win.dll!whcbfnINDEVICECHANGE
将wParam视为指向目标程序中
DEV_BROADCAST_HANDLE64
结构的指针。 该函数将此结构转换为
DEV_BROADCAST_HANDLE32
结构,以与32位应用程序兼容。 发生该故障是因为
wParam
生成的
wParam
值指示内存无效。
将
wParam
视为本地指针是一个坏主意,尽管这可能是针对可移动设备通知与旧版32位Windows应用程序一起使用的故意设计决定。 但是,您可以毫无问题地崩溃另一个应用程序仍然是错误的。 尽管没有跨越安全边界,但我们已向MSRC报告了此问题。 他们确认该错误不是安全问题。 我们希望在将来的Windows版本中看到针对此普遍接受的奇怪问题的修复程序。
结论
窗口消息被低估了,并且通常作为对Windows程序的不可靠输入而被忽略。 甚至在出现第一个开放源代码窗口消息模糊器之后的19年,当同一程序启动时,仍有93%的经过测试的应用程序冻结或崩溃。 但是令人鼓舞的是,某些应用程序可以很好地处理这种失真的输入:这意味着某些组织具有避免此类错误的框架和机构知识。
当然,可以通过许多方法来改进模糊器,但是即使最简单的方法也使93%的应用程序崩溃。 也许在某些情况下,窗口消息甚至跨越了真正的安全边界。 如果您探索这一领域,我们希望您能分享发现。