我编写了一个程序,该程序应查询终端服务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
如您所见,某些数据看起来有效,但不是全部....
答案 0 :(得分:3)
即使WTSQuerySessionInformation采用LPTSTR来保存返回的数据,但数据并不总是字符串。在大多数情况下,尝试printf不是字符串的东西不会很好。您看到空/垃圾字符串这一事实意味着有时LPTSTR指向的缓冲区以'\ 0'开头(如果作为字符串读取),printf将作为空字符串打印。
而是尝试在HEX表示中打印出字符串的每个字符。遍历字符串中的每个字符(0到bytesReturned-1)并将其打印为十六进制。这将使您更好地了解LPTSTR缓冲区中的内容。
答案 1 :(得分:2)
嗯,答案似乎是这些字段在终端服务/ RDP会话上为空是相当正常的。此API最初是Citrix API,并且有一个WF等效于大多数这些WTS功能。在Citrix / IDA服务器上运行时,您似乎从我的程序中获得了更多的数据,这似乎可以更充分地实现此会话API。话虽如此,我还看到了使用MS Remote App时填写的更多字段。但是,基本上我的计划正在运作......
答案 2 :(得分:0)
我认为WTSQuerySessionInformation需要您首先获取权限才能正确返回所有数据?
答案 3 :(得分:0)
我从来没有得过任何东西,除了当前的会话内容。
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)
我们发现的一个解决方案就是这样。根据注册信息:
您在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()