【旧文章搬运】超级无敌大炉子的LzOpenProcess

原文发表于百度空间,2008-11-20
==========================================================================

这个东西嘛,思路来自炉子,C版的最早貌似是sudami写的,我也写一个,练练手。
上次看到有人找资料时找到了我刚开博时的一篇挫文,并且引用到看雪上求助,令我汗颜不已,遂把这个代码加了N多注释,方便自己,也方便某些误打误撞到我这儿找资料的菜菜~

HANDLE LzOpenProcess(DWORD dwDesiredAccess,BOOL bInheritHandle, DWORD dwProcessId)
{
NTSTATUS status=0;
char *pBuf=NULL;
BOOLEAN wasEnabled;
DWORD buflen=0x10000,needlen=0;
DWORD HandleCnt=0;
HANDLE hRetProcess=0,hOwnerProc,hTmp;
PSYSTEM_HANDLE_INFORMATION pSysHandleInfo=NULL;
PROCESS_BASIC_INFORMATION BasePsInfo;
OBJECT_ATTRIBUTES objatr;
CLIENT_ID Cid;
//提升调试权限,否则有些进程,比如服务进程打不开
RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE,TRUE,FALSE,&wasEnabled);
InitializeObjectAttributes(&objatr,0,0,0,0);
//先尝试正常方式打开
Cid.UniqueProcess=(HANDLE)dwProcessId;
Cid.UniqueThread=0;
status=ZwOpenProcess(&hRetProcess,dwDesiredAccess,&objatr,&Cid);//尝试直接打开
if (NT_SUCCESS(status))
{
   return hRetProcess;
}
//不成功,尝试把PID加1再打开,加2,加3也可以
//理由:有些HOOK函数中过滤PID时不完善,正确的做法应该是先用掩码忽略低两位之后再比较
Cid.UniqueProcess=(HANDLE)(dwProcessId+1);
status=ZwOpenProcess(&hRetProcess,dwDesiredAccess,&objatr,&Cid);//尝试直接打开pid+1
if (NT_SUCCESS(status))
{
   return hRetProcess;
}
//都不成功,就找别的进程中的Handle,这才是本代码的核心, 这些Handle大部分是在Csrss.exe中
do 
{
   //申请查询句柄信息所需的内存
   ZwAllocateVirtualMemory(NtCurrentProcess(),(PVOID*)&pBuf,0,&buflen,MEM_COMMIT,PAGE_READWRITE);
   //查询系统句柄信息,类型为16
   status=ZwQuerySystemInformation(SystemHandleInformation,(PVOID)pBuf,buflen,&needlen);
   if (status==STATUS_SUCCESS)
   {
    break;
   }
   //不成功,则释放内存
   //这里只要一块大内存够放这些内容就行,或者直接申请一块足够大的也可以
   //返回的needlen可以做为参考
   ZwFreeVirtualMemory(NtCurrentProcess(),(PVOID*)&pBuf,&buflen,MEM_RELEASE);
   //然后把要申请的内存大小乘2,直至成功为止
   buflen*=2;
   pBuf=NULL;
} while(1);
//返回的缓冲区内容的第一个DWORD是总的句柄的个数
HandleCnt=*(DWORD*)pBuf;
//跳过句柄计数,才是真正的开始
pSysHandleInfo=(PSYSTEM_HANDLE_INFORMATION)((char*)pBuf+sizeof(DWORD));
for (DWORD i=0;i<HandleCnt;i++)
{
   //只验证类型为PROCESS的,值为5
   if (pSysHandleInfo->ObjectTypeNumber==OB_TYPE_PROCESS)
   {
    //打开这个句柄的所有者进程,要复制过来才能查询,否则只能看不能摸~
    Cid.UniqueProcess=(HANDLE)(pSysHandleInfo->ProcessId);
    Cid.UniqueThread=0;
    status=ZwOpenProcess(&hOwnerProc,PROCESS_DUP_HANDLE,&objatr,&Cid);
    if (NT_SUCCESS(status))
    {
     //打开成功,复制句柄到本进程,这里用了PROCESS_ALL_ACCESS以避免权限问题
     status=ZwDuplicateObject(hOwnerProc,
      (HANDLE)(pSysHandleInfo->Handle),
      NtCurrentProcess(),
      &hTmp,
      PROCESS_ALL_ACCESS,
      FALSE,
      0);
     if (NT_SUCCESS(status))
     {
      //复制成功,查询此句柄所对应的进程PID,查询基本信息即可
      status=ZwQueryInformationProcess(hTmp,ProcessBasicInformation,&BasePsInfo,sizeof(PROCESS_BASIC_INFORMATION),NULL);
      if (NT_SUCCESS(status))
      {
       //成功,判断其PID
       if (BasePsInfo.UniqueProcessId==dwProcessId)
       {
        //句柄所有者是我们要的目标进程,再按所需的权限复制过来
        ZwDuplicateObject(hOwnerProc,
         (HANDLE)(pSysHandleInfo->Handle),
         NtCurrentProcess(),
         &hRetProcess,
         dwDesiredAccess,
         FALSE,
         0);
        //关掉为复制而打开的句柄所有者的句柄引用
        ZwClose(hOwnerProc);
        break;
       }
      
      }

     }
    }
   }
   pSysHandleInfo++;//指向下一个结构
}
if (pBuf)
{
   ZwFreeVirtualMemory(NtCurrentProcess(),(PVOID*)&pBuf,&buflen,MEM_RELEASE);
}
return hRetProcess;
}



原文地址:https://www.cnblogs.com/achillis/p/10180415.html