需要先把Kthread中的PreviousMode的值置成KernelMode
因为调用CqEnumProcessInfoByMyOpenProcess这个函数的时候,是由应用层的程序调用DeviceIoControl进入内核的,所以要经过
Kifastcallentry,Kifastcallentry在执行中会把当前要进入内核的这个线程的PreviousMode设置成UserMode,所以当我调用NtOpenProcess时,NtOpenprocess在执行中会判断当前的调用模式,如果不改Kthread中的PreviousMode,NtOpenprocess发现是UserMode,所以要判断clientId则个参数的地址是不是用户层地址,当它发现这个地址是内核地址的时候,执行就是败了,所以要把当前线程的Ktrhead的PerviousMode这个值置成KernelMode,欺骗NtOpenProcess,,这样NtOpenProcess判断的时候就认为这个调用是内核的调用,所以就可以执行成功。
NTSTATUS CqEnumProcessInfoByMyOpenProcess(PPROCESS_INFO pProcessInfo)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
CLIENT_ID ClientId = {0};
ULONG i = 0;
HANDLE ProcessHandle = 0;
PEPROCESS Process = NULL;
PKTHREAD Kthread = NULL;
OBJECT_ATTRIBUTES ProcAttr = {0};
InitializeObjectAttributes(&ProcAttr, 0, 0, 0, 0);
Kthread = (PKTHREAD)PsGetCurrentThread();
*((PUCHAR)Kthread + CqGetOffset(enumPreviousModeOffsetByKthread)) = KernelMode;
for(i = 0; i < 65535; i++)
{
ClientId.UniqueProcess = (HANDLE)i;
Status = MyNtOpenProcess(&ProcessHandle, PROCESS_ALL_ACCESS , &ProcAttr, &ClientId);
if( STATUS_SUCCESS == Status )
{
Status = PsLookupProcessByProcessId(i, &Process);
if( STATUS_SUCCESS != Status )
{
goto Exit0;
}
Status = CqSetProcessInfoByEProcess(pProcessInfo, Process);
if( NULL != Process )
{
ObDereferenceObject(Process);
}
if( NULL != ProcessHandle )
{
ZwClose(ProcessHandle);
}
ProcessHandle = 0;
Process = 0;
i+=3;
}
else
{
continue;
}
}
*((PUCHAR)Kthread + CqGetOffset(enumPreviousModeOffsetByKthread)) = UserMode;
Status = STATUS_SUCCESS;
Exit0:
return Status;
}