NtQuerySystemInformation获取SystemHandleInformation返回大小异常问询
NtQuerySystemInformation返回缓冲区大小异常问题解答
问题背景
执行以下代码时,首次调用NtQuerySystemInformation(对应SystemHandleInformation类,即0x10)无法返回正确的缓冲区大小,导致后续调用失败:
PSYSTEM_HANDLE_INFORMATION HandleInfo = NULL; ULONG HandleInfoLength = 0; ... result = NTQSI((SYSTEM_INFORMATION_CLASS)0x10, NULL, 0, &HandleInfoLength); if (result != 0xC0000004) { printf("OmmeSearchProcessHandle - NTQSI output is unexpected! Expexted : 0xC0000004 Result : 0x%x\n", result); return NULL; } printf("system handle info length : %i\n", HandleInfoLength); SIZE_T HandleInfoRegionSize = HandleInfoLength; result = NTAVM((HANDLE)(-1), (PVOID*)&HandleInfo, 0, &HandleInfoRegionSize, MEM_COMMIT, PAGE_READWRITE); if (!NT_SUCCESS(result)) { printf("OmmeSearchProcessHandle - NTAVM failed with result : %x\n", result); return NULL; } result = NTQSI((SYSTEM_INFORMATION_CLASS)0x10, (PVOID)HandleInfo, HandleInfoLength, &HandleInfoLength); if (!NT_SUCCESS(result)) { printf("OmmeSearchProcessHandle - NTQSI failed with result : %x\n", result); printf("system handle info length : %i\n", HandleInfoLength); return NULL; }
疑问解答
1. 首次调用返回大小不正确的原因
- 系统状态动态变化:
SystemHandleInformation对应系统内所有进程的句柄列表,从首次查询大小到分配内存、发起二次调用的间隙,系统可能已创建新进程、打开新资源,实际需要的缓冲区会比之前返回的HandleInfoLength更大。 - API设计特性:针对部分系统信息类,
NtQuerySystemInformation返回的大小只是近似值,并非严格精确的所需字节数,设计上存在模糊性,无法保证完全匹配后续调用的实际需求。
2. 是否属于业内共识
这确实是Windows内核开发领域的普遍共识:
- 针对
SystemHandleInformation这类动态性极强的信息类,成熟工具(比如Sysinternals的Handle工具)都不会依赖单次大小查询结果,而是采用循环重试策略:分配缓冲区后调用,若返回STATUS_INFO_LENGTH_MISMATCH(0xC0000004),就根据新返回的大小重新分配更大的缓冲区,直到调用成功。 - 你提到的项目开发者的说法,正是这种行业经验的直接体现——单次查询的大小根本赶不上系统状态的实时变化,必须做容错处理。
内容的提问来源于stack exchange,提问作者GetRektBoy724
相关产品推荐
相关产品推荐

