Utility for human shadow connecting non-admin to RDP user sessions in WinServer 2012R2

The problem during the quarantine period of the enterprise was as follows: it is really necessary to minimize the number of visits to cabinets by specialists who service and advise on application software, and frankly, users often abuse the help of specialists not wanting to delve into the question itself, saying "they will come - they will help, they will do it, and while I smoke / drink coffee, etc. " Consulting by phone when sharing a server is more effective when viewing a remote screen.



Already after the ā€œinventionā€ of our bike, sane information turned up on the topic of the article: RDS Shadow - shadow connection to RDP user sessions in Windows Server 2012 R2 or Shadow mode of an unprivileged user in windows server or We delegate the management of RDP sessions . All of them imply the use of a console, even with elements of a simple dialogue.

All of the information below is intended for those who normally tolerate abnormal perversions to obtain the desired result, inventing unnecessary methods.
In order not to ā€œpull the cat by the tailā€, Iā€™ll start with the last one: the bike works for the average user using the AdmiLink utility , for which its author and thank you.

I. Console and shadow RDP.

Since the use of the Server Manager console with administrator rights -> QuickSessionCollection -> by clicking on the session of the user of interest, selecting Shadow from the context menu for staff instructing in working with the software is not an option, another ā€œwoodenā€ method was considered, namely:

1. We learn the RDP session id:

query user | findstr Administrator

or:

qwinsta | findstr Administrator 

Moreover, " | findstr Administrator " was convenient only when you know what exactly you need Administrator , or use only the first part to see all logged in to the server.



2. We are connected to this session, provided that in the domain group policies the parameter ā€œSets the remote control rules for user sessions of Remote Desktop Servicesā€ is selected at least ā€œMonitoring the session with user permissionā€ ( more ):

mstsc /shadow:127

Please note that the list will only contain user logins.

I repeat that without admin rights you will receive the following:



But for preliminary debugging of the program that will be discussed, I used an account with administrator rights.

II. Program

So the statement of the problem: the creation of a simple GUI to connect to the user's shadow sense with his permission, sending a message to the user. The programming environment is selected by Lazarus.

1. We get the full domain list of users ā€œloginā€ - ā€œfull nameā€ from the administrator, or again through the console:

wmic useraccount get Name,FullName 

no one forbids even this:

wmic useraccount get Name,FullName > c:\test\username.txt

I must say right away that it was Lazarus who had the problem with processing this file, since its default encoding is UCS-2, so I just had to manually convert it to regular UTF-8. There are a lot of tabs in the file structure, or rather, a lot of spaces that were decided to be programmed after all, sooner or later the encoding problem will be solved, and the file will be updated programmatically.

So, in the idea of ā€‹ā€‹the folder, accessible to users of the program, for example c: \ test, in which there will be 2 files: the first with login and fullname, the second with id_rdp and login users. Further we process this data as we can :).

In the meantime, to associate with the list of sessions, we transfer this (login and fullname) contents to an array:

procedure Tf_rdp.UserF2Array;
var 
  F:TextFile;   i:integer;   f1, line1:String;   fL: TStringList;
begin //f_d      
f1:=f_d+'user_name.txt';     //     
fL := TStringList.Create; //     
fL.Delimiter := '|'; fL.StrictDelimiter := True;
AssignFile(F,f1); 
try //    
  reset(F); ReadLn(F,line1);
  i:=0;
while not eof(F) do //  ,    
begin
ReadLn(F,line1);
line1:= StringReplace(line1, '  ', '|',[]); //  .2  |
//    
while pos('  ',line1)>0 do line1:= StringReplace(line1, '  ', ' ', [rfReplaceAll]);
begin
if (pos('|',line1)>0) then
begin //      
fL.DelimitedText :=line1; //   
if (fL[0]<>'') then //   
begin //   
 inc(i); //       
 fam[0,i]:=StringReplace(fL[1],' ','',[rfReplaceall, rfIgnoreCase]);
 fam[1,i]:=fL[0];
 end;end;end;end; // .  .
 CloseFile(F);
 Fl.Free;
 except
 on E: EInOutError do  ShowMessage('  . : '+E.Message);
 end;end;

I apologize for the "lot of code", the following points will be more concise.

2. Similarly, using the method from the previous paragraph, we read the result of processing the list into a StringGrid element, while I will give a ā€œsignificantā€ piece of code:

2.1 We get the actual list of RDP sessions in a file:

f1:=f_d+'user.txt';
cmdline:='/c query user >'+ f1;
if ShellExecute(0,nil, PChar('cmd'),PChar(cmdline),nil,1)=0 then;
Sleep(500); //         

2.2 We process the file (only significant lines of code are indicated):

StringGrid1.Cells[0,i]:=fL[1]; StringGrid1.Cells[2,i]:=fL[3]; //    StringGrid1
login1:=StringReplace(fL[1],' ','',[rfReplaceall, rfIgnoreCase]); //   
if (SearchArr(login1)>=0) then //    1.      
StringGrid1.Cells[1,i]:=fam[1,SearchArr(login1)]
else StringGrid1.Cells[1,i]:='+'; //   :)
.... //         
if (b_id.Checked=true) then SortGrid(0) else SortGrid(1);
StringGrid1.AutoSizeColumn(0);StringGrid1.AutoSizeColumn(1); StringGrid1.AutoSizeColumn(2);  

3. The connection itself when you click on the line with the user and his session number:

  id:=(StringGrid1.Row);//     IntToStr(StringGrid1.Row)
  ids:=StringGrid1.Cells[2,id]; //  rdp
  cmdline:='/c mstsc /shadow:'+ ids; // ....
 if (b_rdp.Checked=True) then  if ShellExecute(0,nil, PChar('cmd'),PChar(cmdline),nil,1) =0 then;       

4. A couple more decorations were made, such as sorting by clicking on the radiobutton, and messages to the user or all users.



ā†’ The full source code can be seen here

III. AdminLink application - what I saw:

AdminLink really generates a shortcut that refers to the location of the admilaunch.exe utility and a personal copy of the AdmiRun.Exe launcher that is located in the userā€™s folder, for example, vasya , like C: \ Users \ vasya \ WINDOWS \ . In general, not everything is so bad: you can play with the access rights to the shortcut file and others, to clear your own admin conscience.

All Articles