Ein Tool für den menschlichen Shadow-Zugriff von Nicht-Administratoren auf RDP-Sitzungen von Benutzern in Windows Server 2012R2

Das Problem während der Quarantänezeit des Unternehmens war folgendes: Es ist wirklich notwendig, die Anzahl der Besuche in den Büros der Fachleute, die Anwendungssoftware unterstützen und beraten, zu minimieren. Um ehrlich zu sein, nutzen die Benutzer oft die Hilfe von Fachleuten, ohne sich mit dem Thema auseinanderzusetzen, und denken sich: „Sie kommen vorbei, helfen mir und erledigen es, während ich eine Zigarette rauche oder einen Kaffee trinke.“ Ein telefonisches Beratungsgespräch ist effektiver, wenn man den Server zusammen betrachtet.

Ein Tool für den menschlichen Shadow-Zugriff von Nicht-Administratoren auf RDP-Sitzungen von Benutzern in Windows Server 2012R2

Bereits nach der 'Erfindung' unseres eigenen Fahrrads erhielten wir brauchbare Informationen zum Thema Artikel: RDS Shadow – Schattenverbindung zu RDP-Sitzungen von Benutzern in Windows Server 2012 R2 oder Der Shadow-Modus für nicht privilegierte Benutzer in Windows Server oder Delegieren Sie die Verwaltung von RDP-Sitzungen. Alle diese Methoden setzen die Verwendung der Konsole voraus, sogar mit einfachen Dialogelementen.

Die nachstehenden Informationen sind für diejenigen gedacht, die normal mit abnormalen Maßnahmen umgehen um das gewünschte Ergebnis zu erzielen, indem man unnötige Verfahren erfindet.
Um 'den Schuh nicht unnötig zu zerdrücken', beginne ich mit dem Letzten: Das Fahrrad funktioniert bei einem normalen Benutzer mit dem Tool AdmiLink, wofür ich dem Autor danke.

I. Konsole und Schatten-RDP.

Da die Verwendung der Konsole Server-Manager mit Administratorrechten -> QuickSessionCollection -> Ein Klick auf die Sitzung des interessierten Benutzers, Auswahl im Kontextmenü Schatten (Shadow Copy) für das Personal, das über die Softwareinstruktionen gibt, – ist keine Option, es wurde eine andere „holzartige“ Methode betrachtet, nämlich:

1. Bestimmen Sie die RDP-Sitzungs-ID:

query user | findstr Administrator

oder:

qwinsta | findstr Administrator 

Dabei war "| findstr Administrator" nur nützlich, wenn man weiß, dass man genau das benötigt, oder man verwendet nur den ersten Teil, um alle auf dem Server angemeldeten Benutzer zu sehen. Administrator 2. Verbinden Sie sich mit dieser Sitzung, vorausgesetzt, in den Domänen-

Ein Tool für den menschlichen Shadow-Zugriff von Nicht-Administratoren auf RDP-Sitzungen von Benutzern in Windows Server 2012R2

Gruppenrichtlinien ist die Option 'Setzt Regeln für die Remoteverwaltung von Benutzersitzungen der Remote-Desktopdienste' mindestens auf 'Überwachung der Sitzung mit Genehmigung des Benutzers' ausgewählt ( mstsc /shadow:127mehr erfahren):

Bitte beachten Sie, dass in der Liste nur die Anmeldungen der Benutzer angezeigt werden.

Ich wiederhole, dass Sie ohne Administratorrechte Folgendes erhalten:

Aber für die vorläufige Fehlersuche des Programms, über das es gehen wird, habe ich ein Konto mit Administratorrechten verwendet.

Ein Tool für den menschlichen Shadow-Zugriff von Nicht-Administratoren auf RDP-Sitzungen von Benutzern in Windows Server 2012R2

II. Programm

Also, die Aufgabenstellung: Erstellung einer einfachen grafischen Benutzeroberfläche zur Verbindung mit dem Schatten von Benutzersitzungen mit dessen Genehmigung, um dem Benutzer eine Nachricht zu senden. Die Programmierumgebung wurde auf Lazarus festgelegt.

1. Wir erhalten die vollständige Domänenliste der Benutzer 'Anmeldename' – 'vollständiger Name' vom Administrator, oder wieder über die Konsole:

wmic useraccount get Name,FullName

niemand hindert dabei auch, dies so zu tun: 

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

Ich sage gleich, dass es bei Lazarus ein Problem mit der Verarbeitung dieser Datei gab, da ihre Standardkodierung UCS-2 ist, daher musste ich sie manuell in UTF-8 umwandeln. Die Struktur der Datei enthält viele Tabulatoren, besser gesagt zahlreiche Leerzeichen, die ich programmiert bearbeiten wollte; früher oder später wird das Kodierungsproblem gelöst sein und die Datei wird programmgesteuert aktualisiert.

Das Konzept ist, einen für die Benutzer des Programms zugänglichen Ordner, z.B. c:test, zu haben, in dem es zwei Dateien gibt: die erste mit Login und vollständigem Namen, die zweite mit id_rdp und Benutzernamen. Weiter verarbeiten wir diese Daten, wie wir können:).

Und bisher, um es mit der Liste der Sitzungen zu verknüpfen, übertragen wir den Inhalt (Login und vollständiger Name) in ein Array:

procedure Tf_rdp.UserF2Array; var F:TextFile; i:integer; f1, line1:String; fL: TStringList; begin //f_d globaler Pfad zu den Dateien f1:=f_d+'user_name.txt'; // Aufgabe, den Inhalt der Datei in ein Array zu lesen fL := TStringList.Create; // die Zeile wird Metamorphosen mit Trennzeichen unterzogen fL.Delimiter := '|'; fL.StrictDelimiter := True; AssignFile(F,f1); try // Datei zum Lesen öffnen reset(F); ReadLn(F,line1); i:=0; while not eof(F) do // Zeilen lesen, bis die Datei zu Ende ist begin ReadLn(F,line1); line1:= StringReplace(line1, ' ', '|',[]); // ersetze das erste Auftreten von 2 Leerzeichen durch den Trennzeichen | // entferne alle doppelten Leerzeichen while pos(' ',line1)>0 do line1:= StringReplace(line1, ' ', ' ', [rfReplaceAll]); begin if (pos('|',line1)>0) then begin // wenn der Trennzeichen existiert, speichere ihn im Array fL.DelimitedText :=line1; // teile in Spalten if (fL[0]'') then // wenn das Konto einen Namen hat begin // füge ihn dem Array hinzu inc(i); // beseitige mögliche einzelne Leerzeichen im Login fam[0,i]:=StringReplace(fL[1],' ','',[rfReplaceall, rfIgnoreCase]); fam[1,i]:=fL[0]; end;end;end;end; // Fertig. Datei schließen. CloseFile(F); Fl.Free; except on E: EInOutError do ShowMessage('Fehler bei der Datei Verarbeitung. Details: '+E.Message); end;end;

procedure Tf_rdp.UserF2Array;
var 
  F:TextFile;   i:integer;   f1, line1:String;   fL: TStringList;
begin //f_d globaler Dateipfad für die Ablage der Dateien 
f1:=f_d+'user_name.txt';     //Aufgabe: Inhalt der Datei in ein Array lesen
fL := TStringList.Create; // Wir unterziehen die Zeile Metamorphosen mit Trennzeichen
fL.Delimiter := '|'; fL.StrictDelimiter := True;
AssignFile(F,f1); 
try // Datei für das Lesen öffnen
  reset(F); ReadLn(F,line1);
  i:=0;
while not eof(F) do // Zeilen lesen, bis die Datei endet
begin
ReadLn(F,line1);
line1:= StringReplace(line1, '  ', '|',[]); //ersetze erstes gefundenes doppeltes Leerzeichen mit dem Trennzeichen |
// entferne alle doppelten Leerzeichen
while pos('  ',line1)>0 do line1:= StringReplace(line1, '  ', ' ', [rfReplaceAll]);
begin
if (pos('|',line1)>0) then
begin // wenn Trennzeichen vorhanden, ins Array übernehmen
fL.DelimitedText :=line1; // in Spalten aufteilen
if (fL[0] '') then // wenn der Account einen Namen hat
begin // dann diesen ins Array einfügen
 inc(i); // entferne mögliche einzelne Leerzeichen im Login
 fam[0,i]:=StringReplace(fL[1],' ','',[rfReplaceall, rfIgnoreCase]);
 fam[1,i]:=fL[0];
 end;end;end;end; // Fertig. Datei schließen.
 CloseFile(F);
 Fl.Free;
 except
 on E: EInOutError do  ShowMessage('Fehler bei der Verarbeitung der Datei. Details: '+E.Message);
 end;end;

Ich entschuldige mich für den 'vielen Code'; die nächsten Punkte werden kürzer sein.

2. Ähnlich wie im vorherigen Punkt wird das Ergebnis der Verarbeitung der Liste in das Element StringGrid eingelesen, dabei zeige ich einen "bedeutenden" Codeabschnitt:

2.1 Aktuelle Liste der RDP-Sitzungen in eine Datei erhalten:

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 kann auch länger warten, bis die Datei zum Lesen erstellt wird

2.2 Datei bearbeiten (hier nur bedeutende Zeilen des Codes angegeben):

StringGrid1.Cells[0,i]:=fL[1]; StringGrid1.Cells[2,i]:=fL[3]; // im Zyklus in StringGrid1 speichern
login1:=StringReplace(fL[1],' ','',[rfReplaceall, rfIgnoreCase]); // Leerzeichen aus dem Login entfernen
if (SearchArr(login1)>=0) then // im Array nach p1. Login suchen und in die Tabelle FIO speichern
StringGrid1.Cells[1,i]:=fam[1,SearchArr(login1)]
else StringGrid1.Cells[1,i]:='+'; // oder ein Pluszeichen speichern:)
.... // je nach Wahl des Benutzers sortieren und formatieren  

3. Direkt die Verbindung beim Klicken auf die Zeile mit dem Benutzer und der Nummer seiner Sitzung:

  id:=(StringGrid1.Row);// Zeilennummer erfahren  IntToStr(StringGrid1.Row)
  ids:=StringGrid1.Cells[2,id]; // RDP-Identifikator erhalten
  cmdline:='/c mstsc /shadow:'+ ids; // und verbinden....
 if (b_rdp.Checked=True) then  if ShellExecute(0,nil, PChar('cmd'),PChar(cmdline),nil,1) =0 then;       

4. Es wurden noch einige zusätzliche Funktionen wie Sortierung beim Klicken auf die Radiobuttons und Benutzerbenachrichtigungen hinzugefügt.

Ein Tool für den menschlichen Shadow-Zugriff von Nicht-Administratoren auf RDP-Sitzungen von Benutzern in Windows Server 2012R2

→ Den vollständigen Quellcode kann man einsehen hier

III. Anwendung von AdminLink – was ich gesehen habe:

AdminLink generiert tatsächlich eine Verknüpfung, die auf den Speicherort des Tools verweist admilaunch.exe, und einer persönlichen Kopie des Startwerkzeugs AdmiRun.Exe , welche sich im Benutzerordner befindet, beispielsweise vasya, im Stil von C:UsersvasyaWINDOWS. Insgesamt ist nicht alles so schlecht: Mit den Berechtigungen für die Verknüpfungsdatei und anderen Aspekten kann man zum eigenen administrativen Gewissen spielen.

Quelle: habr.com

Erwerben Sie zuverlässiges Hosting für Websites mit DDoS-Schutz, VPS VDS-Server 🔥 Kaufen Sie zuverlässiges Hosting für Websites mit DDoS-Schutz, VPS VDS-Server | ProHoster