C NtQuerySystemInformation返回24(错误\u错误\u长度)
以下是我的功能:C NtQuerySystemInformation返回24(错误\u错误\u长度),c,winapi,nt,C,Winapi,Nt,以下是我的功能: PVOID QuerySystemInformation(SYSTEMINFOCLASS SystemEnum) { DWORD MemorySize = NULL; NTSTATUS Status = NtQuerySystemInformation(SystemEnum, NULL, 0, &MemorySize); if (NT_SUCCESS(Status)) { PVOID Memory
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\u BAD\u LENGTH)
。问题出在哪里?只需删除即可
if (NT_SUCCESS(Status)) {
并将其替换为:
if(MemorySize){
似乎没有问题-使用零
SystemInformationLength
参数的调用会出现错误
MSDN说:
ReturnLength[输出,可选]-第四个参数
指向函数写入所请求信息的实际大小的位置的可选指针。如果该大小小于或等于SystemInformationLength参数,则函数将信息复制到SystemInformation缓冲区中否则,它将返回NTSTATUS错误代码,并以ReturnLength的形式返回接收请求信息所需的缓冲区大小。
因此,请检查DWORD MemorySize是否包含非零大小。如果系统信息长度太小,无法容纳信息返回错误状态信息长度不匹配。(RtlNtStatusToDosError(状态信息长度不匹配)=错误错误长度
)
需要了解一些SystemInformationClass返回众所周知的固定大小数据。例如系统基本信息
因此,您需要为这个固定的大小信息类执行下一步操作:
SYSTEM_BASIC_INFORMATION sbi;
NTSTATUS status = ZwQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), 0);
if (0 <= status)
{
// do something
}
为什么在循环中?因为在系统返回给您接收请求信息所需的缓冲区大小之后,以及在您再次使用此缓冲区大小调用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 QueryProcessInformation()
{
非关税国家地位;
ULONG cb=0x10000;
做
{
状态=状态资源不足;
if(void*buf=新字节[cb])
{
if(0 UniqueProcessId,&pspi->ImageName);
}而(NexteryOffset=pspi->NexteryOffset);
}
删除[]buf;
}
}而(状态==状态信息长度不匹配);
返回状态;
}
或者,我们也可以在堆栈中使用累积分配(这仅适用于用户模式,在这种模式下,我们有巨大的堆栈大小)
NTSTATUS QueryProcessInformation2()
{
非关税国家地位;
联合{
pvoidbuf;
PBYTE-pb;
PSI系统、过程、信息;
};
ULONG cb=0,rcb=0x10000;
易挥发的乌恰尔古兹;
PVOID stack=alloca(guz);
做
{
如果(cbImageName);
}而(NexteryOffset=pspi->NexteryOffset);
}
}而(状态==状态信息长度不匹配);
返回状态;
}
ooh。好的,非常感谢!我真傻,没注意文档!现在在同一个函数中,在调用Allocate()之后,我得到了0xc000005:Access违例读取位置0x4865764A
,是否有任何明显的说明这背后的原因?我只能猜测,因为我不知道您使用的是什么分配器以及错误发生的确切位置。您不能使用调试器吗?所以请检查DWORD MemorySize
-否。需要准确检查返回的状态以确定要执行的操作。这是错误。所有有条件的如果必须仅基于返回状态,请不要破坏您自己的帖子。更糟糕的是,您似乎得到了多个有用的答案。
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;
}