pslookupprocessbyprocessid

PsLookupProcessByProcessId执行流程学习笔记
本帖被 xIkUg 执行取消置顶操作(2008-01-14)
本来偶在学习内核线程调度的东西,发现里面有关于 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层表,一些结构体。见附件]
最终它返回一个 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这些手段会有更进一步的印象了~
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Windows C语言驱动可以通过调用PsLookupProcessByProcessId函数获取进程的EPROCESS结构体,然后通过EPROCESS结构体中的Peb字段获取进程的PEB结构体,最后通过PEB结构体中的ProcessParameters字段获取进程的命令行参数。具体实现可以参考以下代码: ``` NTSTATUS GetProcessCommandLine(PUNICODE_STRING pCommandLine, HANDLE hProcessId) { NTSTATUS status = STATUS_SUCCESS; PEPROCESS pEprocess = NULL; PPEB pPeb = NULL; PRTL_USER_PROCESS_PARAMETERS pProcessParameters = NULL; KAPC_STATE state; // 获取进程EPROCESS结构体 status = PsLookupProcessByProcessId(hProcessId, &pEprocess); if (!NT_SUCCESS(status)) { return status; } // 获取进程PEB结构体 KeStackAttachProcess((PKPROCESS)pEprocess, &state); pPeb = PsGetProcessPeb(pEprocess); if (pPeb == NULL) { KeUnstackDetachProcess(&state); ObDereferenceObject(pEprocess); return STATUS_UNSUCCESSFUL; } // 获取进程命令行参数 pProcessParameters = pPeb->ProcessParameters; if (pProcessParameters == NULL || pProcessParameters->CommandLine.Length == 0) { KeUnstackDetachProcess(&state); ObDereferenceObject(pEprocess); return STATUS_UNSUCCESSFUL; } // 复制命令行参数到输出参数 status = RtlUnicodeStringCopy(pCommandLine, &pProcessParameters->CommandLine); if (!NT_SUCCESS(status)) { KeUnstackDetachProcess(&state); ObDereferenceObject(pEprocess); return status; } KeUnstackDetachProcess(&state); ObDereferenceObject(pEprocess); return STATUS_SUCCESS; } ``` 调用该函数时,需要传入进程ID和一个UNICODE_STRING类型的输出参数pCommandLine,函数会将进程的命令行参数复制到pCommandLine中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值