...
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;