3

我有一个低级(就像真正的低级,它基本上是所有 IOCTL 调用和对枚举 API 的几个调用),在客户端机器上的 Windows Vista/7 上偶尔崩溃。不幸的是,我无法获得任何故障转储,但一位乐于助人的用户确实提到在 XP 兼容模式下运行程序解决了这个问题。

该应用程序始终以完全管理员权限启动(它是从另一个需要管理员授权的程序启动的),因此这不是 UAC 问题。我不使用任何已弃用的 API,也不依赖任何注册表黑客等。我只是发出调用以枚举磁盘,然后使用 IOCTL 命令获取有关所有连接设备的更多低级信息。

XP 兼容模式下会发生什么?Windows 将什么注入我的应用程序或以其他方式将其沙箱化以防止它在 Vista/7 上崩溃?在被告知它在 XP 兼容模式下运行良好之前,我最初怀疑堆损坏(尽管我已经拔出头发试图复制或追踪问题)。

任何人都可以建议在 XP 兼容模式下可以避免的任何可能的问题,我应该考虑尝试解决这个问题吗?谢谢!

编辑:

还有一件事可能非常重要:我正在从用户空间调用 DDK/Kernel 函数,以便获得某些未通过 WIN32 API 公开的功能。

我正在使用 ZwReadFile、ZwCreateFile、ZwWriteFile、RtlInitUnicodeString、ZwQueryVolumeInformationFile、ZwDeviceIoControlFile、ZwSetInformationFile、ZwClose。

我调用的 IOCTL 包括 IOCTL_DISK_GET_PARTITION_INFO_EX、IOCTL_STORAGE_GET_DEVICE_NUMBER、IOCTL_DISK_GET_LENGTH_INFO 和 IOCTL_DISK_GET_DRIVE_LAYOUT_EX。

4

2 回答 2

1

这很奇怪,但我在调用 ZwQueryVolumeInformationFile 时将 FsInformationClass 设置为 FileFsVolumeInformation。

我传入了一个 FILE_FS_VOLUME_INFORMATION 的缓冲区,首先正常分配,然后过度分配到(sizeof(FILE_FS_VOLUME_INFORMATION) + sizeof(TCHAR)*FILE_FS_VOLUME_INFORMATION->VolumeLabelLength).

然后我打电话 FILE_FS_VOLUME_INFORMATION->VolumeLabel[FILE_FS_VOLUME_INFORMATION->VolumeLabelLength/2] = _T('\0');只有在某些机器上这会导致内存损坏。

不管过度分配的大小(甚至尝试额外分配完整的 256 个字符!),即使使用 avector<unsigned char>作为 FILE_FS_VOLUME_INFORMATION 缓冲区,这也会可靠地导致堆损坏。

似乎内核以某种方式在缓冲区上设置了某种写保护,这导致无论大小如何都导致损坏。将第一个 VolumeLableLength 字节复制到第二个缓冲区,然后post-pending_T('\0')解决了这个问题。不知道 Windows 如何/为什么将分配并作为参数传入的缓冲区设置为只读,或者它是否存储FILE_FS_VOLUME_INFORMATION 结构之后(应该以字符数组结尾!),但只是不修改缓冲区中的任何数据我通过了这个技巧......这很疯狂,因为它只在某些机器上发生(一致且 100% 可重现)。

无论如何:问题解决了*呼*!

于 2010-02-23T16:14:31.770 回答
0

从 XP 到 vista 的低级驱动程序发生了许多变化。我怀疑您正在使用受它影响的 IOCTL。

于 2010-01-30T19:29:28.273 回答