【文章标题】: Hook ExMapHandleToPointer,防止打开被保护进程和线程句柄
【文章作者】: ddlx
【作者邮箱】: DdlxStudio@163.com
【作者声明】: 失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  新发现的方法,不敢私藏特来分享。本人文学水平有限,大家就将就着看吧~

该方法在32位Xp,2003,Vista,Win7上测试通过。
  
  1. ExMapHandleToPointer
  ExMapHandleToPointer函数是通过句柄得到对应的对象地址。函数原型为:
  NTKERNELAPI PHANDLE_TABLE_ENTRY ExMapHandleToPointer ( IN PHANDLE_TABLE HandleTable,IN HANDLE Handle );
  在Vista以后的系统上,该函数的第一个参数通过edi传入。
  
  
  2. 为什么要Hook ExMapHandleToPointer?
  
  Hook ExMapHandleToPointer最大的好处是不光可以拦截上层通过NtOpenProcess打开进程句柄,也可以拦截驱动调用PsLookupProcessByProcessId得进程EPROCESS。
  比直接Hook SSDT中得NtOpenProcess或Hook PsLookupProcessByProcessId要好得多。并且虽然ExMapHandleToPointer函数是未导出的,但是定位容易。
  
  ExMapHandleToPointer函数是通过Pid或Tid得对应的EPROCESS或ETHREAD的关键函数。当然,其它句柄也是通过他得对象地址的。
  
  如PsLookupProcessByProcessId函数就先调用ExMapHandleToPointer函数从PspCidTable中得到Pid的对象地址,然后再取出EPROCESS地址。(PsLookupThreadByThreadId,PsLookupProcessThreadByCid同理)
  
  PsLookupProcessByProcessId源码:

代码:
  NTSTATUS PsLookupProcessByProcessId( IN HANDLE ProcessId, OUT PEPROCESS *Process )
  {
  
      PHANDLE_TABLE_ENTRY CidEntry;
      PEPROCESS lProcess;
      NTSTATUS Status;
  
      CidEntry = ExMapHandleToPointer(PspCidTable, ProcessId);
      Status = STATUS_INVALID_PARAMETER;
      if (CidEntry != NULL) {
          lProcess = (PEPROCESS)CidEntry->Object;
          if (lProcess != (PEPROCESS)PSP_INVALID_ID && lProcess->Pcb.Header.Type == ProcessObject && lProcess->GrantedAccess ) {
              ObReferenceObject(lProcess);
              *Process = lProcess;
              Status = STATUS_SUCCESS;
          }
  
          ExUnlockHandleTableEntry(PspCidTable, CidEntry);
      }
  
      return Status;
  }
  
  3. PspCidTable 是什么?怎么得到?
  
  PspCidTable是进程和线程ID的句柄表。每个进程Id或线程Id都能从该表中得到句柄对象。
  PspCidTable是一个全局变量。可以通过搜索特征码的方式搜索其位置.
  Xp或2003搜索方法:
  从PsLookupProcessByProcessId函数开始搜索特征码 0x35ff(2个字节,即汇编push dword ptr[g_pPspCidTableAddr]的指令码)。
  Vista或Win7搜索方法:
  从PsLookupProcessByProcessId函数开始搜索特征码 0x3d8b(2个字节,即汇编mov edi, dword ptr[g_pPspCidTableAddr]的指令码)。
  g_pPspCidTableAddr中保存的值就是PspCidTable。
  
  
  4. 定位ExMapHandleToPointer函数
  
  定位ExMapHandleToPointer函数很容易:从PsLookupProcessByProcessId函数开始搜索特征码 0xE8,即第一个Call既是。
  
  5. MyExMapHandleToPointer
  
  当前写好MyExMapHandleToPointer就可以开始Hook了,
代码:
  NTKERNELAPI PHANDLE_TABLE_ENTRY MyExMapHandleToPointer( IN PHANDLE_TABLE HandleTable,IN HANDLE Handle )
  {
  if( PsGetCurrentProcessId() == g_MyPid )
  {
  goto CALL;
  }
    if( HandleTable != g_PspCidTable )
  {
  goto CALL;
  }
  
  if( Handle == g_MyPid )
  {
  goto NOCALL;
  }
  if( Handle == g_MyTid )
  {
  goto NOCALL;
  }
  
  CALL:
  return RealExMapHandleToPointer( HandleTable, Handle );
  NOCALL:
  return NULL;
  }
  Vista以后的系统实现略有不同~
  
  
  另外:Hook ExMapHandleToPointer,还可以防止上层其它进程读写保护进程。这个就让各位发挥吧~
  
  欢迎拍砖,
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2011年11月12日 18:06:48