关于滥用Windows窗口类额外字节的兼容性说明
摘要
Raymond Chen 讨论了一个历史性的 Windows 兼容性问题,其中一些 16 位程序滥用窗口类额外字节来存储私有数据,以及微软如何在保持向后兼容性的同时,对 32 位和 64 位程序堵住了这个漏洞。
<p>在我讨论 <a title="Windows 系统中窗口和类额外字节的演变" href="https://devblogs.microsoft.com/oldnewthing/20260629-00/?p=112484">Windows 系统中窗口和类额外字节的演变</a>时,我提到尽管 ID 通常是小的整数,但人们喜欢在那里藏指针,所以我们不得不将 ID 字段扩展为指针大小的整数。</p>
<p>我学到的一件事是,在任何可以隐藏指针的地方,人们都会藏一个指针。即使对于小整数也是如此。</p>
<p>当我挖掘额外字节的历史时,我在 16 位代码中看到了 <code>SetClassWord</code> 的一个特殊注释:它说有一个应用程序希望能够修改 <code>GWW_<wbr />CBCLSEXTRA</code> 的值。</p>
<p>现在,修改这个值没有实际效果,因为类的内存在你调用 <code>RegisterClass</code> 时就已经分配了。你无法回到过去改变分配大小。</p>
<p>但有一个程序意识到它可以用这个值来存储一些私有数据,于是就这么做了。当然,这不是 <code>GWW_<wbr />CBCLSEXTRA</code> 的目的,但这从未阻止过他们。</p>
<p>为了兼容性,Windows 允许 16 位程序修改 <code>GWW_<wbr />CBCLSEXTRA</code>。但至少对于 32 位和 64 位程序,它阻止了这种操作。一个漏洞被堵上了。还有无数个要处理。</p>
<p>本文 <a href="https://devblogs.microsoft.com/oldnewthing/20260630-00/?p=112488">关于滥用Windows窗口类额外字节的兼容性说明</a> 首次出现在 <a href="https://devblogs.microsoft.com/oldnewthing">The Old New Thing</a> 上。</p>
查看缓存全文
缓存时间: 2026/06/30 17:17
# 关于滥用Windows窗口类额外字节的兼容性说明 - The Old New Thing
来源:https://devblogs.microsoft.com/oldnewthing/20260630-00?p=112488
2026年6月30日
like1反应
在我讨论系统窗口和类额外字节的演变过程时(https://devblogs.microsoft.com/oldnewthing/20260629-00/?p=112484),我曾指出:尽管ID通常是小整数,但人们喜欢把指针藏在那里,因此我们不得不将ID字段扩展为指针大小的整数。
我学到的教训是:任何能藏指针的地方,人们都会把指针藏进去。即使是对小整数也是如此。
在我挖掘额外字节的历史时,我在16位`SetClassWord`代码中发现了一条特别说明:存在某个应用程序期望能够修改`GWW\_CBCLSEXTRA`的值。
修改这个值实际上没有任何效果,因为类内存是在调用`RegisterClass`时分配的。你无法回到过去改变分配大小。
但某个程序意识到:它可以将这个值用作存放私有数据的地方,于是就这样做了。当然,这并非`GWW\_CBCLSEXTRA`的设计目的,但这从未阻止过他们。
出于兼容性考虑,Windows允许16位程序修改`GWW\_CBCLSEXTRA`。不过至少对32位和64位程序进行了阻止。堵住了一个漏洞。还有无数个漏洞等着去堵。
### 分类
### 话题
## 作者
Raymond Chen
Raymond参与Windows的演变已有30多年。2003年,他创办了名为The Old New Thing的网站,其受欢迎程度远远超出了他最疯狂的想象——这一发展至今仍让他感到毛骨悚然。该网站衍生了一本书,巧合的是书名也是The Old New Thing(Addison Wesley 2007)。他偶尔会出现在Windows Dev Docs的Twitter账户上,讲述一些毫无实际用处的故事。
## 继续阅读
## 保持关注
新文章发布时会收到通知。
关注本博客
- https://twitter.com/ChenCravat
- youtube(https://www.youtube.com/playlist?list=PLlrxD0HtieHge3_8Dm48C0Ns61I6bHThc)
- https://github.com/oldnewthing
- https://devblogs.microsoft.com/oldnewthing/feed/
相似文章
Windows中窗口和类额外字节的演变
本文追溯了Windows中窗口和类额外字节从16位到32位再到64位的演变,详细描述了随着句柄和指针的扩展,函数名称和数据大小的变化。
为什么32位x86系统上的Windows客户端版本人为地将内存限制为4 GB?
解释了32位Windows客户端版本人为将内存限制为4 GB的历史原因:物理地址扩展(PAE)和数据执行保护(DEP)存在驱动兼容性问题,而非出于任何恶意动机。
Windows堆栈限制检查回顾,后续
Raymond Chen跟进了他之前关于ARM64堆栈限制检查的文章,指出了堆栈探测函数中x15寄存器的非常规使用细节,并比较了多个架构的寄存器使用。
为Windows 3.1改造WM_COPYDATA消息
本文解释如何利用共享地址空间,将针对32位Windows引入的WM_COPYDATA消息改造到16位Windows 3.1上,使得16位程序间的通信无需任何更改。
一个未正式卸载却从内存中消失的DLL案例,第二部分
Ray Chen的一篇技术博文,探究一个内存损坏bug:单个字节0x01破坏HMODULE句柄,导致DLL被错误释放,进而在进程终止时崩溃。