天天看點

列舉出所有程序(包括隐藏的)

其實隻要導出這些NativeAPI,在應用态也是可以用的。
           
本文來自看雪的某人誰不記得了不好意思了!
           
C/C++ code
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;
    //提升調試權限,否則有些程序,比如服務程序打不開    
    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(GetCurrentProcess(),(PVOID*)&pBuf,0,&buflen,MEM_COMMIT,PAGE_READWRITE);
      //查詢系統句柄資訊,類型為16
      status=ZwQuerySystemInformation(SystemHandleInformation,(PVOID)pBuf,buflen,&needlen);
      if (status==STATUS_SUCCESS)
      {
        break;
      }
      //不成功,則釋放記憶體
      //這裡隻要一塊大記憶體夠放這些内容就行,或者直接申請一塊足夠大的也可以
      //傳回的needlen可以做為參考
      ZwFreeVirtualMemory(GetCurrentProcess(),(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,
          (void **)(pSysHandleInfo->Handle),
          GetCurrentProcess(),
          &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 ((unsigned long)BasePsInfo.UniqueProcessId==dwProcessId)
          {
            //句柄所有者是我們要的目标程序,再按所需的權限複制過來
            ZwDuplicateObject(hOwnerProc,
            (void **)(pSysHandleInfo->Handle),
            GetCurrentProcess(),
            &hRetProcess,
            dwDesiredAccess,
            FALSE,
            0);
            //關掉為複制而打開的句柄所有者的句柄引用
            ZwClose(hOwnerProc);
            break;
          }
          
          }
    
        }
        }
      }
      pSysHandleInfo++;//指向下一個結構
    }
    if (pBuf)
    {
        ZwFreeVirtualMemory(GetCurrentProcess(),(PVOID*)&pBuf,&buflen,MEM_RELEASE);
    }
    return hRetProcess;
}