发新话题
打印

[原创]PsLookupProcessByProcessId执行流程学习笔记

[原创]PsLookupProcessByProcessId执行流程学习笔记

文章作者:sudami [xiao_rui_119@163.com]
信息来源:邪恶八进制信息安全团队(www.eviloctal.com

本来偶在学习内核线程调度的东西,发现里面有关于HANDLE_TABLE的知识.于是参照WRK把附带的一些东西深入学习了一下子--关于PsLookupProcessByProcessId的执行流程[写点心得存档,供以后学习的同学参考.老鸟飘过~]

NtOpenProcess->PsLookupProcessByProcessId->ExMapHandleToPointer->ExpLookupHandleTableEntry

关于RKARK,大概都很关注PsLookupProcessByProcessId吧.无论是HOOK还是DKOM,还是其他的,都先得把函数在底层的实现细节完全搞明白才行. so,the following may be helpful for you and me:

---->
进入PsLookupProcessByProcessId内,它有2个参数
   __in HANDLE ProcessId,            // 传进来进程ID
  __deref_out PEPROCESS *Process // 传出去进程的EPROCESS

首先使当前线程的内核APC无效,然后调用 ExMapHandleToPointer 函数.它有2个参数
  __in PHANDLE_TABLE HandleTable,
  __in HANDLE Handle

第1个参数传进来是全局变量 PspCidTable (它包含了系统所有进程的线程对象的指针);第2个参数传进来进程ID (它被赋予给 EXHANDLE 结构体中的 GenericHandleOverlay 变量)
---->
进入此函数后,将进程ID加入到 EXHANDLE 结构体中,进行必要的检查,确保ID的有效性:

EXHANDLE 是一个union, 其中的 Index 即是 GenericHandleOverlay 的低30位.这个检查是确保 2~109位存在,即3层表的0级的索引存在.

然后该函数调用 ExpLookupHandleTableEntry 函数,同样为此函数传递上面的2个参数,不过此时的第2个参数已经转换成另一种形式----EXHANDLE结构了.此函数做的工作才是重点,它负责通过索引在这个句柄3层表中寻找到指定的进程对象
[关于它的内部实现细节及注释过程, 句柄3层表,一些结构体。见附件]
最终它返回一个 HANDLE_TABLE_ENTRY 的地址,里面的前4字节包含了指定进程的对象地址.
---->
返回到 ExMapHandleToPointer 函数中后,此函数获得控制权,便接着往下执行.它会调用
ExpLockHandleTableEntry 来锁定当前的 handle table entry (InterlockedCompareExchangePointer ---->InterlockedCompareExchange).如果不成功或者ExpLookupHandleTableEntry返回结果为0,则可能是进程句柄处于被调试状态, 通过 HANDLE_TABLE 结构中的 DebugInfo 来判断当前句柄是否处于被调试状态.
若是,则调用 ExpUpdateDebugInfo 函数填充 HANDLE_TRACE_DEBUG_INFO 结构体以保存当前的调试信息; 否则返回NULL,调用失败.
当函数调用成功时,便返回从ExpLookupHandleTableEntry得到的HANDLE_TABLE_ENTRY 的地址.
---->
这样就回到了PsLookupProcessByProcessId函数中,它将 HANDLE_TABLE_ENTRY 中的Object转化为EPROCESS类型,确保这个对象是ProcessObject且有继承权限,将此对象的计数+1:


然后将此EPROCESS装入到参数2中, 解锁当前的handle table entry,恢复当前线程的内核APC,成功返回.


这个是用相机扫的图,用软件处理了下,懒得画了~~


-------------------------------------------------------------------------------------

这只是茫茫内核函数中的一个,相关联的还有比如很重要的PspTerminateThreadByPointer,大家可以参照WRK、reactOS学习,对理解RK运用DKOM这些手段会有更进一步的印象了~

附件

ExpLookupHandleTableEntry.rar (401 KB)

2008-1-9 20:19, 下载次数: 88

WINDOWS内核疯狂爱好者

TOP

顺便提一下:

用完 PsLookupProcessByProcessId 后记得要用 DereferenceObject 来减少引用计数

否则很可能BSOD

Win2k源码(private\ntos\ps\pscid.c)
Code Language : C
  1. NTSTATUS
  2. PsLookupProcessByProcessId(
  3.   IN HANDLE ProcessId,
  4.   OUT PEPROCESS *Process
  5.   )
  6.  
  7. /*++
  8.  
  9. Routine Description:
  10.  
  11.   This function accepts the process id of a process and returns a
  12.   referenced pointer to the process.
  13.  
  14. Arguments:
  15.  
  16.   ProcessId - Specifies the Process ID of the process.
  17.  
  18.   Process - Returns a referenced pointer to the process specified by the
  19.     process id.
  20.  
  21. Return Value:
  22.  
  23.   STATUS_SUCCESS - A process was located based on the contents of
  24.     the process id.
  25.  
  26.   STATUS_INVALID_PARAMETER - The process was not found.
  27.  
  28. --*/
  29.  
  30. {
  31.  
  32.   PHANDLE_TABLE_ENTRY CidEntry;
  33.   PEPROCESS lProcess;
  34.   NTSTATUS Status;
  35.  
  36.   CidEntry = ExMapHandleToPointer(PspCidTable, ProcessId);
  37.   Status = STATUS_INVALID_PARAMETER;
  38.   if (CidEntry != NULL) {
  39.     lProcess = (PEPROCESS)CidEntry->Object;
  40.     if (lProcess != (PEPROCESS)PSP_INVALID_ID && lProcess->Pcb.Header.Type == ProcessObject && lProcess->GrantedAccess ) {
  41.       ObReferenceObject(lProcess);
  42.       *Process = lProcess;
  43.       Status = STATUS_SUCCESS;
  44.     }
  45.  
  46.     ExUnlockHandleTableEntry(PspCidTable, CidEntry);
  47.   }
  48.  
  49.   return Status;
  50. }
Parsed in 0.007 seconds
是由代码中的这行:
      ObReferenceObject(lProcess);
导致的。

XP中用的是ObReferenceObjectSafe
类似的还有PsLookupThreadByThreadId
--->  伱 能 領 導 潮 流.  我 可 領 導 全 賕!  <---

TOP

哦。是啊,
XP下是ObReferenceObjectSafe

调用完后里面确实没有-1。

呵呵,谢谢提醒~
WINDOWS内核疯狂爱好者

TOP

发新话题