; If you using external UiAccess class pass it instanse to UIA argument ; Current session is default SendSasEx(sessionId := -1, _UIA := 0) { if (sessionId = -1) DllCall("ProcessIdToSessionId", "UInt",DllCall("GetCurrentProcessId", "UInt"), "UIntP",&sessionId:=0) isUiAccess := IsSystem := false if (DllCall("Advapi32\OpenThreadToken", "Ptr", DllCall("GetCurrentThread", "Ptr"), "UInt",0x0008, "Int",false, "Ptr*", &hToken:=0) ; TOKEN_QUERY || DllCall("Advapi32\OpenProcessToken", "Ptr", DllCall("GetCurrentProcess", "Ptr"), "UInt",0x0008, "Ptr*", &hToken:=0)) { DllCall("Advapi32\GetTokenInformation", "Ptr", hToken, "UInt", TokenUIAccess := 26, "UInt*",&isUiAccess, "UInt", 4, "UInt*", &dwLengthNeeded:=0) TokenUser := Buffer(0), TokenInformationLength := 0 while !DllCall("Advapi32.dll\GetTokenInformation", "ptr",hToken, "uint",1, "ptr",TokenUser, "uint",TokenUser.Size, "uint*",&ReturnLength:=0) ; TokenUser TokenUser.Size := ReturnLength DllCall("Advapi32.dll\ConvertSidToStringSid", "Ptr",NumGet(TokenUser, "Ptr"), "PtrP",&pSid:=0) IsSystem := StrGet(pSid+0) = "S-1-5-18" DllCall("LocalFree", "Ptr",pSid) DllCall("CloseHandle", "Ptr", hToken) } if (!isUiAccess || !IsSystem) { if (_UIA) _UIA.ImpersonateSYSTEM() else _UIA := UiAccess(false, true), _UIA.ImpersonateSYSTEM() } SoftwareSASGeneration := RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System", "SoftwareSASGeneration", -1) if (SoftwareSASGeneration != -1) try RegDelete "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System", "SoftwareSASGeneration" ; http://www.atelierweb.com/index.php/ctrlaltdel/ retval := DllCall("WMsgAPI.dll\WmsgSendMessage", "UInt",sessionId, "UInt",magicNumber:=0x208, "Ptr",pid:=0, "PtrP",&lParam:=0, "UInt") if (isUiAccess && !IsSystem) _UIA.On() else if (!isUiAccess && IsSystem) _UIA.ImpersonateSYSTEM(false) else if (!isUiAccess && !IsSystem) _UIA.Off() if (SoftwareSASGeneration = -1) try RegWrite "REG_DWORD", "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System", "SoftwareSASGeneration", SoftwareSASGeneration return retval } ; Pass VarRef to isUiAccess and AsUser to get SendSAS result. ; If you using external UiAccess class pass it instanse to UIA argument. In this case it doesn't break it functionality. SendSAS(isUiAccess?, AsUser?, _UIA := 0) { if SysGet(4096) { ; SM_REMOTESESSION ; try ShellDispatch4 := ComObject("{13709620-C279-11CE-A49E-444553540000}", "{efd84b2d-4bcf-4298-be25-eb542a59fbda}") ; if (ShellDispatch4) ; ComCall(40, ShellDispatch4) ComObject("Shell.Application").WindowsSecurity return } _isUiAccess := writtenSsasg := uia_wasoff := false _AsUser := -1 if ((bThreadHasToken := DllCall("Advapi32\OpenThreadToken", "Ptr", DllCall("GetCurrentThread", "Ptr"), "UInt",0x0008, "Int",false, "Ptr*", &hToken:=0)) ; TOKEN_QUERY || DllCall("Advapi32\OpenProcessToken", "Ptr", DllCall("GetCurrentProcess", "Ptr"), "UInt",0x0008, "Ptr*", &hToken:=0)) { DllCall("Advapi32\GetTokenInformation", "Ptr", hToken, "UInt", TokenUIAccess := 26, "UInt*",&_isUiAccess, "UInt", 4, "UInt*", &dwLengthNeeded:=0) TokenUser := Buffer(0), TokenInformationLength := 0 while !DllCall("Advapi32.dll\GetTokenInformation", "ptr",hToken, "uint",1, "ptr",TokenUser, "uint",TokenUser.Size, "uint*",&ReturnLength:=0) ; TokenUser TokenUser.Size := ReturnLength DllCall("Advapi32.dll\ConvertSidToStringSid", "Ptr",NumGet(TokenUser, "Ptr"), "PtrP",&pSid:=0) _AsUser := StrGet(pSid+0) != "S-1-5-18" DllCall("LocalFree", "Ptr",pSid) if (!bThreadHasToken) DllCall("CloseHandle", "Ptr", hToken) ; else close token later in loop } if (!_isUiAccess) { if (!_UIA) _UIA := UiAccess() else _UIA.On(), uia_wasoff := true if !(_isUiAccess := _UIA.CheckForUiAccess()) return bThreadHasToken := true } if (_isUiAccess) { SoftwareSASGeneration := RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System", "SoftwareSASGeneration", -1) if ((ssasgNotExisting := -1) || !(SoftwareSASGeneration & 0x2)) { if (!A_IsAdmin) { return } else { try RegWrite 3, "REG_DWORD", "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System", "SoftwareSASGeneration" ; Enable services and Ease of Access apps (i.e., uiAccess applications) to simulate SAS catch writtenSsasg := false else writtenSsasg := true } } DllCall("SAS.dll\SendSAS", "Int",_AsUser) ; If current thread has token, SendSAS creates a leak of two tokens (I doin't know why) ; This hack allows to close all leaking handles if (bThreadHasToken) { if (ObjHasOwnProp(_UIA, "hTokenUIAccess") && _UIA.hTokenUIAccess) hToken := _UIA.hTokenUIAccess if (ObjHasOwnProp(_UIA, "hTokenSystem") && _UIA.hTokenSystem) hToken2 := _UIA.hTokenSystem ; Thanks Process Hacker for amaizing NT-headers ProcessHandleInformation := 51 PROCESS_HANDLE_SNAPSHOT_INFORMATION := Buffer(0x8000) ProcessHandle := DllCall("GetCurrentProcess", "Ptr") ; On Windows 8 and later, NtQueryInformationProcess with ProcessHandleInformation is the most efficient method. ; This method almost 1000x faster than NtQuerySystemInformation with SystemHandleInformation while ((sts := DllCall("ntdll\NtQueryInformationProcess", "Ptr",ProcessHandle, "UInt",ProcessHandleInformation, "Ptr",PROCESS_HANDLE_SNAPSHOT_INFORMATION , "UInt",PROCESS_HANDLE_SNAPSHOT_INFORMATION.Size, "UIntP",&bufferSize:=0, "UInt")) = 0xC0000004) ; STATUS_INFO_LENGTH_MISMATCH PROCESS_HANDLE_SNAPSHOT_INFORMATION.Size := bufferSize ; Windows 7 and early unsupported... if (!sts) { NumberOfHandles := NumGet(PROCESS_HANDLE_SNAPSHOT_INFORMATION, "UInt") pHandleInfoEntry := PROCESS_HANDLE_SNAPSHOT_INFORMATION.Ptr + 2*A_PtrSize entry_size := 3*A_PtrSize + 16 off_ObjectTypeIndex := 3*A_PtrSize + 4 ; Get LUID of current thread token TOKEN_STATISTICS := Buffer(56) DllCall("Advapi32\GetTokenInformation", "Ptr",hToken, "UInt", TokenStatistics := 10, "Ptr",TOKEN_STATISTICS, "UInt",TOKEN_STATISTICS.Size, "UInt*",&bufferSize) TokenId := NumGet(TOKEN_STATISTICS, "Int64") Loop NumberOfHandles { if (NumGet(pHandleInfoEntry + off_ObjectTypeIndex, "UInt") = 5) { ; token if ((h := NumGet(pHandleInfoEntry+0, "Ptr")) = hToken || h = hToken2) ; skip UiAccess class tokens goto check_next_handle DllCall("Advapi32\GetTokenInformation", "Ptr",h, "UInt", TokenStatistics, "Ptr",TOKEN_STATISTICS, "UInt",TOKEN_STATISTICS.Size, "UInt*",&bufferSize) if (NumGet(TOKEN_STATISTICS, "Int64") = TokenId) DllCall("CloseHandle", "Ptr", h) ; close all duplicate tokens with same LUID (even from OpenThreadToken call) } check_next_handle: pHandleInfoEntry += entry_size } } } if (writtenSsasg) { if (ssasgNotExisting) RegDelete "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System", "SoftwareSASGeneration" else RegWrite SoftwareSASGeneration, "REG_DWORD", "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System", "SoftwareSASGeneration" ; Enable services and Ease of Access apps (i.e., uiAccess applications) to simulate SAS } if (uia_wasoff) _UIA.Off() } if isUiAccess is VarRef %isUiAccess% := _isUiAccess if AsUser is VarRef %AsUser% := _AsUser } #Include