低级 C++除非在 XP 兼容模式下运行,否则应用程序在 Windows Vista/7 上崩溃

发布于 2024-08-19 21:31:57 字数 852 浏览 11 评论 0原文

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

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

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

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

编辑:

还有一件可能非常重要的事情要提:我从用户空间调用 DDK/内核函数,以获得未通过 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。

I have a low-level (like really low-level, it's basically all IOCTL calls and several calls to enumeration APIs) that crashes sporadically on Windows Vista/7 on clients' machines. Unfortunately, I have not been able to procure any crash dumps but one helpful user did mention that running the program in XP Compatibility Mode solved the problem.

The application is always launched with full admin rights (it's launched from another program that requires admin authorization) so it's not a UAC issue. I don't use any deprecated APIs and I'm not relying on any registry hacks, etc. I'm just issuing calls to enumerate disks, then using IOCTL commands to get some more low-level info about all attached devices.

What happens in XP Compatibility mode? What does Windows inject into my application or otherwise sandbox it with that prevents it from crashing on Vista/7? I had originally suspected heap corruption (though I've pulled my hair out attempting to replicate or to track down the issue) before being told that it runs fine in XP Compatibility Mode.

Can anyone suggest any possible issues that would be avoided in XP Compat Mode that I should look into to try to address this issue? Thanks!

EDIT:

One more thing that's probably very important to mention: I'm calling DDK/Kernel functions from userspace in order to get at certain features not exposed via the WIN32 API.

I'm using ZwReadFile, ZwCreateFile, ZwWriteFile, RtlInitUnicodeString, ZwQueryVolumeInformationFile, ZwDeviceIoControlFile, ZwSetInformationFile, ZwClose.

The IOCTLs I'm calling include IOCTL_DISK_GET_PARTITION_INFO_EX, IOCTL_STORAGE_GET_DEVICE_NUMBER, IOCTL_DISK_GET_LENGTH_INFO, and IOCTL_DISK_GET_DRIVE_LAYOUT_EX.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

南风几经秋 2024-08-26 21:31:57

这很奇怪,但我正在调用 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 个字符!),当使用 vector 作为时,这都会可靠地导致堆损坏甚至 FILE_FS_VOLUME_INFORMATION 缓冲区。

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

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

This is very odd, but I was calling ZwQueryVolumeInformationFile with FsInformationClass set to FileFsVolumeInformation.

I had passed in a buffer of FILE_FS_VOLUME_INFORMATION first normally allocated, then overallocated to (sizeof(FILE_FS_VOLUME_INFORMATION) + sizeof(TCHAR)*FILE_FS_VOLUME_INFORMATION->VolumeLabelLength).

Then I called
FILE_FS_VOLUME_INFORMATION->VolumeLabel[FILE_FS_VOLUME_INFORMATION->VolumeLabelLength/2] = _T('\0'); and only on some machines this would result in memory corruption.

Regardless of the size of the overallocation (even tried allocating a full 256 chars extra!), this would reliably result in heap corruption even when using a vector<unsigned char> as the FILE_FS_VOLUME_INFORMATION buffer.

It seems that the kernel places some sort of write protection on the buffer somehow that was resulting in corruption regardless of the size. Copying the first VolumeLableLength bytes to a second buffer, then post-pending _T('\0') solved the problem. Not sure how/why Windows was making the buffer that I allocated and passed in as a parameter readonly or if it was storing after the FILE_FS_VOLUME_INFORMATION struct (which should end with the character array!), but simply not modifying any data in the buffer that I passed did the trick.... which is crazy because it only happens (consistently and 100% reproducible) on certain machines.

At any rate: problem solved *phew*!

醉殇 2024-08-26 21:31:57

从XP到Vista,底层驱动程序发生了很多变化。我怀疑您使用的 IOCTL 受其影响。

There have been many changes in the low-level driver's from XP to vista. I suspect you are using an IOCTL that is affected by it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文