class UiAccess { __New(bOn := true, bAsSystem := false) { if (bOn = -1) return this.RunWithUiAccess(bAsSystem) this.StartAsAdmin() if (this.hTokenSystem := this.GetSystemToken()) { if (bOn) { if (!bAsSystem) this.On() else this.ImpersonateSYSTEM() } } } __Delete() { this.On(false) if (this.hTokenSystem) DllCall("CloseHandle", "ptr",this.hTokenSystem) if (this.hTokenSelf) DllCall("CloseHandle", "ptr",this.hTokenSelf) } RunWithUiAccess(bAsSystem := false) { this.StartAsAdmin() if (((isUia := this.CheckForUiAccess(false, IsSystem)) && !bAsSystem && !IsSystem) || (isUia && bAsSystem && IsSystem)) return true if !(this.hTokenSystem := this.GetSystemToken( , bAsSystem ? hTokenSystemPrimary : 0)) return false this.ImpersonateSYSTEM(false) if (!bAsSystem && DllCall("advapi32\SetTokenInformation", "ptr", this.hTokenSelf, "uint", TokenUIAccess := 26, "uint*", true, "uint", 4)) { DllCall("CloseHandle", "ptr", this.hTokenSystem), DllCall("CloseHandle", "ptr", this.hTokenSelf) Run % DllCall("GetCommandLine", "str") ExitApp } else if (bAsSystem && DllCall("advapi32\SetTokenInformation", "ptr", hTokenSystemPrimary, "uint", TokenUIAccess := 26, "uint*", true, "uint", 4)) { VarSetCapacity(PROCESS_INFORMATION, A_PtrSize*2 + 8, 0) VarSetCapacity(STARTUPINFO, A_PtrSize*9 + 32, 0) NumPut(A_PtrSize*9 + 32, &STARTUPINFO + 0, "uint") DllCall("GetStartupInfo", "ptr", &STARTUPINFO) if DllCall("advapi32\CreateProcessAsUser", "ptr", hTokenSystemPrimary, "ptr", 0, "str", DllCall("GetCommandLine", "str") , "ptr", 0, "ptr", 0, "int", false , "uint", CREATE_SUSPENDED := 0x4 , "ptr", 0, "ptr", 0, "ptr", &STARTUPINFO, "ptr", &PROCESS_INFORMATION) { hThread := NumGet(&PROCESS_INFORMATION + A_PtrSize) DllCall("CloseHandle", "ptr", NumGet(&PROCESS_INFORMATION)) DllCall("CloseHandle", "ptr", hTokenSystemPrimary) DllCall("CloseHandle", "ptr", this.hTokenSystem), DllCall("CloseHandle", "ptr", this.hTokenSelf) DllCall("ResumeThread", "Ptr",hThread), DllCall("CloseHandle", "ptr", hThread) ExitApp } } ; Cleanup on fail DllCall("CloseHandle", "ptr", this.hTokenSystem), DllCall("CloseHandle", "ptr", this.hTokenSelf) if (hTokenSystemPrimary) DllCall("CloseHandle", "ptr", hTokenSystemPrimary) return DllCall("Advapi32.dll\RevertToSelf") && false } On(bOn := true) { if (!this.hTokenSystem || !this.hTokenSelf) return false this.ImpersonateSYSTEM(false) return DllCall("advapi32\SetTokenInformation", "ptr", this.hTokenSelf, "uint", TokenUIAccess := 26, "uint*", bOn, "uint", 4) , DllCall("Advapi32.dll\RevertToSelf") } ImpersonateSYSTEM(bUiAccess := true) { if (!this.hTokenSystem) return false return DllCall("advapi32\SetThreadToken", "ptr", 0, "ptr", this.hTokenSystem) && DllCall("advapi32\SetTokenInformation", "ptr", this.hTokenSystem, "uint", TokenUIAccess := 26, "uint*", bUiAccess, "uint", 4) } CheckForUiAccess(bCheckThread := true, ByRef IsSystem := 0) { if ((bCheckThread && DllCall("Advapi32\OpenThreadToken", "Ptr", DllCall("GetCurrentThread", "Ptr"), "UInt",0x0008, "Int",false, "Ptr*", hToken)) ; TOKEN_QUERY || DllCall("Advapi32\OpenProcessToken", "Ptr", DllCall("GetCurrentProcess", "Ptr"), "UInt",0x0008, "Ptr*", hToken)) { DllCall("Advapi32\GetTokenInformation", "Ptr", hToken, "UInt", TokenUIAccess := 26, "UInt*", isUiAccess, "UInt", 4, "UInt*", dwLengthNeeded) " " A_LastError if IsByRef(IsSystem) { pTokenUser := 0, TokenInformationLength := 0 while !DllCall("Advapi32.dll\GetTokenInformation", "ptr",hToken, "uint",1, "ptr",pTokenUser, "uint",TokenInformationLength, "uint*",ReturnLength) ; TokenUser TokenInformationLength := VarSetCapacity(TokenUser, ReturnLength), pTokenUser := &TokenUser DllCall("Advapi32.dll\ConvertSidToStringSid", "Ptr",NumGet(&TokenUser+0), "PtrP",pSid) IsSystem := StrGet(pSid+0) = "S-1-5-18" DllCall("LocalFree", "Ptr",pSid) } DllCall("CloseHandle", "Ptr", hToken) } return isUiAccess } StartAsAdmin() { isRestarted := (cmd_line := DllCall("GetCommandLine", "str")) ~= " /restart(?!\S)" if not (A_IsAdmin || isRestarted) { try Run % "*RunAs " cmd_line " /restart" catch Throw Exception("Can not restart as admin!") ExitApp } else if (!A_IsAdmin && isRestarted) Throw Exception("Can not restart as admin!") } GetSystemToken(sessionId := -1, ByRef hTokenSystemPrimary := 0, ByRef WinlogonPid := 0) { static PRIVILEGE_SET_ALL_NECESSARY := 1, SE_PRIVILEGE_ENABLED := 2 if !DllCall("advapi32\LookupPrivilegeValue", "Ptr", 0, "Str", "SeTcbPrivilege", "Int64P", luid) return false VarSetCapacity(PRIVILEGE_SET, 20, 0) NumPut(1, &PRIVILEGE_SET + 0, "UInt") NumPut(PRIVILEGE_SET_ALL_NECESSARY, &PRIVILEGE_SET + 4, "UInt") NumPut(luid, &PRIVILEGE_SET + 8, "Int64P") ; TOKEN_QUERY|TOKEN_DUPLICATE|TOKEN_ADJUST_DEFAULT DllCall("advapi32\OpenProcessToken", "ptr", DllCall("GetCurrentProcess", "ptr"), "uint", 0x0008|0x0002|0x0080, "ptr*", hTokenSelf:=0) this.hTokenSelf := hTokenSelf if (sessionId = -1) DllCall("advapi32\GetTokenInformation", "ptr", hTokenSelf, "uint", 12, "uint*", TokenSelfSessionId, "uint", 4, "uint*", ReturnLength) else TokenSelfSessionId := sessionId hTokenSystem := 0 hSnapshot := DllCall("CreateToolhelp32Snapshot", "uint", TH32CS_SNAPPROCESS := 0x00000002, "uint", 0, "ptr") VarSetCapacity(PROCESSENTRY32, A_PtrSize*3 + 544, 0) NumPut(A_PtrSize*3 + 544, &PROCESSENTRY32 + 0, "uint") loop { if (A_Index = 1) hr := DllCall("Process32FirstW", "ptr", hSnapshot, "ptr", &PROCESSENTRY32) else hr := DllCall("Process32NextW", "ptr", hSnapshot, "ptr", &PROCESSENTRY32) if !hr break if (StrGet(&PROCESSENTRY32 + A_PtrSize*2 + 28, "UTF-16") = "winlogon.exe") { hProcess := DllCall("OpenProcess", "uint", PROCESS_QUERY_LIMITED_INFORMATION := 0x1000, "int", false, "uint", _WinlogonPid := NumGet(&PROCESSENTRY32 + 8, "uint"), "ptr") DllCall("advapi32\OpenProcessToken", "ptr", hProcess, "uint", 0x0008|0x0002, "ptr*", hToken) ; TOKEN_QUERY|TOKEN_DUPLICATE DllCall("advapi32\PrivilegeCheck", "ptr", hToken, "ptr", &PRIVILEGE_SET, "int*", pfResult) if pfResult { DllCall("advapi32\GetTokenInformation", "ptr", hToken, "uint", 12, "uint*", TokenSessionId, "uint", 4, "uint*", ReturnLength) if (TokenSessionId = TokenSelfSessionId) { pTokenUser := 0, TokenInformationLength := 0 while !DllCall("advapi32\GetTokenInformation", "ptr",hToken, "uint",1, "ptr",pTokenUser, "uint",TokenInformationLength, "uint*",ReturnLength) ; TokenUser TokenInformationLength := VarSetCapacity(TokenUser, ReturnLength), pTokenUser := &TokenUser DllCall("advapi32\ConvertSidToStringSid", "Ptr",NumGet(&TokenUser+0), "PtrP",pSystemSid) SystemSid := StrGet(pSystemSid+0), DllCall("LocalFree", "Ptr",pSystemSid) if (SystemSid = "S-1-5-18") { ; TOKEN_IMPERSONATE|TOKEN_QUERY|TOKEN_DUPLICATE|TOKEN_ADJUST_PRIVILEGES|TOKEN_ADJUST_DEFAULT DllCall("advapi32\DuplicateTokenEx", "ptr", hToken, "uint", 0x0004|0x0008|0x0002|0x0020|0x0080, "ptr", 0, "int", SecurityImpersonation := 2, "int", TokenImpersonation := 2, "ptr*", hTokenSystem:=0) if IsByRef(WinlogonPid) WinlogonPid := _WinlogonPid this.WinlogonPid := _WinlogonPid if IsByRef(hTokenSystemPrimary) { ; TOKEN_ASSIGN_PRIMARY|TOKEN_QUERY|TOKEN_ADJUST_DEFAULT DllCall("advapi32\DuplicateTokenEx", "ptr", hToken, "uint", 0x0001|0x0008|0x0080, "ptr", 0, "int", SecurityAnonymous := 0, "int", TokenPrimary := 1, "ptr*", hTokenSystemPrimary:=0) } } } } DllCall("CloseHandle", "ptr", hProcess) DllCall("CloseHandle", "ptr", hToken) if (hTokenSystem) { DllCall("CloseHandle", "ptr", hSnapshot) break } } } if (hTokenSystem && DllCall("advapi32\LookupPrivilegeValue", "Ptr", 0, "Str", "SeAssignPrimaryTokenPrivilege", "Int64P", luid := 0, "UInt")) { NumPut(luid, &PRIVILEGE_SET + 8, "Int64") DllCall("advapi32\PrivilegeCheck", "ptr", hTokenSystem, "ptr", &PRIVILEGE_SET, "int*", pfResult) if (!pfResult) { VarSetCapacity(TOKEN_PRIVILEGES, 16, 0) ; TOKEN_PRIVILEGES NumPut(1, &TOKEN_PRIVILEGES + 0, "UInt") NumPut(luid, &TOKEN_PRIVILEGES + 4, "Int64") NumPut(SE_PRIVILEGE_ENABLED, &TOKEN_PRIVILEGES + 12, "UInt") DllCall("advapi32\AdjustTokenPrivileges", "Ptr", hTokenSystem, "UInt", 0, "Ptr", &TOKEN_PRIVILEGES, "UInt", 0, "Ptr", 0, "Ptr", 0, "UInt") } } return hTokenSystem+0 } }