这是我的功能:
PVOID QuerySystemInformation(SYSTEMINFOCLASS SystemEnum) {
DWORD MemorySize = NULL;
NTSTATUS Status = NtQuerySystemInformation(SystemEnum, NULL, 0, &MemorySize);
if (NT_SUCCESS(Status)) {
PVOID Memory = PVOID(Allocate(MemorySize));
if (Memory != ERROR) {
Status = NtQuerySystemInformation(SystemEnum, Memory, MemorySize, &MemorySize);
if (NT_SUCCESS(Status)) {
return Memory;
}
Free(Memory);
}
}
return ERROR;
}
我将SystemBasicInformation
传递给该函数。第一次调用NtQuerySystemInformation
后,我收到错误消息。 RtlNtStatusToDosError(Status)
的结果是24 (ERROR_BAD_LENGTH)
。问题在哪里?
答案 0 :(得分:1)
似乎没有问题 - 对于SystemInformationLength
参数为零的调用,会出现错误。
NtQuerySystemInformation
:
ReturnLength [out,optional] - 第4个参数
指向函数写入所请求信息的实际大小的位置的可选指针。如果该大小小于或等于SystemInformationLength参数,则该函数将信息复制到SystemInformation缓冲区中; 否则,它返回一个NTSTATUS错误代码,并在ReturnLength中返回接收所请求信息所需的缓冲区大小。
因此,请检查DWORD MemorySize
是否包含非零大小。
答案 1 :(得分:0)
只需删除
if (NT_SUCCESS(Status)) {
并将其替换为:
if(MemorySize){
答案 2 :(得分:0)
NtQuerySystemInformation
如果 SystemInformationLength 太小而无法保留信息返回错误STATUS_INFO_LENGTH_MISMATCH
。 ( RtlNtStatusToDosError(STATUS_INFO_LENGTH_MISMATCH)==ERROR_BAD_LENGTH
)
需要了解一些 SystemInformationClass 返回众所周知的固定大小的数据。例如 SystemBasicInformation
因此,您需要为此已修复尺寸信息类:
执行下一步操作SYSTEM_BASIC_INFORMATION sbi;
NTSTATUS status = ZwQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), 0);
if (0 <= status)
{
// do something
}
但是一些Information Class返回可变长度数据。所需的长度在开始时是未知的,STATUS_INFO_LENGTH_MISMATCH
这里是绝对正常错误(不是致命的)。您需要的可变长度信息类始终查询循环并检查STATUS_INFO_LENGTH_MISMATCH
的返回状态为条件继续循环:
do
{
...
status = ZwQuerySystemInformation(...);
...
} while (status == STATUS_INFO_LENGTH_MISMATCH);
为什么循环?因为在系统返回到您接收所请求信息所需的缓冲区大小之后,以及在使用此缓冲区大小再次调用ZwQuerySystemInformation
之前,所需长度可能会发生变化。
这个SystemProcessInformation
的明亮示例,它获取了有关系统中当前运行的所有进程和线程的信息。在系统返回所需的缓冲区大小后 - 新的线程或进程可以在系统中启动 - 因此可能需要更大的缓冲区。
我们可以通过以下方式查询此信息:
NTSTATUS QueryProcessInformation()
{
NTSTATUS status;
ULONG cb = 0x10000;
do
{
status = STATUS_INSUFFICIENT_RESOURCES;
if (void* buf = new BYTE[cb])
{
if (0 <= (status = ZwQuerySystemInformation(SystemProcessInformation, buf, cb, &cb)))
{
union {
PVOID pv;
PBYTE pb;
PSYSTEM_PROCESS_INFORMATION pspi;
};
pv = buf;
ULONG NextEntryOffset = 0;
do
{
pb += NextEntryOffset;
DbgPrint("%p %wZ\n", pspi->UniqueProcessId, &pspi->ImageName);
} while (NextEntryOffset = pspi->NextEntryOffset);
}
delete [] buf;
}
} while (status == STATUS_INFO_LENGTH_MISMATCH);
return status;
}
或者我们可以在堆栈中使用累积分配(这仅适用于我们拥有巨大堆栈大小的用户模式)
NTSTATUS QueryProcessInformation2()
{
NTSTATUS status;
union {
PVOID buf;
PBYTE pb;
PSYSTEM_PROCESS_INFORMATION pspi;
};
ULONG cb = 0, rcb = 0x10000;
volatile UCHAR guz;
PVOID stack = alloca(guz);
do
{
if (cb < rcb)
{
cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
}
if (0 <= (status = ZwQuerySystemInformation(SystemProcessInformation, buf, cb, &rcb)))
{
ULONG NextEntryOffset = 0;
do
{
pb += NextEntryOffset;
DbgPrint("%p %wZ\n", pspi->UniqueProcessId, &pspi->ImageName);
} while (NextEntryOffset = pspi->NextEntryOffset);
}
} while (status == STATUS_INFO_LENGTH_MISMATCH);
return status;
}