首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

如果访问未文档化的结构会怎样

三个实际案例

如果程序有意或者无意的访问和依赖未文档化的结构,会出现怎样的结果?

我马上就想起了下面的三个例子。

对一些不能碎片整理的东西进行碎片整理(Defragmenting)

在Windows 2000上,有一些对象是不能被碎片整理的,例如目录,独占打开的文件,MFT和页面文件。但是,还是有一些软件公司在他们开发的碎片整理程序中对这些对象进行碎片整理。在软件中,他们进入了内核模式,对NFTS数据结构进行了逆向工程,然后对这些结构进行了修改。这可不是好主意啊老哥。

后来,NTFS开发团队在Windows XP中添加了对MFT进行碎片整理的支持,上面提到的这些软件修改了这些已经修改过的NTFS数据结构,然后,使用者的电脑磁盘毫无疑问地被搞乱了。当然,这种行为并没有在文档中体现出来,所以,当后台的碎片整理程序搞乱了磁盘结构后,微软的程序员背了这个锅。

传递资源管理器视图数据结构

有一些软件公司想从一个外壳扩展(Shell Extension)中修改资源管理器的视图显示。正常来说,外壳扩展没有可能去修改资源管理器的视图显示,因为这个只能由用户来控制,于是,他们决定使用他们自己的方法。

在外壳扩展中,他们使用了一个未文档化的消息来获取一个内部数据结构的指针。然后他们对这个数据结构进行遍历,直到找到他们熟悉的部分,他们想着:”在找到的熟悉的部分的地址空间后面应该是我们需要的数据结构。”

戏剧性的是,他们识别到的部分和他们想要的部分,实际上是一个多继承类的基类。如果一个类有多个基类,则编译器在实现的时候,并没有规定基类的顺序。在这家公司测试的操作系统版本上,这个顺序是X, Y, Z。

但是到了Windows 2000,编译器决定将顺序修改为X, Z, Y,于是当他们看到X时,他们认为接下来的部分肯定是Y,但是实际上是Z,于是他们开发的程序在运行一段时间之后就导致了系统的崩溃。

于是,我不得不创建这样一个顺序”fake, X, Y”,所以当它们尝试寻找X时,它们会首先找到一个假的结构。

这个问题花费了我的大半个星期才得以解决。

硬编码访问栈地址

有一些公司开发软件的时候,觉得从NM_DBLCLK通知中获取坐标然后判断用户是否点击了树控件很麻烦,于是他们在得到的NMHDR结构体指针上直接加了一个60,然后从地址上获取一个DWORD数据,如果这个数据值为0,则他们会执行一个对应的操作,如果不是0,他们会执行另外一个操作。

实际上发生的是,这个NMHDR结构是分配在栈上的,他们的程序会访问栈上某些自动变量的值(可能是栈上的两个栈帧),然后使用获取到的值来决定他们的操作逻辑。

在Windows 2000时,我们升级了编译器的版本,新版本的编译器优化了栈上自动变量的重排序和重用,因此,他们的程序找不到他们想要的自动变量就不能正常工作了。

为了解决这个问题,我不得不创建一个特殊的NMHDR结构,让它看起来像他们所需要的样子,然后传输这个假的结构。我花了两天解决这个问题。

总结

我希望你能理解,为什么当人们建议依赖未文档化的结构时我会生气。

他们不是那种在车库里编写玩具软件的业余爱好者,上面提到的都是商业软件公司。当用户升级到下一个版本的Windows时,可能会遇到(a)磁盘损坏,(b)偶尔的资源管理器崩溃,或(c)喜欢的程序偶尔失去功能,那用户会认为是程序的问题,还是会归咎于Windows?

如果你说”程序有问题”,那么第一个问题,当然是找出是哪个程序。在上面的例子中,前面的两个很难看出来是他们的问题。

最后

Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一,里面有很多关于Windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。

本文来自:《When programs grovel into undocumented structures…》

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20200906A06B5400?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券