代码之家  ›  专栏  ›  技术社区  ›  Benj

返回空字符串的WTSQuerySessionInformation

  •  3
  • Benj  · 技术社区  · 14 年前

    我已经编写了一个程序,它应该查询终端服务API并打印出一些关于终端服务盒上运行的会话的状态信息。我正在使用WTSQuerySessionInformation函数来执行此操作,它返回一些数据,但大部分数据似乎丢失了。。。有人知道为什么吗?

    以下是我的程序:

    void WTSGetString( HANDLE serverHandle, DWORD sessionid, WTS_INFO_CLASS command, wchar_t* commandStr) 
    {
        DWORD bytesReturned = 0;
        LPTSTR pData = NULL;
        if (WTSQuerySessionInformation(serverHandle, sessionid, command, &pData, &bytesReturned))
        {
            wprintf(L"\tWTSQuerySessionInformationW - session %d - %s returned \"%s\"\n", sessionid, commandStr, pData);    
        }
        else
        {
            wprintf(L"\tWTSQuerySessionInformationW - session %d - %s failed - error=%d - ", sessionid, commandStr, GetLastError());
            printLastError(NULL, GetLastError());
        }
        WTSFreeMemory(pData);
    }
    
    
    void ExtractFromWTS( HANDLE serverHandle, DWORD sessionid ) 
    {
    
        WTSGetString(serverHandle, sessionid, WTSInitialProgram, L"WTSInitialProgram");
        WTSGetString(serverHandle, sessionid, WTSApplicationName, L"WTSApplicationName");
        WTSGetString(serverHandle, sessionid, WTSWorkingDirectory, L"WTSWorkingDirectory");
        WTSGetString(serverHandle, sessionid, WTSOEMId, L"WTSOEMId");
        WTSGetString(serverHandle, sessionid, WTSSessionId, L"WTSSessionId");
        WTSGetString(serverHandle, sessionid, WTSUserName, L"WTSUserName");
        WTSGetString(serverHandle, sessionid, WTSWinStationName, L"WTSWinStationName");
        WTSGetString(serverHandle, sessionid, WTSDomainName, L"WTSDomainName");
        WTSGetString(serverHandle, sessionid, WTSConnectState, L"WTSConnectState");
        WTSGetString(serverHandle, sessionid, WTSClientBuildNumber, L"WTSClientBuildNumber");
        WTSGetString(serverHandle, sessionid, WTSClientName, L"WTSClientName");
        WTSGetString(serverHandle, sessionid, WTSClientDirectory, L"WTSClientDirectory");
        WTSGetString(serverHandle, sessionid, WTSClientProductId, L"WTSClientProductId");
        WTSGetString(serverHandle, sessionid, WTSClientHardwareId, L"WTSClientHardwareId");
        WTSGetString(serverHandle, sessionid, WTSClientAddress, L"WTSClientAddress");
        WTSGetString(serverHandle, sessionid, WTSClientDisplay, L"WTSClientDisplay");
        WTSGetString(serverHandle, sessionid, WTSClientProtocolType, L"WTSClientProtocolType");
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        PWTS_SESSION_INFOW ppSessionInfo = 0;
        DWORD pCount;
        if(!WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &ppSessionInfo, &pCount))
        {
            printLastError(L"WTSEnumerateSessions", GetLastError());
            return 1;
        }
    
        wprintf(L"%d WTS sessions found on host\n", pCount);
    
        for (unsigned int i=0; i<pCount; i++)
        {
            wprintf(L"> session=%d, stationName = %s\n", ppSessionInfo[i].SessionId, ppSessionInfo[i].pWinStationName);
            ExtractFromWTS(WTS_CURRENT_SERVER_HANDLE, ppSessionInfo[i].SessionId);
            LPWSTR sessionstr = new wchar_t[200];
            wsprintf(sessionstr, L"%d", ppSessionInfo[i].SessionId);    
        }
    
        return 0;
    }
    

    输出结果如下:

    C:\Users\Administrator\Desktop>ObtainWTSStartShell.exe empserver1
    4 WTS sessions found on host
    > session=0, stationName = Services
            WTSQuerySessionInformationW - session 0 - WTSInitialProgram failed - error=87 - The paramete
    r is incorrect.
    
            WTSQuerySessionInformationW - session 0 - WTSApplicationName failed - error=87 - The paramet
    er is incorrect.
    
            WTSQuerySessionInformationW - session 0 - WTSWorkingDirectory returned ""
            WTSQuerySessionInformationW - session 0 - WTSOEMId returned ""
            WTSQuerySessionInformationW - session 0 - WTSSessionId returned ""
            WTSQuerySessionInformationW - session 0 - WTSUserName returned ""
            WTSQuerySessionInformationW - session 0 - WTSWinStationName returned "Services"
            WTSQuerySessionInformationW - session 0 - WTSDomainName returned ""
            WTSQuerySessionInformationW - session 0 - WTSConnectState returned "♦"
            WTSQuerySessionInformationW - session 0 - WTSClientBuildNumber returned ""
            WTSQuerySessionInformationW - session 0 - WTSClientName returned ""
            WTSQuerySessionInformationW - session 0 - WTSClientDirectory returned ""
            WTSQuerySessionInformationW - session 0 - WTSClientProductId returned ""
            WTSQuerySessionInformationW - session 0 - WTSClientHardwareId returned ""
            WTSQuerySessionInformationW - session 0 - WTSClientAddress returned ""
            WTSQuerySessionInformationW - session 0 - WTSClientDisplay returned ""
            WTSQuerySessionInformationW - session 0 - WTSClientProtocolType returned ""
            GetShellProcessNameFromUserPolicy - Error: Unable to open policy key - returned [2]
            GetShellProcessName succeseded - explorer.exe
    > session=1, stationName = Console
            WTSQuerySessionInformationW - session 1 - WTSInitialProgram returned ""
            WTSQuerySessionInformationW - session 1 - WTSApplicationName returned ""
            WTSQuerySessionInformationW - session 1 - WTSWorkingDirectory returned ""
            WTSQuerySessionInformationW - session 1 - WTSOEMId returned ""
            WTSQuerySessionInformationW - session 1 - WTSSessionId returned "☺"
            WTSQuerySessionInformationW - session 1 - WTSUserName returned ""
            WTSQuerySessionInformationW - session 1 - WTSWinStationName returned "Console"
            WTSQuerySessionInformationW - session 1 - WTSDomainName returned ""
            WTSQuerySessionInformationW - session 1 - WTSConnectState returned "☺"
            WTSQuerySessionInformationW - session 1 - WTSClientBuildNumber returned ""
            WTSQuerySessionInformationW - session 1 - WTSClientName returned ""
            WTSQuerySessionInformationW - session 1 - WTSClientDirectory returned ""
            WTSQuerySessionInformationW - session 1 - WTSClientProductId returned ""
            WTSQuerySessionInformationW - session 1 - WTSClientHardwareId returned ""
            WTSQuerySessionInformationW - session 1 - WTSClientAddress returned ""
            WTSQuerySessionInformationW - session 1 - WTSClientDisplay returned "?"
            WTSQuerySessionInformationW - session 1 - WTSClientProtocolType returned ""
            GetShellProcessNameFromUserPolicy - Error: Unable to open policy key - returned [2]
            GetShellProcessName succeseded - explorer.exe
    > session=3, stationName = RDP-Tcp#0
            WTSQuerySessionInformationW - session 3 - WTSInitialProgram returned ""
            WTSQuerySessionInformationW - session 3 - WTSApplicationName returned ""
            WTSQuerySessionInformationW - session 3 - WTSWorkingDirectory returned ""
            WTSQuerySessionInformationW - session 3 - WTSOEMId returned ""
            WTSQuerySessionInformationW - session 3 - WTSSessionId returned "♥"
            WTSQuerySessionInformationW - session 3 - WTSUserName returned "Administrator"
            WTSQuerySessionInformationW - session 3 - WTSWinStationName returned "RDP-Tcp#0"
            WTSQuerySessionInformationW - session 3 - WTSDomainName returned "EMPSERVER1"
            WTSQuerySessionInformationW - session 3 - WTSConnectState returned ""
            WTSQuerySessionInformationW - session 3 - WTSClientBuildNumber returned "?"
            WTSQuerySessionInformationW - session 3 - WTSClientName returned "APWADEV03"
            WTSQuerySessionInformationW - session 3 - WTSClientDirectory returned "C:\Windows\System32\m
    stscax.dll"
            WTSQuerySessionInformationW - session 3 - WTSClientProductId returned "☺"
            WTSQuerySessionInformationW - session 3 - WTSClientHardwareId returned ""
            WTSQuerySessionInformationW - session 3 - WTSClientAddress returned "☻"
            WTSQuerySessionInformationW - session 3 - WTSClientDisplay returned "?"
            WTSQuerySessionInformationW - session 3 - WTSClientProtocolType returned "☻"
            GetShellProcessNameFromUserPolicy - Error: Unable to open policy key - returned [2]
            GetShellProcessName succeseded - explorer.exe
    > session=65536, stationName = RDP-Tcp
            WTSQuerySessionInformationW - session 65536 - WTSInitialProgram returned ""
            WTSQuerySessionInformationW - session 65536 - WTSApplicationName returned ""
            WTSQuerySessionInformationW - session 65536 - WTSWorkingDirectory returned ""
            WTSQuerySessionInformationW - session 65536 - WTSOEMId returned ""
            WTSQuerySessionInformationW - session 65536 - WTSSessionId returned ""
            WTSQuerySessionInformationW - session 65536 - WTSUserName returned ""
            WTSQuerySessionInformationW - session 65536 - WTSWinStationName returned "RDP-Tcp"
            WTSQuerySessionInformationW - session 65536 - WTSDomainName returned ""
            WTSQuerySessionInformationW - session 65536 - WTSConnectState returned "♠"
            WTSQuerySessionInformationW - session 65536 - WTSClientBuildNumber returned ""
            WTSQuerySessionInformationW - session 65536 - WTSClientName returned ""
            WTSQuerySessionInformationW - session 65536 - WTSClientDirectory returned ""
            WTSQuerySessionInformationW - session 65536 - WTSClientProductId returned ""
            WTSQuerySessionInformationW - session 65536 - WTSClientHardwareId returned ""
            WTSQuerySessionInformationW - session 65536 - WTSClientAddress returned ""
            WTSQuerySessionInformationW - session 65536 - WTSClientDisplay returned ""
            WTSQuerySessionInformationW - session 65536 - WTSClientProtocolType returned ""
            GetShellProcessNameFromUserPolicy - Error: Unable to open policy key - returned [2]
            GetShellProcessName succeseded - explorer.exe
    

    如你所见,有些数据看起来是有效的,但不是全部。。。。

    5 回复  |  直到 12 年前
        1
  •  3
  •   jon    13 年前

    尽管WTSQuerySessionInformation需要LPTSTR来保存返回的数据,但数据并不总是字符串。尝试打印一些不是字符串的东西在大多数情况下都不会很好地工作。您看到的是空/垃圾字符串,这意味着有时LPTSTR指向的缓冲区以'\0'开头,如果读取为字符串,printf将打印为空字符串。

        2
  •  2
  •   Benj    14 年前

    嗯,答案似乎是,在终端服务/RDP会话中,这些字段为空是很正常的。这个API最初是一个citrixapi,有一个WF等价于大多数WTS函数。在Citrix/IDA服务器上运行时,您似乎从我的程序中获得了更多的数据,而Citrix/IDA服务器似乎更全面地实现了这个会话API。话虽如此,我也看到了更多的领域正在填写时,使用微软远程应用程序。不过,基本上我的程序是工作的。。。

        3
  •  0
  •   Super Dave    10 年前

    我从来没能得到任何东西,除了当前会议的东西。

        int _tmain(int argc, _TCHAR* argv[])
        {
    
            //  if(!WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &ppSessionInfo, &pCount))
            //  {
            ////The stuff coming back from WTSEnumerateSessions in ppSessionInfo doesn't seem to be useful. 
    
            if (GetSystemMetrics(SM_REMOTESESSION) == 0)
            {
                //it ain't remote.  give up.
                return 1;
            }
    
            DWORD bytesReturned = 0;
            LPTSTR pData = NULL;
            WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTSSessionId, &pData, &bytesReturned);
            DWORD sessionId = pData[0]; /*for lookin' at in the debugger*/
            wprintf(L"%d WTS session where you will see stuff.  CURRENT_SESSION\n", pData[0]);
    
            ExtractFromWTS(WTS_CURRENT_SERVER_HANDLE, pData[0]); 
            LPWSTR sessionstr = new wchar_t[200];
            wsprintf(sessionstr, L"%d", pData[0]);    
    
            getchar();
            return 0;
        }
    
        4
  •  0
  •   Sven Sowa    8 年前

    enter image description here

    您可以在HKLM\Software\Citrx\Ica\Session下的远程注册表中查询所有注册表项(即会话id)。然后从每个子键连接读取它们的值PublishedName。之后,将WTSQuerySessionInformation中的会话id与注册表项名称匹配,就完成了。

    某些PowerShell PoC代码如下所示:

    $Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', 'YOURSERVER')
    $RegKey = $Reg.OpenSubKey("SOFTWARE\\Citrix\\ICA\\Session")
    foreach ($sessionId in $RegKey.GetSubKeyNames())
    {
        $sessionKey = $RegKey.OpenSubKey($sessionId + "\\Connection")
        if ($sessionKey -ne $null)
        {
            $sessionKey.GetValue("PublishedName")
            $sessionKey.Close()
        }
    }    
    $RegKey.Close()
    $Reg.Close()