Der Artikel über Prozesssicherheit und Zugriffsrechte des MSDN enthält eine interessante Bemerkung:
... wenn Prozess A ein Handle zum Verarbeiten von B mit PROCESS_DUP_HANDLE- Zugriff hat, kann er das Pseudo-Handle für Prozess B duplizieren. Dadurch wird ein Handle erstellt, das maximalen Zugriff auf Prozess B hat.
Wenn Sie dies frei ins Russische übersetzen, heißt es hier, dass wir mit einem Deskriptor für einen Prozess mit dem Zugriffsrecht PROCESS_DUP_HANDLE mit der Funktion DuplicateHandle (...) einen Deskriptor mit den maximal zulässigen Zugriffsmasken für diesen Prozess erhalten können.

Demonstration
Der Quellcode, der diese Funktion nutzt, ist recht einfach:
#include <Windows.h> int wmain(int argc, PWSTR argv[]) { HANDLE ProcessAllAccessHandle; HANDLE ProcessDuplicateHandle = OpenProcess(PROCESS_DUP_HANDLE, FALSE, _wtoi(argv[1])); if (ProcessDuplicateHandle) { if (DuplicateHandle(ProcessDuplicateHandle, GetCurrentProcess(), GetCurrentProcess(), &ProcessAllAccessHandle, 0, FALSE, DUPLICATE_SAME_ACCESS)) { CloseHandle(ProcessAllAccessHandle); } CloseHandle(ProcessDuplicateHandle); } return 0; }
Als Ergebnis der Kompilierung und Verknüpfung erhalten wir ein Testdienstprogramm, das die Zielprozesskennung (PID) als Argument verwendet. Anschließend öffnet das Dienstprogramm den angegebenen Prozess mit dem Recht PROCESS_DUP_HANDLE . Somit simulieren wir die notwendige Bedingung für die Verfügbarkeit eines Deskriptors für einen Prozess mit dem richtigen PROCESS_DUP_HANDLE (== 0x40).
Als Demonstration werde ich das zusammengestellte Dienstprogramm in WinDbg verfolgen:
0:000> lsa @$ip 0,3 > 13: if (ProcessDuplicateHandle) 14: { 15: if (DuplicateHandle(ProcessDuplicateHandle, 0:000> !handle @@C++(ProcessDuplicateHandle) 3 Handle 80 Type Process Attributes 0 GrantedAccess 0x40: None DupHandle HandleCount 9 PointerCount 260518
Und danach Bewegung des Handgelenks Durch Aufrufen von DuplicateHandle (...) erhalten wir den zweiten Deskriptor für denselben Prozess, jedoch mit den breitesten Berechtigungen:
0:000> lsa @$ip 0,3 > 23: CloseHandle(ProcessAllAccessHandle); 24: } 25: CloseHandle(ProcessDuplicateHandle); 0:000> !handle @@C++(ProcessAllAccessHandle) 3 Handle 84 Type Process Attributes 0 GrantedAccess 0x1fffff: Delete,ReadControl,WriteDac,WriteOwner,Synch Terminate,CreateThread,,VMOp,VMRead,VMWrite,DupHandle,CreateProcess,SetQuota,SetInfo,QueryInfo,SetPort HandleCount 10 PointerCount 292877
Der Schlüsselpunkt ist der GrantedAccess-Wert, der für den neuen Deskriptor 0x1fffff ist und PROCESS_ALL_ACCESS entspricht. Leider zeigt WinDbg die PID des Zielprozesses nicht an. Um sicherzustellen, dass der Deskriptor für den gewünschten Prozess empfangen wird, können Sie die Deskriptoren im Prozess-Explorer anzeigen (nachdem Sie die in den Befehlszeilenargumenten im Debugger angegebene PID angegeben haben):
0:000> dx argv[1] argv[1] : 0x1b7c2e2412c : "21652" [Type: wchar_t *]

Im Screenshot öffnet das Dienstprogramm die Deskriptoren zum Ausführen von notepad.exe.
Warum passiert das?
Erstens, weil beim Duplizieren des Deskriptors, wenn die Zugriffsmaske für das Objekt nicht erweitert wird (und das Operationsflag DUPLICATE_SAME_ACCESS speziell für uns angegeben ist), nicht überprüft wird, ob der Prozess (in dem der duplizierte Deskriptor erstellt wird) Zugriff auf dieses Objekt hat. Es wird nur überprüft, ob die an die Funktion DuplicateHandle (...) übergebenen Prozessdeskriptoren die zulässige Zugriffsmaske PROCESS_DUP_HANDLE haben . Und dann erfolgt das Kopieren des Deskriptors zwischen den Prozessen, ohne die Zugriffsrechte zu überprüfen (ich wiederhole: Wenn der neue Deskriptor die Maske für zulässige Rechte hat, die nicht breiter als der ursprüngliche duplizierte Deskriptor ist).
Und dann sollte beachtet werden, dass der Aufruf von GetCurrentProcess () eine Konstante zurückgibt, denselben Pseudo-Deskriptor (Pseudo-Handle), der ganz am Anfang dieser Veröffentlichung erwähnt wurde. Es gibt zwei dokumentierte Pseudodeskriptoren mit konstanten Werten, die in der Prozessdeskriptortabelle physisch fehlen. Diese Deskriptoren werden jedoch von allen Kernelfunktionen verarbeitet (zusammen mit den üblichen Deskriptoren aus der Prozessdeskriptortabelle):
Es ist der Wert von NtCurrentProcess (== -1), der den Aufruf GetCurrentProcess () zurückgibt .
Dieser Pseudo-Deskriptor im Rahmen eines bestimmten Prozesses bedeutet ein Objekt dieses Prozesses mit den Rechten PROCESS_ALL_ACCESS (tatsächlich gibt es Nuancen, aber der Artikel handelt nicht davon). Es stellt sich heraus, dass eine solche Verbindung zu sich selbst besteht, aber durch den Deskriptor:

Das heißt, unser Aufruf von DuplicateHandle (ProcessDuplicateHandle, GetCurrentProcess (), ...) wird wie folgt interpretiert: Duplizieren Sie im offenen (Ziel-) Prozess das Handle mit dem Wert -1. Und für den Zielprozess (für den der Deskriptor in der Variable ProcessDuplicateHandle gespeichert ist) bezieht sich der Wert -1 auf denselben Zielprozess mit den Rechten PROCESS_ALL_ACCESS . Als Ergebnis erhalten wir einen Deskriptor für den Zielprozess mit maximalen Rechten.
Anstelle eines Nachworts
Ich wiederhole den ganz am Anfang geschriebenen Gedanken: Wenn jemand einen Deskriptor für den Prozess mit dem Recht PROCESS_DUP_HANDLE erhält, kann er unter dem Windows-Sicherheitsmodell einen anderen Deskriptor für denselben Prozess erhalten, jedoch mit den Rechten PROCESS_ALL_ACCESS (und mit dem Prozess tun, was er will) )
Vielen Dank an alle, die die Publikation bis zum Ende gelesen haben. Ich lade alle ein, an der Umfrage teilzunehmen, um herauszufinden, wie solche Veröffentlichungen für das Publikum interessant / nützlich sein können.