Ett verktyg för mänsklig icke-administratör att ansluta till RDP-sessioner för användare i WinServer 2012R2

Under the quarantine working period, the problem became as follows: it is indeed necessary to minimize the number of visits to specialists' offices who provide support and consulting on application software. Frankly, users often abuse the help of specialists, not wanting to delve into the issue themselves, saying, 'they will come — help — fix it, and I will just have a smoke or drink coffee, etc.' Phone consultation while sharing access to the server is more effective if the remote screen is viewed.

Ett verktyg för mänsklig icke-administratör att ansluta till RDP-sessioner för användare i WinServer 2012R2

Already after the 'invention' of our bicycle, reasonable information on the topic of the article emerged: RDS Shadow – shadow connection to RDP sessions of users in Windows Server 2012 R2 eller The shadow mode of a non-privileged user in Windows Server eller Delegerar hanteringen av RDP-sessioner. All of them imply the use of the console, even with elements of simple dialogue.

All the information presented below is intended for those who can normally endure abnormal deviations to achieve the desired result by inventing unnecessary methods.
To 'not drag the cat by the tail', I will start with the last: the bicycle works for the ordinary user using the utility AdmiLink, for which the author deserves thanks.

I. Console and shadow RDP.

Since using the Server Manager console with admin rights -> QuickSessionCollection -> by clicking on the session of the interested user, selecting Shadow (Shadow Copy) in the context menu for the staff instructing on the use of software, — is not an option, another 'wooden' method was considered, namely:

1. Find out the RDP session id:

query user | findstr Administrator

or:

qwinsta | findstr Administrator 

Moreover, "| findstr Administrator" was only convenient when you know exactly what you need, or to use only the first part to see all users logged onto the server. Administrator 2. Connect to this session, provided that in the domain

Ett verktyg för mänsklig icke-administratör att ansluta till RDP-sessioner för användare i WinServer 2012R2

Group Policies the parameter 'Establishes rules for remote control of user sessions for Remote Desktop Services' has at least the option 'Observe session with user's permission' selected ( mstsc /shadow:127mer information):

Please note that only user logins will be in the list.

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

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

Ett verktyg för mänsklig icke-administratör att ansluta till RDP-sessioner för användare i WinServer 2012R2

Но для предварительной отладки программы, о которой пойдет речь, я использовал учетку с правами администратора.

II. Programmet

Så här ser uppgiften ut: att skapa ett enkelt grafiskt gränssnitt för att ansluta till användarens skuggsensor med hans tillstånd, och skicka ett meddelande till användaren. Programmeringsmiljön som valdes är Lazarus.

1. Vi får en fullständig domänlista över användare "inloggning" — "fullständigt namn" från administratören, eller återigen via konsolen:

wmic useraccount get Name,FullName 

ingen hindrar oss från att göra det så här:

wmic useraccount get Name,FullName > c:testusername.txt

Jag säger genast att det var i Lazarus som det fanns ett problem med att bearbeta den här filen, eftersom dess standardkodning är UCS-2, så jag var tvungen att konvertera den manuellt till vanlig UTF-8. Strukturen i filen har många tabbar, eller snarare många mellanslag, som vi beslutade att ändå bearbeta programmässigt; förr eller senare kommer problemlösningen med kodningen att komma, och filen kommer att uppdateras programmässigt.

Så, planen är att ha en mapp som är tillgänglig för programmets användare, till exempel c:test, där det kommer att finnas 2 filer: den första med inloggning och fullständigt namn, den andra med id_rdp och inloggning för användarna. Vi bearbetar sedan dessa data som vi kan :)

Och för att koppla det till sessionslistan flyttar vi detta (inloggning och fullständigt namn) innehåll till en array:

procedure Tf_rdp.UserF2Array;
var 
  F:TextFile;   i:integer;   f1, line1:String;   fL: TStringList;
begin // f_d global sökväg till filerna 
f1:=f_d+'user_name.txt';     // uppgiften är att läsa filens innehåll till arrayen
fL := TStringList.Create; // vi kommer att utsätta strängen för metamorfoser med avgränsare
fL.Delimiter := '|'; fL.StrictDelimiter := True;
AssignFile(F,f1); 
try // Öppna filen för läsning
  reset(F); ReadLn(F,line1);
  i:=0;
while not eof(F) do // Läser rader tills filen tar slut
begin
ReadLn(F,line1);
line1:= StringReplace(line1, '  ', '|',[]); // ersätter första två mellanrum med avgränsaren |
// tar bort alla dubbla mellanrum
while pos('  ',line1)>0 do line1:= StringReplace(line1, '  ', ' ', [rfReplaceAll]);
begin
if (pos('|',line1)>0) then
begin // om avgränsaren existerar lägger vi till den i arrayen
fL.DelimitedText :=line1; // delar upp i kolumner
if (fL[0]'') then // om kontot har ett namn
begin // lägger till det i arrayen
 inc(i); // tar bort eventuella ensamma mellanslag i inloggningen
 fam[0,i]:=StringReplace(fL[1],' ','',[rfReplaceall, rfIgnoreCase]);
 fam[1,i]:=fL[0];
 end;end;end;end; // Klart. Stänger filen.
 CloseFile(F);
 Fl.Free;
 except
 on E: EInOutError do  ShowMessage('Fel vid bearbetning av filen. Detaljer: '+E.Message);
 end;end;

Jag ber om ursäkt för "mycket kod", de följande punkterna kommer att vara mer koncisa.

2. På samma sätt som i föregående punkt läser vi av resultatet av bearbetningen av listan i elementet StringGrid, här är ett 'betydelsefullt' kodstycke:

2.1 Vi får den aktuella listan över RDP-sessioner i en fil:

f1:=f_d+'user.txt';
cmdline:='\/c query user >'+ f1;
if ShellExecute(0,nil, PChar('cmd'),PChar(cmdline),nil,1)=0 then;
Sleep(500); \/\/ man kan vänta lite längre medan filen skapas för läsning

2.2 Bearbeta filen (endast betydelsefulla kodrader anges):

StringGrid1.Cells[0,i]:=fL[1]; StringGrid1.Cells[2,i]:=fL[3]; \/\/lägger i en loop i StringGrid1
login1:=StringReplace(fL[1],' ','',[rfReplaceall, rfIgnoreCase]); \/\/tar bort mellanslag från inloggningen
if (SearchArr(login1)>=0) then \/\/söker i arrayen från p1. loggningen och skriver in i tabellen Namn
StringGrid1.Cells[1,i]:=fam[1,SearchArr(login1)]
else StringGrid1.Cells[1,i]:='+'; \/\/ annars skriver vi plusset:)
.... \/\/beroende på användarens val sorterar och formaterar vi efter data
if (b_id.Checked=true) then SortGrid(0) else SortGrid(1);
StringGrid1.AutoSizeColumn(0);StringGrid1.AutoSizeColumn(1); StringGrid1.AutoSizeColumn(2);  

3. Själva anslutningen vid klick på raden med användaren och numret på hans session:

  id:=(StringGrid1.Row);\/\/ får radnumret IntToStr(StringGrid1.Row)
  ids:=StringGrid1.Cells[2,id]; \/\/hämtar rdp-identifieraren
  cmdline:='\/c mstsc \/shadow:'+ ids; \/\/och vi ansluter....
 if (b_rdp.Checked=True) then  if ShellExecute(0,nil, PChar('cmd'),PChar(cmdline),nil,1) =0 then;       

4. Flera dekoreringar är gjorda, såsom sortering vid klick på radioknappen och meddelanden till användaren, eller till alla användare.

Ett verktyg för mänsklig icke-administratör att ansluta till RDP-sessioner för användare i WinServer 2012R2

→ Den fullständiga källkoden kan ses här

III. Användning av AdminLink — vad jag såg:

AdminLink genererar verkligen en genväg som refererar till platsen för verktyget admilaunch.exe, och en personlig kopia av körverktyget AdmiRun.Exe som finns i användarens mapp, till exempel vasya, typ C:UsersvasyaWINDOWS. Allt som allt är det inte så illa: med rättigheterna till genvägsfilen och annat, kan man leka lite för att stilla sin administrativa samvete.

Källa: habr.com

Köp pålitlig webbhotell med DDoS-skydd, VPS VDS-servrar 🔥 Köp pålitlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster