通过GetProcessNameByProcessId得到进程路径
发布日期:2021-06-29 01:11:27 浏览次数:3 分类:技术文章

本文共 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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:ZwCreateFile报错0xC0000043,STATUS_SHARING_VIOLATION
下一篇:x64回调监控注册表

发表评论

最新留言

第一次来,支持一个
[***.219.124.196]2024年04月08日 00时25分34秒