Einzelnen Beitrag anzeigen

kopernikus

Registriert seit: 8. Feb 2008
19 Beiträge
 
Delphi 10 Seattle Professional
 
#4

AW: LsaGetLogonSessionData - Zugriffsverletzung

  Alt 7. Nov 2011, 12:30
Der unter bereitgestellte Quellcode ist noch nicht ganz wasserdicht. Außerdem funktioniert er nicht bei Remoote-Sitzungen. Daher habe ich folgende Änderungen eingefügt:
  1. Da die verwendeten API-Funktionen nicht in allen Windows-Versionen verfügbar sind, wurden sie dynamisch eingebunden
  2. Der Aufruf von LsaGetLogonSessionData kann einen Fehler verursachen (z.B. Access denied). Durch eine zusätzliche Abfrage wird das abgefangen.
  3. Der LogonType darf auch RemoteInteractive sein.
  4. Die Abfrage WTSGetActiveConsoleSessionId funktioniert nicht bei Remote-Sitzungen und wird durch ProcessIdToSessionId und GetCurrentProcessId ersetzt.

Delphi-Quellcode:
type
  TSessionData = record
    UserLuid : TLUID;
    UserName,
    Domain : string;
    LogonType : TSecurityLogonType;
    LogonTime : TDateTime;
    end;

function ProcessIdToSessionId (ProcessId : DWORD; var SessionId : DWORD) : BOOL; stdcall; external kernel32 name 'ProcessIdToSessionId'

// Daten des angemeldeten Benutzers ermitteln
function GetUserSessionData (var SessionData : TSessionData) : boolean;
var
  Count: cardinal;
  Luid: PLUID;
  PSesDat: PSecurityLogonSessionData;
  i : integer;
  sid : cardinal;
  SizeNeeded, SizeNeeded2: DWORD;
  OwnerName, DomainName: PChar;
  OwnerType: SID_NAME_USE;
  pBuffer: Pointer;
  pBytesreturned: DWord;
  LocalFileTime: TFileTime;
  Secur32Handle,Wtsapi32Handle : THandle;
  FWTSQuerySessionInformation : TWTSQuerySessionInformation; // ab Win XP
  FWTSGetActiveConsoleSessionId : TWTSGetActiveConsoleSessionId; // ab Win XP
  FLsaEnumerateLogonSessions : TLsaEnumerateLogonSessions; // ab Win XP
  FLsaGetLogonSessionData : TLsaGetLogonSessionData; // ab Win 2000
  FLsaFreeReturnBuffer : TLsaFreeReturnBuffer; // ab Win 2000
begin
  result:=false;
  Secur32Handle:=LoadLibrary(secur32);
  if Secur32Handle=0 then Exit;
  FLsaEnumerateLogonSessions:=GetProcAddress(Secur32Handle,'LsaEnumerateLogonSessions');
  if not assigned(FLsaEnumerateLogonSessions) then Exit;
  FLsaGetLogonSessionData:=GetProcAddress(Secur32Handle,'LsaGetLogonSessionData');
  if not assigned(FLsaGetLogonSessionData) then Exit;
  FLsaFreeReturnBuffer:=GetProcAddress(Secur32Handle,'LsaFreeReturnBuffer');
  if not assigned(FLsaFreeReturnBuffer) then Exit;
  Wtsapi32Handle:=LoadLibrary(wtsapi32);
  if Wtsapi32Handle=0 then Exit;
  FWTSQuerySessionInformation:=GetProcAddress(Wtsapi32Handle,'WTSQuerySessionInformationW');
  if not assigned(FWTSQuerySessionInformation) then Exit;
  DllHandle:=GetModuleHandle(kernel32);
  if DllHandle=0 then Exit;
  FWTSGetActiveConsoleSessionId:=GetProcAddress(DllHandle,'WTSGetActiveConsoleSessionId');
  if not assigned(FWTSGetActiveConsoleSessionId) then Exit;
  //Auflisten der LogOnSessions
  try
    if (LsaNtStatusToWinError(FLsaEnumerateLogonSessions(Count,Luid))=0) then begin
      i:= -1;
      if Count > 0 then repeat
        inc(i);
        // Prüfe auf mögliche Fehler (z.B. Access denied)
        if LsaNtStatusToWinError(FLsaGetLogonSessionData(Luid,PSesDat))=0 then begin
          // Prüfe, ob es sich um eine Konsolen- oder Remote-Anmeldung handelt
          if (PSesDat^.LogonType=Interactive) or (PSesDat^.LogonType=RemoteInteractive) then begin
            SizeNeeded := MAX_PATH;
            SizeNeeded2:= MAX_PATH;
            GetMem(OwnerName, MAX_PATH);
            GetMem(DomainName, MAX_PATH);
            try
              if LookupAccountSID(nil, PSesDat^.SID, OwnerName,SizeNeeded,DomainName,SizeNeeded2,
                              OwnerType) then begin
                // Prüfen ob es sich um einen Benutzer handelt und ob es die
                // SessionId des aufrufenden Prozesses ist
                if (OwnerType=1) and ProcessIdToSessionId(GetCurrentProcessId,sid)
                    and(PSesDat^.Session=sid) then begin
                  if FWTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE,
                      PSesDat^.Session, WTSConnectState,pBuffer,pBytesreturned) then begin
                    if WTS_CONNECTSTATE_CLASS(pBuffer^) = WTSActive then with SessionData do begin
                      UserLuid:=Luid^;
                      UserName:=PSesDat^.UserName.Buffer;
                      DOmain:=PSesDat^.LogonDomain.Buffer;
                      LogonType:=PSesDat^.LogonType;
                      LogonTime:=Now;
                      if FileTimeToLocalFileTime(TFileTime(PSesDat^.LogonTime),LocalFileTime) then
                        LogonTime:=FileTimeToDateTime(LocalFileTime);
                      result:=true;
                      end;
                    end;
                  FLSAFreeReturnBuffer(pBuffer);
                  end;
                end;
            finally
              FreeMem(OwnerName);
              FreeMem(DomainName);
              end;
            end;
          end;
        inc(Luid);
        try
          FLSAFreeReturnBuffer(PSesDat);
        except
          end;
        until (i = Count-1) or result;
      end;
  finally
    FLSAFreeReturnBuffer(Luid);
    FreeLibrary(Wtsapi32Handle); FreeLibrary(Secur32Handle);
    end;
  end;
  Mit Zitat antworten Zitat