写主防时,为了拿到进程路径,所以查询发现一种发现一种方式是通过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://www.cnblogs.com/aliflycoris/p/5271417.html
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)