|
Antwort |
Registriert seit: 10. Okt 2006 Ort: 's-Hertogenbosch, Die Niederlande 222 Beiträge RAD-Studio 2010 Arc |
#1
Sorry for writing in English but although I can read German writing in it is more difficult.
I took me quite a while to get code below working (Thanks for the help Olli). So I am posting this some sample code as it might be usefull for others. It's a sample on how to use LsaLogonUser The special thing about LsaLogonUser is the LocalGroups parameter, you can add the user to one or more localgroups for the duration of the session. The sample code adds the logon sid of the user that starts the sample program, therefore we have access to the desktop. This is a lot easier than the sample code from MSDN [msdn]Starting an Interactive Client Process in C++[/msdn] and besides it will also work in Terminal Server sessions and under Windows Vista. The sample also retrieves the Administrator Sid's and adds this, so the process gets Admin access. To use LsaLogonUser you need the SeTcbPrivilege (Act as part of the Operating System).
Delphi-Quellcode:
...
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, JwaWinType, JwaWinBase, JwaWinNT, JwaNtSecApi, JwaNTStatus, JwaNative, JwaUserEnv, JwaWinSta, StdCtrls, ExtCtrls, JwaProfInfo, JwaSDDL; ... var Res: NTSTATUS; hLSA: THandle; LSAString: _LSA_STRING; AuthenticationPackage: ULONG; AuthentificationInfo: TAuthInfo; hToken: THandle; pProfileBuffer: Pointer; LogonID: _LUID; hLsaToken: THandle; QuotaLimits: QUOTA_LIMITS; SubStatus: Integer; wsDomain: WideString; wsUser: WideString; wsPwd: WideString; TokenSource: TOKEN_SOURCE; dwReturnLength: DWORD; Mode: LSA_OPERATIONAL_MODE; pi: PROCESS_INFORMATION; si: STARTUPINFO; // SessionID: Cardinal; // Only needed when starting a process in another terminal session pGroups: PTOKEN_GROUPS; AdminSid: PSid; dwSizeSid: Cardinal; dwSizeDomain: Cardinal; SidType: TSidNameUse; Domain: String; MaxGroups: Integer; bRes: Longbool; begin // Enable Act as part of the Operating System token if not OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES, hToken) then begin raise exception.create(SysErrorMessage(GetLastError)); end; if not EnablePrivilege(hToken, 'SeTcbPrivilege', true) then begin ShowMessageFmt('SeTcbPrivilege: %s', [SysErrorMessage(GetLastError)]); end; if ImpersonateCheckBox.Checked then begin // Enable Impersonation token if not EnablePrivilege(hToken, 'SeImpersonatePrivilege', true) then begin ShowMessageFmt('SeImpersonatePrivilege: %s', [SysErrorMessage(GetLastError)]); end; CloseHandle(hToken); end; (* // Get the SessionID of our session // Only needed if we want to start the process in another session if not ProcessIdToSessionID(GetCurrentProcessId, SessionID) then begin ShowMessageFmt('ProcessIdToSessionID: %s', [SysErrorMessage(GetLastError)]); end; *) RtlInitString(@LsaString, PCSZ(PChar('Winlogon'))); Res := LsaRegisterLogonProcess(LsaString, hLSA, @Mode); if Failed(Res) then begin ShowMessageFmt('LsaRegisterLogonProcess: %s', [SysErrorMessage(LsaNtStatusToWinError(Res))]); end; RtlInitString(@LsaString, PCSZ(PChar(MSV1_0_PACKAGE_NAME))); Res := LsaLookupAuthenticationPackage(hLSA, LSAString, AuthenticationPackage); if Failed(Res) then begin ShowMessageFmt('LookupAuthPackage: %s', [SysErrorMessage(LsaNtStatusToWinError(Res))]); end; TokenSource.SourceName := '**ANON**'; if not AllocateLocallyUniqueId(TokenSource.SourceIdentifier) then begin ShowMessageFmt('AllocLocUniqueId: %s', [SysErrorMessage(GetLastError)]); end; // The number of TOKEN_GROUPS we're going to insert MaxGroups := 2; // Reserve memory for MaxGroups numbur of PTOKEN_GROUPS pGroups := PTOKEN_GROUPS(GlobalAlloc(GPTR, sizeof(_SID_AND_ATTRIBUTES) * MaxGroups)); pGroups^.GroupCount := MaxGroups; // Get and open Token from CurrentProcess if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, hToken)) then begin // Get the Logon Sid and it to the LocalGroups parameter of LsaLogonUser // The Logon Sid has the form S-1-5-5-XXXXXXXX-YYYYYYYY // We need it to obtain access to the user's desktop GetLogonSid(hToken, pGroups^.Groups[0].Sid); pGroups^.Groups[0].Attributes := SE_GROUP_MANDATORY or SE_GROUP_ENABLED or SE_GROUP_ENABLED_BY_DEFAULT or SE_GROUP_LOGON_ID; // Cleanup CloseHandle(hToken); end; // Now get the Administrator's SID dwSizeSid := 0; dwSizeDomain := 0; bRes := LookupAccountName(nil, 'Administrator', nil, dwSizeSid, nil, dwSizeDomain, SidType); if (not bRes) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) then begin // Reserve memory AdminSid := AllocMem(dwSizeSid); SetLength(Domain, dwSizeDomain); // Lookup Sid from Accountname // Assuming that the Admin account has not been renamed! bRes := LookUpAccountName(nil, 'Administrator', AdminSid, dwSizeSid, PChar(Domain), dwSizeDomain, SidType); if not bRes then begin // Cleanup FreeMem(AdminSid); AdminSid := nil; end; end else begin RaiseLastOSError; end; ShowMessageFmt('Administrator Sid: %s, Domain: %s', [SidToStr(AdminSid), Domain]); // Add the Administrator's sid to pGroups pGroups^.Groups[MaxGroups -1].Sid := AdminSid; pGroups^.Groups[MaxGroups -1].Attributes := SE_GROUP_MANDATORY or SE_GROUP_ENABLED or SE_GROUP_ENABLED_BY_DEFAULT; // Fill the AuthentificationInfo structure // First convert the EDITs to WideString wsDomain:= DomainEdit.Text; wsUser:= UserNameEdit.Text; wsPwd:= PasswordEdit.Text; // Fill with zeros RtlZeroMemory(@AuthentificationInfo, sizeof(AuthentificationInfo)); AuthentificationInfo.Header.MessageType := MsV1_0InteractiveLogon; // Copy the strings into a buffer. RtlCopyMemory(@AuthentificationInfo.Domain, @wsDomain[1], sizeof(WideChar) * Length(wsDomain)); RtlCopyMemory(@AuthentificationInfo.User, @wsUser[1], sizeof(WideChar) * Length(wsUser)); RtlCopyMemory(@AuthentificationInfo.Password, @wsPwd[1], sizeof(WideChar) * Length(wsPwd)); // Now set which buffer we want to use (the arrays of WideChar from the struct) RtlInitUnicodeString(@AuthentificationInfo.Header.LogonDomainName, AuthentificationInfo.Domain); RtlInitUnicodeString(@AuthentificationInfo.Header.UserName, AuthentificationInfo.User); RtlInitUnicodeString(@AuthentificationInfo.Header.Password, AuthentificationInfo.Password); Res := LsaLogonUser(hLSA, LsaString, RemoteInteractive, AuthenticationPackage, @AuthentificationInfo, SizeOf(AuthentificationInfo), pGroups, @TokenSource, pProfileBuffer, dwReturnLength, LogonID, hLSAToken, QuotaLimits, SubStatus); if Failed(Res) then begin ShowMessageFmt('LsaLogonUser: %s', [SysErrorMessage(LsaNtStatusToWinError(Res))]); end; (* // Set the token to the user's Terminal Session // Only needed if we want to start the process in another session if not SetTokenInformation(hLsaToken, TokenSessionId, @SessionID, SizeOf(SessionID)) then begin ShowMessageFmt('SetTokenInformation: %s', [SysErrorMessage(GetLastError)]); end; *) if ImpersonateCheckBox.Checked then begin if not ImpersonateLoggedOnUser(hLSAToken) then begin ShowMessageFmt('ImpersonateLoggedOnUser: %s', [SysErrorMessage(GetLastError)]); end; end; ZeroMemory(@si, SizeOf(si)); si.cb := SizeOf(si); si.lpReserved := nil; si.lpDesktop := nil; si.dwFlags := STARTF_USESHOWWINDOW;; si.wShowWindow := SW_SHOWNORMAL; if not CreateProcessAsUser(hLsaToken, nil, PChar(ProcessEdit.Text), nil, nil, False, NORMAL_PRIORITY_CLASS or CREATE_NEW_PROCESS_GROUP, nil, nil, &si, &pi) then begin ShowMessageFmt('CreateProcessAsUser: %s', [SysErrorMessage(GetLastError)]); end else begin end; // Cleanup FreeMem(AdminSid); LsaDeregisterLogonProcess(hLSA); LsaFreeReturnBuffer(pProfileBuffer); RevertToSelf; end;
Delphi-Quellcode:
procedure GetLogonSID(hToken: THandle; var ppsid: PSID);
var dwLength: DWORD; ptg : ^TOKEN_GROUPS; i : integer; begin dwLength := 0; ptg := nil; try // Get required buffer size and allocate the TOKEN_GROUPS buffer. if not GetTokenInformation(hToken, TokenGroups, ptg, 0, dwLength) then begin if GetLastError <> ERROR_INSUFFICIENT_BUFFER then begin ShowMessage('GetTokenInformation failed'); Exit; end; ptg := HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, dwLength); if ptg = nil then begin Exit; end; // Get the token group information from the access token. if not GetTokenInformation(hToken, TokenGroups, ptg, dwLength, dwLength) then begin Exit; end; // Loop through the groups to find the logon SID. for i := 0 to ptg.GroupCount-1 do begin if ptg.Groups[i].Attributes and SE_GROUP_LOGON_ID = SE_GROUP_LOGON_ID then begin // Found the logon SID; make a copy of it. dwLength := GetLengthSid(ptg.Groups[i].Sid); ppsid := HeapAlloc(GetProcessHeap, HEAP_ZERO_MEMORY, dwLength); if ppsid = nil then begin Exit; end; if not CopySid(dwLength, ppsid, ptg.Groups[i].Sid) then begin raise exception.Create(Format('CopySid: %s', [SysErrorMessage(GetLastError)])); HeapFree(GetProcessHeap, 0, ppsid); Exit; end; Break; end; end; end; finally // Free the buffer for the token groups. if ptg <> nil then begin HeapFree(GetProcessHeap, 0, ptg); end; end; end; (* // Alternative way to get the Logon Sid procedure GetLogonSid(var LogonSid: pSid); var hWinstation: HWINSTA; dwSize : Cardinal; begin // Open the WindowStation hWinstation := OpenWindowStation('winsta0', False, READ_CONTROL); if hWinstation = 0 then begin ShowMessageFmt('OpenWindowStation: %s', [SysErrorMessage(GetLastError)]); Exit; end; // GetUserObjectInformation returns required size in dwSizeNeeded if not GetUserObjectInformation(hWinStation, UOI_USER_SID, nil, 0, dwSize) then begin // GetUserObjectInformation returns required size GetMem(LogonSid, dwSize + 1); if not GetUserObjectInformation(hWinStation, UOI_USER_SID, LogonSid, dwSize, dwSize) then begin ShowMessageFmt('GetUserObjectInformation: %s', [SysErrorMessage(GetLastError)]); Exit; end; end; // Cleanup CloseWindowStation(hWinStation); end; *) |
Zitat |
Olli
(Gast)
n/a Beiträge |
#2
The units from JEDI API Lib are required as well, although one could always write own replacements if the license terms of this project are "too strict"
Die Units von JEDI API Lib werden benoetigt, auch wenn man die natuerlich durch eigene Varianten ersetzen kann, falls die Lizenzbedingungen des Projekts "zu streng" sind Wenn gewuenscht, kann ich eine deutsche Uebersetzung von Remkos Text anfertigen. |
Zitat |
Ansicht |
Linear-Darstellung |
Zur Hybrid-Darstellung wechseln |
Zur Baum-Darstellung wechseln |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
LinkBack URL |
About LinkBacks |