簡體   English   中英

如何獲得給定進程的窗口站?

[英]How to get window station for a given process?

比如說,如果我有一個進程 ID 或者它的句柄,我能得到進程運行所在的窗口站嗎?

不是直截了當,但試試這個:

  1. 調用EnumWindowStations()以枚舉與調用進程相同的 Session 中的可用窗口站(如果您需要查詢另一個 Session 中的進程,則這將不起作用)。

  2. 對於每個窗口站,調用EnumDesktops()以枚舉其桌面。

  3. 對於每個桌面,調用EnumDesktopWindows()以枚舉其頂級窗口。

  4. 對於每個窗口,調用GetWindowThreadProcessId()以獲取其進程 ID 並將其與您要查找的 ID 進行比較。

另一種選擇可能是執行以下操作:

  1. 調用OpenProcess()從目標進程 ID 獲取HANDLE

  2. 調用NtQueryInformationProcess()來檢索進程的PEB結構的地址。

  3. 調用ReadProcessMemory()讀取PEB 它的ProcessParams.DesktopName字段包含當前與進程關聯的工作站/桌面的名稱PEB.ProcessParams中有更多的字段可用,然后 MSDN 顯示)。

  4. 解析DesktopName以提取窗口站和桌面名稱。

  5. 根據需要枚舉工作站,從GetUserObjectInformation()查找匹配的名稱。

好吧,這個不適合膽小的人。 這是我在@RemyLebeau 的建議之后想出的代碼。 事實證明,對於 32/64 位進程,我需要以不同的方式執行此操作。 我找不到 64 位進程的確切 PEB 結構,所以我做了一些基本的逆向工程來匹配它。

還有一個很有趣的結果:

  1. 如果我為我自己的進程調用它,我會得到這樣的東西: Winsta0\\Default
  2. 如果我在其他一些 GUI 進程上調用它,我會得到這個: Default

總體而言,您可以獲得以下類型的桌面/winstation:

  • 常規輸入桌面的Default (您現在正在使用)
  • WinlogonWinsta0\\Winlogon用於安全桌面(例如,Windows 登錄屏幕)
  • Metro(或現代 UI)Windows 8 應用程序的""或空字符串。

所以接下來是代碼。 如果有人可以評論它會很好:

//'dwProcID' = process ID to look up window station for
HANDLE hProc = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcID);
if(hProc)
{
    BOOL (WINAPI *pfnIsWow64Process)(HANDLE, PBOOL);

    (FARPROC&)pfnIsWow64Process = ::GetProcAddress(::GetModuleHandle(L"kernel32.dll"), "IsWow64Process");

    SYSTEM_INFO si = {0};
    ::GetNativeSystemInfo(&si);

    //See if 32-bit process on 64-bit OS
    BOOL bWow64Proc = TRUE;
    if(si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
    {
        if(pfnIsWow64Process)
            if(!pfnIsWow64Process(hProc, &bWow64Proc))
            {
                //Error
                _tprintf(L"ERROR in IsWow64Process: %d\n", ::GetLastError());
            }
    }

    NTSTATUS ntStatus;


    if(bWow64Proc)
    {
        //32-bit process
        NTSTATUS (WINAPI *pfnNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);
        (FARPROC&)pfnNtQueryInformationProcess = ::GetProcAddress(::GetModuleHandle(L"Ntdll.dll"), "NtQueryInformationProcess");
        if(pfnNtQueryInformationProcess)
        {
            PROCESS_BASIC_INFORMATION pbi = {0};
            DWORD dwsz = 0;
            if((ntStatus = pfnNtQueryInformationProcess(hProc, ProcessBasicInformation, &pbi, sizeof(pbi), &dwsz)) == 0 &&
                dwsz <= sizeof(pbi) &&
                pbi.PebBaseAddress)
            {
                //Define PEB structs
                typedef struct _RTL_DRIVE_LETTER_CURDIR
                {
                    WORD Flags;
                    WORD Length;
                    ULONG TimeStamp;
                    STRING DosPath;
                } RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR;

                struct RTL_USER_PROCESS_PARAMETERS_32
                {
                    ULONG                   MaximumLength;
                    ULONG                   Length;
                    ULONG                   Flags;
                    ULONG                   DebugFlags;
                    PVOID                   ConsoleHandle;
                    ULONG                   ConsoleFlags;
                    HANDLE                  StdInputHandle;
                    HANDLE                  StdOutputHandle;
                    HANDLE                  StdErrorHandle;
                    UNICODE_STRING          CurrentDirectoryPath;
                    HANDLE                  CurrentDirectoryHandle;
                    UNICODE_STRING          DllPath;
                    UNICODE_STRING          ImagePathName;
                    UNICODE_STRING          CommandLine;
                    PVOID                   Environment;
                    ULONG                   StartingPositionLeft;
                    ULONG                   StartingPositionTop;
                    ULONG                   Width;
                    ULONG                   Height;
                    ULONG                   CharWidth;
                    ULONG                   CharHeight;
                    ULONG                   ConsoleTextAttributes;
                    ULONG                   WindowFlags;
                    ULONG                   ShowWindowFlags;
                    UNICODE_STRING          WindowTitle;
                    UNICODE_STRING          DesktopName;
                    UNICODE_STRING          ShellInfo;
                    UNICODE_STRING          RuntimeData;
                    RTL_DRIVE_LETTER_CURDIR DLCurrentDirectory[0x20];
                };

                struct PEB_32
                {
                  BYTE                          Reserved1[2];
                  BYTE                          BeingDebugged;
                  BYTE                          Reserved2[1];
                  PVOID                         Reserved3[2];
                  void*                         Ldr;
                  RTL_USER_PROCESS_PARAMETERS_32* ProcessParameters;
                  BYTE                          Reserved4[104];
                  PVOID                         Reserved5[52];
                  void*                         PostProcessInitRoutine;
                  BYTE                          Reserved6[128];
                  PVOID                         Reserved7[1];
                  ULONG                         SessionId;
                };

                //Read PEB-32
                PEB_32 peb32 = {0};

                DWORD dwcbSzRead = 0;
                if(ReadProcessMemory(hProc, pbi.PebBaseAddress, &peb32, sizeof(peb32), &dwcbSzRead) &&
                    dwcbSzRead == sizeof(peb32) &&
                    peb32.ProcessParameters)
                {
                    //Read RTL_USER_PROCESS_PARAMETERS_32
                    RTL_USER_PROCESS_PARAMETERS_32 rupp32 = {0};

                    dwcbSzRead = 0;
                    if(ReadProcessMemory(hProc, peb32.ProcessParameters, &rupp32, sizeof(rupp32), &dwcbSzRead) &&
                        dwcbSzRead == sizeof(rupp32) &&
                        rupp32.DesktopName.Buffer)
                    {
                        //Get desktop name
                        int ncbSzLn = rupp32.DesktopName.Length + sizeof(TCHAR);
                        BYTE* pDesktopName = new (std::nothrow) BYTE[ncbSzLn];
                        if(pDesktopName)
                        {
                            dwcbSzRead = 0;
                            if(ReadProcessMemory(hProc, rupp32.DesktopName.Buffer, pDesktopName, ncbSzLn, &dwcbSzRead) &&
                                dwcbSzRead == ncbSzLn)
                            {
                                //Set last NULL
                                *(TCHAR*)(pDesktopName + ncbSzLn - sizeof(TCHAR)) = 0;

                                //We're done
                                _tprintf(L"Desktop32: %s\n", (LPCTSTR)pDesktopName);
                            }
                            else
                                _tprintf(L"ERROR in ReadProcessMemory DesktopName: %d\n", ::GetLastError());

                            delete[] pDesktopName;
                        }
                        else
                            _tprintf(L"ERROR DesktopName ptr\n");
                    }
                    else
                        _tprintf(L"ERROR in ReadProcessMemory RTL_USER_PROCESS_PARAMETERS_32: %d\n", ::GetLastError());
                }
                else
                    _tprintf(L"ERROR in ReadProcessMemory PEB-32: %d\n", ::GetLastError());
            }
            else
                _tprintf(L"ERROR in NtQueryInformationProcess: %d\n", ntStatus);
        }
        else
            _tprintf(L"ERROR NtQueryInformationProcess API\n");
    }
    else
    {
        //64-bit process
        NTSTATUS (WINAPI *pfnNtQueryInformationProcess64)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);
        NTSTATUS (WINAPI *pfnNtWow64ReadVirtualMemory64)(HANDLE, PVOID64, PVOID, ULONG64, PULONG64);

        (FARPROC&)pfnNtQueryInformationProcess64 = ::GetProcAddress(::GetModuleHandle(L"Ntdll.dll"), "NtWow64QueryInformationProcess64");
        (FARPROC&)pfnNtWow64ReadVirtualMemory64 = ::GetProcAddress(::GetModuleHandle(L"Ntdll.dll"), "NtWow64ReadVirtualMemory64");

        if(pfnNtQueryInformationProcess64 &&
            pfnNtWow64ReadVirtualMemory64)
        {
            //Define PEB structs
            struct UNICODE_STRING_64 {
                USHORT Length;
                USHORT MaximumLength;
                PVOID64 Buffer;
            };

            struct PROCESS_BASIC_INFORMATION64
            {
                PVOID Reserved1[2];
                PVOID64 PebBaseAddress;
                PVOID Reserved2[4];
                ULONG_PTR UniqueProcessId[2];
                PVOID Reserved3[2];
            };

            PROCESS_BASIC_INFORMATION64 pbi64 = {0};
            DWORD dwsz = 0;
            if((ntStatus = pfnNtQueryInformationProcess64(hProc, ProcessBasicInformation, &pbi64, sizeof(pbi64), &dwsz)) == 0 &&
                dwsz <= sizeof(pbi64))
            {
                struct PEB_64
                {
                    UCHAR               InheritedAddressSpace;
                    UCHAR               ReadImageFileExecOptions;
                    UCHAR               BeingDebugged;
                    BYTE                b003;
                    ULONG               Reserved0;
                    ULONG64             Mutant;
                    ULONG64             ImageBaseAddress;
                    ULONG64             Ldr;
                    PVOID64             ProcessParameters;
                };

                //Read PEB-64
                PEB_64 peb64 = {0};

                ULONG64 uicbSzRead = 0;
                if(pfnNtWow64ReadVirtualMemory64(hProc, pbi64.PebBaseAddress, &peb64, sizeof(peb64), &uicbSzRead) == 0 &&
                    uicbSzRead == sizeof(peb64) &&
                    peb64.ProcessParameters)
                {
                    //Don't know the structure of RTL_USER_PROCESS_PARAMETERS_64 thus read raw bytes
                    const int ncbSz_rawRUPP64 = sizeof(DWORD) * (6 * 8) + sizeof(UNICODE_STRING_64);
                    BYTE rawRUPP64[ncbSz_rawRUPP64] = {0};

                    uicbSzRead = 0;
                    if(pfnNtWow64ReadVirtualMemory64(hProc, peb64.ProcessParameters, &rawRUPP64, ncbSz_rawRUPP64, &uicbSzRead) == 0 &&
                        uicbSzRead == ncbSz_rawRUPP64)
                    {
                        //Point to the location in raw byte array
                        UNICODE_STRING_64* pDesktopName = (UNICODE_STRING_64*)(rawRUPP64 + sizeof(DWORD) * (6 * 8));

                        //Get desktop name
                        int ncbSzLn = pDesktopName->Length + sizeof(TCHAR);
                        BYTE* pBytesDesktopName = new (std::nothrow) BYTE[ncbSzLn];
                        if(pBytesDesktopName)
                        {
                            uicbSzRead = 0;
                            if(pfnNtWow64ReadVirtualMemory64(hProc, pDesktopName->Buffer, pBytesDesktopName, ncbSzLn, &uicbSzRead) == 0 &&
                                uicbSzRead == ncbSzLn)
                            {
                                //Set last NULL
                                *(TCHAR*)(pBytesDesktopName + ncbSzLn - sizeof(TCHAR)) = 0;
                                LPCTSTR pStrDesktopName = (LPCTSTR)pBytesDesktopName;

                                //We're done
                                _tprintf(L"Desktop64: %s\n", pStrDesktopName);
                            }
                            else
                                _tprintf(L"ERROR in NtWow64ReadVirtualMemory64 DesktopName: %d\n", ::GetLastError());

                            delete[] pBytesDesktopName;
                        }
                        else
                            _tprintf(L"ERROR DesktopName64 ptr\n");
                    }
                    else
                        _tprintf(L"ERROR in NtWow64ReadVirtualMemory64 RTL_USER_PROCESS_PARAMETERS_32: %d\n", ::GetLastError());
                }
                else
                    _tprintf(L"ERROR in NtWow64ReadVirtualMemory64 PEB-64: %d\n", ::GetLastError());
            }
            else
                _tprintf(L"ERROR in NtQueryInformationProcess64: %d\n", ntStatus);
        }
        else
            _tprintf(L"ERROR NtWow64QueryInformationProcess64 API\n");
    }

    ::CloseHandle(hProc);
}
else
    _tprintf(L"ERROR in OpenProcess: %d\n", ::GetLastError());

按照您的鏈接,以下頁面可能會有所幫助:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms684859(v=vs.85).aspx

進程不在窗口站下運行,而是窗口站與進程“關聯”。

似乎沒有任何直接方法可以找到與給定進程關聯的窗口站。

我看到兩個選項:

  • 使用代碼注入在目標進程中運行GetProcessWindowStationGetUserObjectInformation

  • 使用EnumWindowStationsEnumDesktopsEnumDesktopWindows遍歷會話中的所有窗口; 然后使用GetWindowThreadProcessId並將進程 ID 與目標進程的進程 ID 進行比較。 當然,如果進程當前沒有窗口,這將不起作用。

您也可以嘗試使用GetThreadDesktopGetUserObjectInformation來獲取桌面名稱; 我不確定這是否包括窗口站名稱。 如果這樣做有效,請參閱 MSDN 中的遍歷線程列表以枚舉屬於該進程的線程。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM