//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