我尝试使用内核模式驱动程序查找FindProcessidByName,有时ImageName.Buffer变为NULL,因此,当ImageName.Buffer变为NULL时,我无法找到进程ID。你有没有想过ImageName.Buffer有时为什么会变成NULL,先生?
typedef struct _SYSTEM_PROCESS_INFO_L
{
ULONG NextEntryOffset;
ULONG NumberOfThreads;
LARGE_INTEGER Reserved[3];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ImageName;
ULONG BasePriority;
HANDLE ProcessId;
HANDLE InheritedFromProcessId;
}_SYSTEM_PROCESS_INFO_L, *P_SYSTEM_PROCESS_INFO_L;
HANDLE LSFindProcess(LPSTR name)
{
NTSTATUS durum;
ULONG retsize;
HANDLE hProcid = -1;
P_SYSTEM_PROCESS_INFO_L pi;
durum = ZwQuerySystemInformation(SystemProcessInformation, NULL, NULL, &retsize); // request how much memory size we need.
if (!NT_SUCCESS(durum) && durum !=STATUS_INFO_LENGTH_MISMATCH)
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "LS : ZwQuerySystemInformation Failed 1 durum : %p \n",durum);
return -1;
}
PVOID memPtr;
memPtr = ExAllocatePool(PagedPool, retsize);
if (!memPtr)
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "LS : ExAllocatePool Failed \n");
return -1;
}
memset(memPtr, 0, retsize);// zero mem
durum = ZwQuerySystemInformation(SystemProcessInformation, memPtr, retsize, NULL);
pi = (P_SYSTEM_PROCESS_INFO_L)memPtr; // parselliyorz
if (!NT_SUCCESS(durum))
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "LS : ZwQuerySystemInformation Failed 2 durum : %p \n", durum);
return -1;
}
while (pi->NextEntryOffset)
{
if (pi->ImageName.Buffer) //some process null if I dont use this I am getting BSOD.
{
if (!_stricmp(pi->ImageName.Buffer, name))
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "LS : name %ws , pid : %d \n", pi->ImageName.Buffer, pi->ProcessId);
hProcid = pi->ProcessId; // pid
break; // foundedd
}
}
pi = (P_SYSTEM_PROCESS_INFO_L)((unsigned char*)pi + pi->NextEntryOffset);
}
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "LS : LSFindProcess bitti \n");
return hProcid;
}
答案 0 :(得分:2)
ZwQuerySystemInformation is Not working Properly
this is of course false. api working properly. if you got wrong results, this is only due errors in code. in concrete code spinet exist several errors.
in kernel mode exist difference between Zw and Nt api - need understand which version need call, if both (like in this concrete case) is exported. if you know that previous mode is kernel mode - need use Nt version. if you don't know previous mode in this point(at compile time) or previous mode user mode - need use Zw version. however this is general note and will be not error always call Zw
the first serious error - this is how ZwQuerySystemInformation
called - first time for query requested buffer size retsize
(in code) and second time already with this buffer size. but between this calls new threads and processes can be spawn in system. as result returned buffer size can be already not large enough. correct solution - call this api in loop, while it return STATUS_INFO_LENGTH_MISMATCH
the second - memory always must be free. especially in kernel mode. say that code incomplete - no excuse. code can be incomplete and intermediate, but free memory after allocation always must be immediately inserted
else one critical error - while (pi->NextEntryOffset)
loop - with this loop we always lost (not process) the last entry (last created process). need change this.
if (pi->ImageName.Buffer) //some process null if I dont use this I am getting BSOD.
the ImageName
is UNICODE_STRING
and need work with it respectively. in case ImageName.Buffer
the ImageName.Length
is also 0. the UNICODE_STRING ImageName;
is correct. incorrect only how you use it.
!_stricmp(pi->ImageName.Buffer, name); // ??
the pi->ImageName.Buffer
is PWSTR
so it can not be used with _stricmp
as a matter of principle. think you use c compiler - c++ simply give you error here. but even use _wcsicmp
is incorrect here - again pi->ImageName
is UNICODE_STRING
and need use RtlEqualUnicodeString(&pi->ImageName, name, TRUE)
where name must be of course PCUNICODE_STRING
but not PCSTR
or PSTR
or even PCWSTR
. if you have PCWSTR name
as input - you need wrap it to UNICODE_STRING
before call this api. example of code:
NTSTATUS LSFindProcess(PCUNICODE_STRING ImageName, PHANDLE UniqueProcessId)
{
ULONG cb = 0x20000;
PVOID buf;
NTSTATUS status;
do
{
status = STATUS_INSUFFICIENT_RESOURCES;
if (buf = ExAllocatePool(PagedPool, cb))
{
if (0 <= (status = NtQuerySystemInformation(SystemProcessInformation, buf, cb, &cb)))
{
union {
PVOID pv;
PBYTE pb;
PSYSTEM_PROCESS_INFORMATION pspi;
};
pv = buf;
ULONG NextEntryOffset;
goto __0;
do
{
pb += NextEntryOffset;
__0:
if (RtlEqualUnicodeString(&pspi->ImageName, ImageName, TRUE))
{
*UniqueProcessId = pspi->UniqueProcessId;
break;
}
} while (NextEntryOffset = pspi->NextEntryOffset);
}
ExFreePool(buf);
}
} while (status == STATUS_INFO_LENGTH_MISMATCH);
return status;
}
NTSTATUS LSFindProcess(PCWSTR ImageName, PHANDLE UniqueProcessId)
{
UNICODE_STRING us;
RtlInitUnicodeString(&us, ImageName);
return LSFindProcess(&us, UniqueProcessId);
}
答案 1 :(得分:-1)
你不应该调用ZwQuerySystemInformation,它不容易在Windows操作系统上移植,甚至可能在其中一些上不可用。 MSDN documentation for this function建议您使用其他功能。
答案 2 :(得分:-1)
感谢大家特别是@RbMm感谢信息。 完成的代码我希望这篇文章可以帮助别人..
/// <summary>
/// Struct SystemProcessInformation
/// </summary>
typedef struct _SYSTEM_PROCESS_INFO_L
{
ULONG NextEntryOffset;
ULONG NumberOfThreads;
LARGE_INTEGER Reserved[3];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ImageName;
ULONG BasePriority;
HANDLE ProcessId;
HANDLE InheritedFromProcessId;
}_SYSTEM_PROCESS_INFO_L, *P_SYSTEM_PROCESS_INFO_L;
/// <summary>
/// Find Process ID By Name , thanks @RbMm
/// </summary>
/// <param name="imagename">Process name </param>
/// <param name="pid">Output Process id</param>
/// <returns>NTSTATUS.</returns>
NTSTATUS LSFindProcessIdByName(IN PCWSTR imagename, OUT PHANDLE pid)
{
NTSTATUS durum = STATUS_UNSUCCESSFUL;
ULONG qmemsize = 0x1024;
PVOID qmemptr = 0;
P_SYSTEM_PROCESS_INFO_L spi;
UNICODE_STRING uimagename;
RtlInitUnicodeString(&uimagename, imagename); // @RbMm
*pid = -1;
do
{
qmemptr = ExAllocatePool(PagedPool, qmemsize); // alloc memory for spi
if (qmemptr == NULL) // check memory is allocated or not.
{
return STATUS_UNSUCCESSFUL;
}
durum = ZwQuerySystemInformation(SystemProcessInformation,qmemptr, qmemsize, NULL);
if (durum == STATUS_INFO_LENGTH_MISMATCH)
{
qmemsize = qmemsize * 2; // increase qmemsize for next memory alloc
ExFreePool(qmemptr); // free memory
}
} while (durum == STATUS_INFO_LENGTH_MISMATCH); // resize memory
spi = (P_SYSTEM_PROCESS_INFO_L)qmemptr;
while(1)
{
if (RtlEqualUnicodeString(&uimagename, &spi->ImageName, TRUE)) // @RbMm
{
*pid = spi->ProcessId;
break;
}
if (spi->NextEntryOffset == 0)
break;
spi = (P_SYSTEM_PROCESS_INFO_L)((unsigned char*)spi + spi->NextEntryOffset); // next info
}
if (!NT_SUCCESS(durum))
{
ExFreePool(qmemptr); // free memory
return STATUS_UNSUCCESSFUL;
}
ExFreePool(qmemptr); // free memory
return STATUS_SUCCESS;
}