需要先把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;}