本文共 3652 字,大约阅读时间需要 12 分钟。
写主防时,为了拿到进程路径,所以查询发现一种发现一种方式是通过PID,调用PsLookupProcessByProcessId(ProcessId, &ProcessObj)拿到进程的EPROCESS,然后PsGetProcessImageFileName(ProcessObj)拿到进程进程路径。
现在看下PsLookupProcessByProcessId资料
kd> u PsLookupProcessByProcessId l 20 nt!PsLookupProcessByProcessId: 805ca38a 8bff mov edi,edi 805ca38c 55 push ebp 805ca38d 8bec mov ebp,esp 805ca38f 53 push ebx 805ca390 56 push esi 805ca391 64a124010000 mov eax,dword ptr fs:[00000124h] 805ca397 ff7508 push dword ptr [ebp+8] 805ca39a 8bf0 mov esi,eax 805ca39c ff8ed4000000 dec dword ptr [esi+0D4h] 805ca3a2 ff3560b25580 push dword ptr [nt!PspCidTable (8055b260)] 805ca3a8 e84bb50300 call nt!ExMapHandleToPointer (806058f8)
PsLookupProcessByHandle首先使APC无效
CurrentThread = PsGetCurrentThread ();
KeEnterCriticalRegionThread (&CurrentThread->Tcb);
然后调用了函数ExMapHandleToPointer函数,传入的参数就是PspCidTable系统句柄表的指针。
CidEntry = ExMapHandleToPointer(PspCidTable, ProcessId); if (CidEntry != NULL) { lProcess = (PEPROCESS)CidEntry->Object; if (lProcess->Pcb.Header.Type == ProcessObject && lProcess->GrantedAccess != 0) { if (ObReferenceObjectSafe(lProcess)) { *Process = lProcess; Status = STATUS_SUCCESS; } } ExUnlockHandleTableEntry(PspCidTable, CidEntry); }
ExMapHandleToPointer函数调用了ExpLookupHandleTableEntry函数,但是在之前做了参数检查
LocalHandle.GenericHandleOverlay = Handle; //会判断句柄的有效性 HandleTableEntry = ExpLookupHandleTableEntry( HandleTable, LocalHandle ); if (HandleTableEntry == NULL) { return NULL; }
ExMapHandleToPointer调用ExpLookupHandleTableEntry所做的事情就是在句柄表的三层结构中找到对应的对象,返回HANDLE_TABLE_ENTRY结构,再返回之后就会调用ExpLockHandleTableEntry函数来锁定当前的HANDLE_TABLE_ENTRY
HandleTableEntry = ExpLookupHandleTableEntry( HandleTable, LocalHandle ); if (HandleTableEntry == NULL) { return NULL; }
在ExpLockHandleTableEntry中就会调用InterlockedCompareExchangePointer,如果不成功,则可能是进程句柄处于被调试状态,可以通过HandleTableEntry中的debugInfo来判断句柄是否处于调试状态
if ((HandleTableEntry == NULL) || !ExpLockHandleTableEntry( HandleTable, HandleTableEntry)) { // // If we are debugging handle operations then save away the details // if (HandleTable->DebugInfo != NULL) { ExpUpdateDebugInfo(HandleTable, PsGetCurrentThread (), Handle, HANDLE_TRACE_DB_BADREF); } return NULL; }
如果处于调试状态,则用ExpUpdateDebugInfo函数填充HANDLE_TRACE_DEBUG_INFO结构,保存调试信息,否则返回NULL,调用失败
当函数调用成功就返回到PsLookupProcessByProcessId中,将HANDLE_TABLE_ENTRY中的Object转化成EPROCESS对象,确保这个对象是ProcessObject且有继承权,则引用计数加1
CidEntry = ExMapHandleToPointer(PspCidTable, ThreadId); Status = STATUS_INVALID_PARAMETER; if (CidEntry != NULL) { lThread = (PETHREAD)CidEntry->Object; if (lThread != (PETHREAD)PSP_INVALID_ID && lThread->Tcb.Header.Type == ThreadObject && lThread->GrantedAccess ) { ObReferenceObject(lThread); *Thread = lThread; Status = STATUS_SUCCESS; } ExUnlockHandleTableEntry(PspCidTable, CidEntry); }
然后装入参数EPROCESS,解锁当前的handle table entry,恢复当前内核线程的APC,成功返回。
PCHAR GetProcessNameByProcessId(HANDLE ProcessId){ NTSTATUS st=STATUS_UNSUCCESSFUL; PEPROCESS ProcessObj=NULL; PCHAR string=NULL; st = PsLookupProcessByProcessId(ProcessId, &ProcessObj); if(NT_SUCCESS(st)) { string = PsGetProcessImageFileName(ProcessObj); ObfDereferenceObject(ProcessObj); } return string;}
然后如上调用PsGetProcessImageFileName,得到进程路径。
参考资料
转载地址:https://blog.csdn.net/youyou519/article/details/96498505 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!