How to access the disks mapped through RDP from a service?

rdp, unc, windows

Solution

I think you can achieve this using `CreateProcessAsUser`, but you need to retrieve the token for the user's session, which you do via `WTSQueryUserToken`.

Problem

RDP has this fantastic ability to let export disks from remote user's workstation to the RDP server. As far as I can tell, it is not just a windows explorer trick, but all kinds of programs can use the shortcuts "X:", "Y:", "Z:" etc... This stack overflow entry on RDP disk copying mentions the '\tsclient' alias which points to the machine of the RDP user. Now, it is obvious that if there are 2 or more users, they will each have their own, non-conflicting tsclient destinations. So, my question is this: how do I get a list of and access all remote user shared resources (disks) from a service? Ideally, if, say 2 users have connected and have shared their C: drives, i'd get a list like: - \UserJohnDoe\VolumeXyzC - John's C drive - \UserJaneRoe\VolumeXyzC - Jane's C drive Help appreciated! UPDATE: Here's a working piece of code (gist snippet) ``` // rdpjoker by Konrads #include "stdafx.h" #define SERVER "XXX.compute-1.amazonaws.com" #define CMD "cmd.exe /C dir \\tsclient\\c >output.txt" int main(int argc, char **argv){ HANDLE server; PWTS_SESSION_INFOA ppSessionInfo=NULL; WTS_SESSION_INFOA pSessionInfo; DWORD pCount; DWORD pLevel=1; DWORD i=0; LPSTR ppBuffer; DWORD bytesReturned; HANDLE userToken=NULL; HANDLE pUserToken=NULL; ULONG sessionid; DWORD dwCreationFlags=0; LPVOID environment=NULL; STARTUPINFOA si; PROCESS_INFORMATION pi; char *cmdline; char *username; char *homedir;//[MAX_PATH]; char desktop[8192]; server=WTSOpenServerA(WTS_CURRENT_SERVER_NAME); if(argc>2){ sessionid=atol(argv[1]); printf("[*] Impersonating session: %i\n",sessionid); if(WTSQueryUserToken(sessionid,&userToken)){ //if(DuplicateTokenEx(userToken,MAXIMUM_ALLOWED,NULL,SecurityIdentification,TokenPrimary,&pUserToken)){ if(CreateEnvironmentBlock(&environment,pUserToken,FALSE)){ ZeroMemory( &si, sizeof( STARTUPINFO ) ); //WTSQuerySessionInformationA(server,sessionid,WTSWinStationName,&ppBuffer,&bytesReturned); //sprintf_s(desktop,8192,"%s\\default",ppBuffer); si.lpDesktop = "winsta0\\default";; si.cb=sizeof(STARTUPINFO); //WTSFreeMemory(ppBuffer); ZeroMemory( &pi,sizeof(pi)); cmdline=(char *)malloc(MAX_PATH +1); //GetUserProfileDirectoryA(userToken,homedir,&bytesReturned); //WTSUserConfigTerminalServerProfilePath //WTSQuerySessionInformationA(server,sessionid,WTSUserName,&ppBuffer,&bytesReturned); WTSQuerySessionInformationA(server,sessionid,WTSUserName,&ppBuffer,&bytesReturned); username=_strdup(ppBuffer); WTSFreeMemory(ppBuffer); //WTSQueryUserConfigA(WTS_CURRENT_SERVER_NAME,username,WTSUserConfigTerminalServerProfilePath,&ppBuffer,&bytesReturned); homedir=(char *)malloc(MAX_PATH); sprintf_s(homedir,MAX_PATH,"C:\\Users\\%s\\",username); //homedir=_strdup(ppBuffer); //WTSFreeMemory(ppBuffer); printf("[D] homedir: %s\n",homedir); sprintf_s(cmdline,MAX_PATH,"cmd.exe /C dir %s >output.txt",argv[2]); dwCreationFlags|= CREATE_UNICODE_ENVIRONMENT | NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE; //WTSQuerySessionInformationA(server,sessionid,WTSWinStationName,&ppBuffer,&bytesReturned); //printf("station: %s",ppBuffer); if(CreateProcessAsUserA(userToken, NULL, cmdline, NULL, NULL, FALSE, dwCreationFlags, environment, homedir, &si, &pi)){ printf("[*]CreateProcessAsUserA succeeded! pid:%i, tid:%i\n",pi.dwProcessId,pi.dwProcessId); }else{ printf("[E] CreateProcessAsUserA failed: %i\n", GetLastError()); } //}else{ //printf("[E] CreateEnvironmentBlock failed: %i\n", GetLastError()); // } }else{ printf("[E] DuplicateTokenEx failed: %i\n", GetLastError()); } } else{ printf("[E] WTSQueryUserToken failed: %i\n", GetLastError()); exit(-1); } } else{ // no arguments specified if(WTSEnumerateSessionsA(server,0,1,&ppSessionInfo,&pCount)){ // printf("pCount: %i,",pCount); for (i=0;i<pCount;++i){ // printf("i = %i\n",i); pSessionInfo=ppSessionInfo[i]; printf("Session ID: %i; name: %s, ",pSessionInfo.SessionId,pSessionInfo.pWinStationName); if(WTSQuerySessionInformationA(server,pSessionInfo.SessionId,WTSUserName,&ppBuffer,&bytesReturned)){ printf("user: %s, ",ppBuffer); WTSFreeMemory(ppBuffer); }else{ printf("WTSQuerySessionInformation[WTSUserName] failed: %i\n", GetLastError()); } if(WTSQuerySessionInformationA(server,pSessionInfo.SessionId,WTSWinStationName,&ppBuffer,&bytesReturned)){ printf("station: %s",ppBuffer); WTSFreeMemory(ppBuffer); }else{ printf("WTSQuerySessionInformation[WTSWinStationName] failed: %i\n", GetLastError()); } printf("\n"); } WTSFreeMemory(ppSessionInfo); }else //0014fb3c { printf("EnumerateSessions failed: %i\n", GetLastError()); } } } ```

Original source

Related problems