Skip to content

Instantly share code, notes, and snippets.

@ThunderGunExpress
Created November 7, 2019 03:51
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ThunderGunExpress/e25809745d71b647aee3a3f301c354b2 to your computer and use it in GitHub Desktop.
Save ThunderGunExpress/e25809745d71b647aee3a3f301c354b2 to your computer and use it in GitHub Desktop.
//Reference
//https://gist.github.com/truekonrads/3173572
//https://docs.microsoft.com/en-us/windows/win32/api/wtsapi32/nf-wtsapi32-wtsvirtualchannelquery
//https://github.com/FreeRDP/FreeRDP/blob/master/winpr/libwinpr/wtsapi/test/TestWtsApiQuerySessionInformation.c
#include <Windows.h>
#include <stdio.h>
#include <wtsapi32.h>
#include <tsvirtualchannels.h>
#pragma comment(lib, "wtsapi32.lib")
int main()
{
HANDLE hRdpServer = NULL;
HANDLE hVirtualChannelStatic, hVirtualChannelDynamic = NULL;
PWTS_SESSION_INFOA pSessionInfo = NULL;
WTS_SESSION_INFOA wSessionInfo;
DWORD dSessionCount, dwLen;
PVOID pvFileHandlePtr = NULL;
const char *dvc[] =
{
"UniversalDVC",
"rdp2tcp",
NULL
};
printf("[*] RDP Dynamic Channel Hunter [*]\r\nWill look for the following dynamic virtual channels:");
for (int i = 0; dvc[i] != NULL; i++)
{
printf("\r\n\t- %s", dvc[i]);
}
hRdpServer = WTSOpenServerA(WTS_CURRENT_SERVER_NAME);
if (hRdpServer == NULL)
{
printf("\r\nWTSOpenServerA() Error");
}
if (!WTSEnumerateSessionsA(hRdpServer, 0, 1, &pSessionInfo, &dSessionCount))
{
printf("\r\nWTSEnumerateSessionsA() Error");
}
printf("\r\n\r\n[*] RDP Session Enumeration [*]");
for (int iSess = 0; iSess < dSessionCount; iSess++)
{
wSessionInfo = pSessionInfo[iSess];
LPSTR pBuffer;
DWORD dwReturn;
char* Username;
char* Domain;
char* ClientName;
USHORT ClientProtocol;
if (!WTSQuerySessionInformationA(hRdpServer, wSessionInfo.SessionId, WTSUserName, &pBuffer, &dwReturn))
{
printf("\r\nWTSQuerySessionInformationA() Error - Username");
return 0;
}
Username = (char*)pBuffer;
if (!WTSQuerySessionInformationA(hRdpServer, wSessionInfo.SessionId, WTSDomainName, &pBuffer, &dwReturn))
{
printf("\r\nWTSQuerySessionInformationA() Error - DomainName");
return 0;
}
Domain = (char*)pBuffer;
if (!WTSQuerySessionInformationA(hRdpServer, wSessionInfo.SessionId, WTSClientProtocolType, &pBuffer, &dwReturn))
{
printf("\r\nWTSQuerySessionInformationA() Error - ClientProtocolType");
return 0;
}
ClientProtocol = *((USHORT*)pBuffer);
if (!WTSQuerySessionInformationA(hRdpServer, wSessionInfo.SessionId, WTSClientName, &pBuffer, &dwReturn))
{
printf("\r\nWTSQuerySessionInformationA() Error - ClientAddress");
return 0;
}
ClientName = (char*)pBuffer;
if (ClientProtocol == 2)
{
hVirtualChannelStatic = NULL;
hVirtualChannelDynamic = NULL;
printf("\r\n\r\nSession Name: %s", wSessionInfo.pWinStationName);
printf("\r\nUsername: %s", Username);
printf("\r\nDomain Name: %s", Domain);
printf("\r\nRDP Client Name: %s", ClientName);
printf("\r\nProtocol Type: %d", ClientProtocol);
printf("\r\nSession ID: %d", wSessionInfo.SessionId);
for (int iVirt = 0; dvc[iVirt] != NULL; iVirt++)
{
hVirtualChannelStatic = WTSVirtualChannelOpenEx(wSessionInfo.SessionId, (LPSTR)dvc[iVirt], 0);
if (hVirtualChannelStatic != NULL)
{
if (!WTSVirtualChannelQuery(hVirtualChannelStatic, WTSVirtualFileHandle, &pvFileHandlePtr, &dwLen))
{
printf("\r\nWTSVirtualChannelQuery() Error");
return 0;
}
if (pvFileHandlePtr != NULL)
{
printf("\r\n[*] Remote desktop virtual channel found: %s [*]", dvc[iVirt]);
}
WTSFreeMemory(pvFileHandlePtr);
WTSVirtualChannelClose(hVirtualChannelStatic);
}
hVirtualChannelDynamic = WTSVirtualChannelOpenEx(wSessionInfo.SessionId, (LPSTR)dvc[iVirt], WTS_CHANNEL_OPTION_DYNAMIC);
if (hVirtualChannelDynamic != NULL)
{
printf("\r\n[*] Remote desktop virtual channel found: %s [*]", dvc[iVirt]);
WTSVirtualChannelClose(hVirtualChannelDynamic);
}
}
}
}
WTSFreeMemory(pSessionInfo);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment