Last active
February 13, 2024 19:48
-
-
Save qwerty12/2eff3d720c06077bdd9f443e40608e63 to your computer and use it in GitHub Desktop.
Bunch of functions to help facilitate running AutoHotkey on the Winlogon desktop - https://autohotkey.com/boards/viewtopic.php?f=6&t=27709
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; LogonDesktop - run scripts on the Winlogon desktop | |
; 26/02/17 - qwerty12 | |
; Modified version of RunAsTask() by SKAN: https://autohotkey.com/boards/viewtopic.php?t=4334 | |
LogonDesktop_AddTask(runNow, runOnStartup) | |
{ | |
local TaskName, XML, TaskSchd, TaskRoot, RunAsTask | |
local TASK_CREATE := 0x2, TASK_LOGON_SERVICE_ACCOUNT := 5, scriptDir := A_ScriptDir | |
try | |
TaskSchd := ComObjCreate("Schedule.Service"), TaskSchd.Connect(), TaskRoot := TaskSchd.GetFolder("\") | |
catch | |
return "" | |
TaskName := "[AHKLogonDesktop]" . A_ScriptName . " - " . DllCall("NTDLL\RtlComputeCrc32", "Int", 0, "Ptr", &scriptDir, "UInt", StrLen(scriptDir) * 2, "UInt") | |
try | |
RunAsTask := TaskRoot.GetTask(TaskName) | |
catch | |
RunAsTask := "" | |
if (!RunAsTask) { | |
trigger := runOnStartup ? "<Triggers><BootTrigger><Enabled>true</Enabled></BootTrigger></Triggers>" : "<Triggers />" | |
XML := " | |
( LTrim Join | |
<?xml version=""1.0"" ?><Task xmlns=""http://schemas.microsoft.com/windows/2004/02/mit/task""> | |
<RegistrationInfo />" . trigger . "<Principals><Principal id=""Author""><UserId>S-1-5-18</UserId><RunLevel>HighestAvailable</RunLevel> | |
</Principal></Principals><Settings><MultipleInstancesPolicy>Parallel</MultipleInstancesPolicy> | |
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries><StopIfGoingOnBatteries>false</StopIfGoingOnBatteries> | |
<AllowHardTerminate>false</AllowHardTerminate><StartWhenAvailable>false</StartWhenAvailable><RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAva | |
ilable><IdleSettings><StopOnIdleEnd>false</StopOnIdleEnd><RestartOnIdle>false</RestartOnIdle></IdleS | |
ettings><AllowStartOnDemand>true</AllowStartOnDemand><Enabled>true</Enabled><Hidden>false</Hidden>< | |
RunOnlyIfIdle>false</RunOnlyIfIdle><DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteApp | |
Session><UseUnifiedSchedulingEngine>false</UseUnifiedSchedulingEngine><WakeToRun>false</WakeToRun>< | |
ExecutionTimeLimit>PT0S</ExecutionTimeLimit><Priority>4</Priority></Settings><Actions Context=""Author""><Exec> | |
<Command>" . """" . A_AhkPath . """" . "</Command> | |
<Arguments>" . (A_IsCompiled ? "" : """" . A_ScriptFullPath . """") . " /ErrorStdOut" . "</Arguments> | |
<WorkingDirectory>" . scriptDir . "</WorkingDirectory></Exec></Actions></Task> | |
)" | |
TaskRoot.RegisterTask(TaskName, XML, TASK_CREATE, "", "", TASK_LOGON_SERVICE_ACCOUNT) | |
} | |
if (!RunAsTask) { | |
try | |
RunAsTask := TaskRoot.GetTask(TaskName) | |
catch | |
return "" | |
} | |
if (runNow) | |
RunAsTask.Run("") | |
return TaskName | |
} | |
LogonDesktop_LaunchOnWinlogonDesktop(cmdLine, sessionId, ignoreSentinel := False, InheritHandles := False) | |
{ | |
static tokenPerms := 0x0100 | 0x0008 | 0x0002 | 0x0001, neededPrivs := {"SeTcbPrivilege": True, "SeImpersonatePrivilege": True, "SeAssignPrimaryTokenPrivilege": True, "SeIncreaseQuotaPrivilege": True} ; TOKEN_ADJUST_SESSIONID | TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | |
ret := False | |
if (!ignoreSentinel) { | |
EnvGet, _LOGON_DESKTOP_SENTINEL, _LOGON_DESKTOP_SENTINEL | |
if (_LOGON_DESKTOP_SENTINEL == "1") | |
return ret | |
} | |
if (LogonDesktop_AdjustThisProcessPrivileges(neededPrivs, PreviousState)) { | |
if (LogonDesktop_OpenProcessToken(LogonDesktop_GetCurrentProcess(), tokenPerms, hToken)) { | |
if (LogonDesktop_DuplicateTokenEx(hToken, 0x02000000, 0, 1, 1, hNewToken)) { ; MAXIMUM_ALLOWED, SecurityIdentification, TokenPrimary | |
if (_SetTokenInformation(hNewToken, 12, sessionId, 4, "UInt*")) { ; TokenSessionId | |
EnvSet, _LOGON_DESKTOP_SENTINEL, 1 | |
ret := LogonDesktop_EasyCreateProcessUsingToken(hNewToken, cmdLine, "WinSta0\Winlogon", False, InheritHandles) | |
EnvSet, _LOGON_DESKTOP_SENTINEL, 0 | |
} | |
LogonDesktop_CloseHandle(hNewToken) | |
} | |
LogonDesktop_CloseHandle(hToken) | |
} | |
LogonDesktop_AdjustThisProcessPrivileges(0, PreviousState) | |
} | |
return ret | |
} | |
_IsSystemSid(pSid) { | |
return DllCall("advapi32\IsWellKnownSid", "Ptr", pSid, "UInt", 22) ; WinLocalSystemSid | |
} | |
LogonDesktop_IsScriptProcessSYSTEM() | |
{ | |
ret := hToken := 0 | |
if (LogonDesktop_OpenProcessToken(LogonDesktop_GetCurrentProcess(), 0x0008, hToken)) { ; TOKEN_QUERY | |
if (LogonDesktop_GetTokenUser(hToken, TOKEN_USER)) | |
ret := _IsSystemSid(NumGet(TOKEN_USER,, "Ptr")) | |
LogonDesktop_CloseHandle(hToken) | |
} | |
return ret | |
} | |
LogonDesktop_AdjustTokenPrivileges(hToken, privNames, ByRef PreviousState := 0, ByRef notAllAssigned := 0) { | |
static cbTOKEN_PRIVILEGES := 16, skipPrivCount := cbTOKEN_PRIVILEGES - 4 | |
static LookupPrivilegeValueW := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "LookupPrivilegeValueW", "Ptr"), AdjustTokenPrivileges := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "AdjustTokenPrivileges", "Ptr") | |
ret := False | |
DllCall("SetLastError", "UInt", 0) | |
if (IsObject(privNames)) { | |
if (!(privNamesOrPrevStateLen := privNames.SetCapacity(0))) | |
return ret | |
VarSetCapacity(TOKEN_PRIVILEGES, (sizeTp := 4 + (skipPrivCount * privNamesOrPrevStateLen)), 0) | |
NumPut(privNamesOrPrevStateLen, TOKEN_PRIVILEGES,, "UInt") | |
for priv, enabled in privNames { | |
luidOffset := 4 + (skipPrivCount * (A_Index - 1)) | |
if (DllCall(LookupPrivilegeValueW, "Ptr", 0, "WStr", priv, "Ptr", &TOKEN_PRIVILEGES+luidOffset)) | |
if (enabled) | |
NumPut(0x00000002, TOKEN_PRIVILEGES, luidOffset+8, "UInt") | |
} | |
} else { | |
if (!privNames && !IsByRef(PreviousState)) | |
return ret | |
} | |
if (hToken) { | |
psBr := IsByRef(PreviousState) | |
if (privNames) { | |
if (psBr) | |
VarSetCapacity(PreviousState, sizeTp, 0) | |
ret := DllCall(AdjustTokenPrivileges, "Ptr", hToken, "Int", False, "Ptr", &TOKEN_PRIVILEGES, "UInt", psBr ? 0 : sizeTp, "Ptr", psBr ? &PreviousState : 0, "UInt*", ReturnLength) | |
if (!ret && psBr && ReturnLength && A_LastError == 122) { ; ERROR_INSUFFICIENT_BUFFER | |
VarSetCapacity(PreviousState, ReturnLength) | |
ret := DllCall(AdjustTokenPrivileges, "Ptr", hToken, "Int", False, "Ptr", &TOKEN_PRIVILEGES, "UInt", ReturnLength, "Ptr", &PreviousState, "UInt*", ReturnLength) | |
} | |
} else { | |
if (psBr && PreviousState) | |
ret := DllCall(AdjustTokenPrivileges, "Ptr", hToken, "Int", False, "Ptr", &PreviousState, "UInt", 0, "Ptr", 0, "Ptr", 0) | |
} | |
} | |
if (ret) | |
notAllAssigned := A_LastError == 1300 ; ERROR_NOT_ALL_ASSIGNED | |
return ret | |
} | |
LogonDesktop_AdjustThisProcessPrivileges(privNames, ByRef PreviousState := 0, ByRef notAllAssigned := 0) { | |
ret := False | |
if (LogonDesktop_OpenProcessToken(LogonDesktop_GetCurrentProcess(), 0x0028, hToken)) { ; TOKEN_ADJUST_PRIVILEGES := 0x0020 | TOKEN_QUERY := 0x0008 | |
ret := LogonDesktop_AdjustTokenPrivileges(hToken, privNames, PreviousState, notAllAssigned) | |
LogonDesktop_CloseHandle(hToken) | |
} | |
return ret | |
} | |
LogonDesktop_EasyCreateProcessUsingToken(hToken, cmdLine, desktop, useTokenEnvBlock, InheritHandles := False, ShowWindow := -1) { | |
ret := envModule := pEnv := 0 | |
if (!cmdLine) | |
return ret | |
if (useTokenEnvBlock) { | |
if (!(envModule := _PrepareEnvironmentBlockCall())) | |
return ret | |
; http://stackoverflow.com/a/13733317 | |
if (!_CreateEnvironmentBlock(pEnv, hToken, False)) { | |
_EndEnvironmentBlockCall(envModule) | |
return ret | |
} | |
} | |
_PROCESS_INFORMATION(pi) | |
_STARTUPINFO(si, desktop ? &desktop : 0, ShowWindow) | |
dwCreationFlags := 0x01000000 | (pEnv ? 0x00000400 : 0) ; CREATE_BREAKAWAY_FROM_JOB | CREATE_UNICODE_ENVIRONMENT | |
if (!(ret := _CreateProcessAsUserW(hToken, 0, &cmdLine, 0, 0, InheritHandles, dwCreationFlags, pEnv, 0, &si, &pi))) | |
ret := _CreateProcessWithTokenW(hToken, 0x00000001, 0, &cmdLine, dwCreationFlags, pEnv, 0, &si, &pi) ; LOGON_WITH_PROFILE | |
if (ret) { | |
LogonDesktop_CloseHandle(_PROCESS_INFORMATION_hProcess(pi)) | |
LogonDesktop_CloseHandle(_PROCESS_INFORMATION_hThread(pi)) | |
} | |
if (useTokenEnvBlock) { | |
if (pEnv) | |
_DestroyEnvironmentBlock(pEnv) | |
if (envModule) | |
_EndEnvironmentBlockCall(envModule) | |
} | |
return ret | |
} | |
LogonDesktop_WaitForTermSrvInit() | |
{ | |
ret := False | |
if ((TermSrvReadyEvent := DllCall("OpenEventW", "UInt", 0x00100000, "Int", False, "WStr", "Global\TermSrvReadyEvent", "Ptr"))) { ; SYNCHRONIZE | |
ret := DllCall("WaitForSingleObject", "Ptr", TermSrvReadyEvent, "UInt", -1) == 0 | |
LogonDesktop_CloseHandle(TermSrvReadyEvent) | |
} | |
return ret | |
} | |
/* | |
; NOTE: I don't recommend using LogonDesktop_WaitForDesktopSwitchSync(). With AutoHotkey, it's nicer to use the accessibility framework to be be notified asynchronously: | |
OnDesktopSwitch(hWinEventHook, event, hWnd, idObject, idChild, dwEventThread, dwmsEventTime) | |
{ | |
MsgBox Desktop switched | |
} | |
DllCall("SetWinEventHook", "UInt", (EVENT_SYSTEM_DESKTOPSWITCH := 0x0020), "UInt", EVENT_SYSTEM_DESKTOPSWITCH, "Ptr", 0, "Ptr", (lpfnWinEventProc := RegisterCallback("OnDesktopSwitch", "")), "UInt", 0, "UInt", 0, "UInt", WINEVENT_OUTOFCONTEXT := 0x0000 | WINEVENT_SKIPOWNPROCESS := 0x0002) | |
(You should include a corresponding call to UnhookWinEvent, and GlobalFree for the callback function pointer at exit.) | |
; If you really don't want to use the accessibility framework, you might be able to use RegisterWaitForSingleObject in lieu of MsgWaitForMultipleObjectsEx, | |
; in combination with Lexikos' RegisterSyncCallback library to be notified asynchronously, in the style of SetWinEventHook. | |
*/ | |
; The following blocks the current thread unless a message is recieved, waiting fails or WinSta0_DesktopSwitch is signalled | |
LogonDesktop_WaitForDesktopSwitchSync() | |
{ | |
static SYNCHRONIZE := 0x00100000, evt := DllCall("OpenEventW", "UInt", SYNCHRONIZE, "Int", False, "WStr", "WinSta0_DesktopSwitch", "Ptr"), MsgWaitForMultipleObjectsEx := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "user32.dll", "Ptr"), "AStr", "MsgWaitForMultipleObjectsEx", "Ptr") | |
desktopSwitched := False | |
Loop { | |
r := DllCall(MsgWaitForMultipleObjectsEx, "UInt", 1, "Ptr*", evt, "UInt", -1, "UInt", 0x4FF, "UInt", 0x0002) ; INFINITE, QS_ALLINPUT, MWMO_ALERTABLE - stolen from Lexikos | |
Sleep -1 ; let AutoHotkey process messages | |
if (r == 0) { ; WAIT_OBJECT_0 | |
desktopSwitched := True | |
break | |
} else if (r == -1) { ; WAIT_FAILED | |
break | |
} | |
} | |
;LogonDesktop_CloseHandle(evt) | |
return desktopSwitched | |
} | |
LogonDesktop_GetTokenUser(hToken, ByRef TOKEN_USER) | |
{ | |
ret := dwLengthNeeded := 0 | |
if (!_GetTokenInformation(hToken, TokenUser := 1, 0, 0, dwLengthNeeded)) | |
if (A_LastError == 122 && VarSetCapacity(TOKEN_USER, dwLengthNeeded)) ; ERROR_INSUFFICIENT_BUFFER | |
ret := _GetTokenInformation(hToken, TokenUser, &TOKEN_USER, dwLengthNeeded, dwLengthNeeded) | |
return ret | |
} | |
_LookupAccountSidW(lpSid, ByRef username, ByRef domain := 0, ByRef use := 0) ; thanks to jNizM: https://autohotkey.com/boards/viewtopic.php?t=4365 | |
{ | |
cchName := cchReferencedDomainName := 0 | |
if (!DllCall("advapi32.dll\LookupAccountSidW", "Ptr", 0, "Ptr", lpSid, "Ptr", 0, "UInt*", cchName, "Ptr", 0, "UInt*", cchReferencedDomainName, "UInt*", peUse) && A_LastError == 122) { | |
VarSetCapacity(n, cchName * 2), VarSetCapacity(d, cchReferencedDomainName * 2) | |
ret := DllCall("advapi32.dll\LookupAccountSidW", "Ptr", 0, "Ptr", lpSid, "Ptr", &n, "UInt*", cchName, "Ptr", &d, "UInt*", cchReferencedDomainName, "UInt*", peUse) | |
if (ret) { | |
if (IsByRef(username)) | |
username := StrGet(&n,, "UTF-16") | |
if (IsByRef(domain)) | |
domain := StrGet(&d,, "UTF-16") | |
if (IsByRef(use)) | |
use := _use | |
} | |
return ret | |
} | |
return False | |
} | |
LogonDesktop_GetTokenUsername(hToken, ByRef username, ByRef domain := 0, ByRef use := 0) | |
{ | |
if (LogonDesktop_GetTokenUser(hToken, TOKEN_USER)) | |
return _LookupAccountSidW(NumGet(TOKEN_USER,, "Ptr"), username, domain, use) | |
return False | |
} | |
LogonDesktop_GetProcessWindowStationName(ByRef out) | |
{ | |
ret := False | |
if ((hWinSta := DllCall("GetProcessWindowStation", "Ptr"))) | |
ret := LogonDesktop_GetUserObjectName(hWinSta, out) | |
return ret | |
} | |
LogonDesktop_GetThreadDesktopName(ByRef out, tId := -1) | |
{ | |
ret := False | |
if ((hDesk := DllCall("GetThreadDesktop", "UInt", tId == -1 ? DllCall("GetCurrentThreadId", "UInt") : tId, "Ptr"))) | |
ret := LogonDesktop_GetUserObjectName(hDesk, out) | |
return ret | |
} | |
LogonDesktop_ProcessIdToSessionId(dwProcessId, ByRef dwSessionId) | |
{ | |
static ProcessIdToSessionId := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "kernel32.dll", "Ptr"), "AStr", "ProcessIdToSessionId", "Ptr") | |
return DllCall(ProcessIdToSessionId, "UInt", dwProcessId, "UInt*", dwSessionId) | |
} | |
/* | |
LogonDesktop_OpenProcessToken(LogonDesktop_GetCurrentProcess(), 0x0008, hToken) ; TOKEN_QUERY | |
if (!LogonDesktop_GetTokenSessionId(hToken, scriptSessionId)) | |
return | |
LogonDesktop_CloseHandle(hToken) | |
*/ | |
LogonDesktop_GetTokenSessionId(hToken, ByRef out) | |
{ | |
ret := dwLengthNeeded := 0 | |
if (hToken) | |
ret := _GetTokenInformation(hToken, 12, out, 4, dwLengthNeeded, "UInt*") ; TokenSessionId | |
return ret | |
} | |
LogonDesktop_PossiblyDetermineIfUnelevatedUserCanWriteToScript() | |
{ | |
AccessStatus := grantedAccess := hPrimaryToken := TokenIsElevated := hToken := dwLengthNeeded := ret := 0 | |
if ((desktopHwnd := DllCall("GetShellWindow", "Ptr"))) { | |
WinGet, explorerPid, PID, ahk_id %desktopHwnd% | |
if (explorerPid) { | |
if ((hProc := DllCall("OpenProcess", "UInt", PROCESS_QUERY_LIMITED_INFORMATION := 0x1000, "Int", False, "UInt", explorerPid, "Ptr"))) { | |
if (LogonDesktop_OpenProcessToken(hProc, TOKEN_QUERY := 0x0008 | TOKEN_DUPLICATE := 0x0002, hToken)) { | |
if (_GetTokenInformation(hToken, TokenElevation := 20, TokenIsElevated, 4, dwLengthNeeded, "UInt*")) { | |
if (!TokenIsElevated) { | |
; From Aaron Ballman @ http://blog.aaronballman.com/2011/08/how-to-check-access-rights/ | |
dwLengthNeeded := 0 | |
if (!DllCall("advapi32.dll\GetFileSecurity", "WStr", A_ScriptFullPath, "UInt", DACL_SECURITY_INFORMATION := 0x00000004 | OWNER_SECURITY_INFORMATION := 0x00000001 | GROUP_SECURITY_INFORMATION := 0x00000002, "Ptr", 0, "Ptr", 0, "UInt*", dwLengthNeeded)) { | |
if (A_LastError == (ERROR_INSUFFICIENT_BUFFER := 122) && VarSetCapacity(sd, dwLengthNeeded) && DllCall("advapi32.dll\GetFileSecurity", "WStr", A_ScriptFullPath, "UInt", DACL_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION, "Ptr", &sd, "Ptr", dwLengthNeeded, "UInt*", dwLengthNeeded)) { | |
VarSetCapacity(GENERIC_MAPPING, 16) | |
NumPut(0x00020000 | 0x0001 | 0x0080 | 0x0008 | 0x00100000, GENERIC_MAPPING, 0, "UInt") | |
NumPut(0x00020000 | 0x0002 | 0x0100 | 0x0010 | 0x0004 | 0x00100000, GENERIC_MAPPING, 4, "UInt") | |
NumPut(0x00020000 | 0x0080 | 0x0020 | 0x00100000, GENERIC_MAPPING, 8, "UInt") | |
NumPut(0x000F0000 | 0x00100000 | 0x1FF, GENERIC_MAPPING, 12, "UInt") | |
GENERIC_WRITE := 0x40000000 | |
VarSetCapacity(PRIVILEGE_SET, cbPS := 20, 0) | |
DllCall("advapi32.dll\MapGenericMask", "UInt*", GENERIC_WRITE, "Ptr", &GENERIC_MAPPING) | |
if (DllCall("advapi32.dll\DuplicateToken", "Ptr", hToken, "UInt", SecurityIdentification := 1, "Ptr*", hPrimaryToken)) { | |
if (DllCall("advapi32.dll\AccessCheck", "Ptr", &sd, "Ptr", hPrimaryToken, "UInt", GENERIC_WRITE, "Ptr", &GENERIC_MAPPING, "Ptr", &PRIVILEGE_SET, "UInt*", cbPS, "UInt*", grantedAccess, "Int*", AccessStatus)) | |
ret := AccessStatus | |
LogonDesktop_CloseHandle(hPrimaryToken) | |
} | |
} | |
} | |
} | |
} | |
LogonDesktop_CloseHandle(hToken) | |
} | |
LogonDesktop_CloseHandle(hProc) | |
} | |
} | |
} | |
return ret | |
} | |
; Pretty much from the GetEffectiveRightsFromAcl MSDN sample | |
LogonDesktop_AllUsersCanWriteToThisScript() | |
{ | |
; This doesn't check the allowed ACEs for users that are only part of the Users group. Bear that in mind... | |
hAuthzResourceManager := hAuthzClientContext := psd := pacl := ret := 0 | |
SECURITY_MAX_SID_SIZE := 68 | |
SIDs := {"WinBuiltinUsersSid": "27", "WinWorldSid": "1"} | |
for k, v in SIDs { | |
cbSize := SECURITY_MAX_SID_SIZE | |
SIDs.SetCapacity(k, cbSize) | |
if (!_CreateWellKnownSid(v+0, 0, SIDs.GetAddress(k), cbSize)) | |
return ret | |
} | |
if (!authzMod := _LoadLibrary("Authz.dll")) | |
return ret | |
if (!DllCall("advapi32.dll\GetNamedSecurityInfoW", "WStr", A_ScriptFullPath, "UInt", SE_FILE_OBJECT := 1, "UInt", DACL_SECURITY_INFORMATION := 0x00000004 | OWNER_SECURITY_INFORMATION := 0x00000001 | GROUP_SECURITY_INFORMATION := 0x00000002, "Ptr", 0, "Ptr", 0, "Ptr*", pacl, "Ptr", 0, "Ptr*", psd, "UInt")) { | |
if (DllCall("Authz\AuthzInitializeResourceManager", "UInt", AUTHZ_RM_FLAG_NO_AUDIT := 0x1, "Ptr", 0, "Ptr", 0, "Ptr", 0, "Ptr", 0, "Ptr*", hAuthzResourceManager)) { | |
for k, v in SIDs { | |
if (DllCall("Authz\AuthzInitializeContextFromSid", "UInt", 0, "Ptr", SIDs.GetAddress(k), "Ptr", hAuthzResourceManager, "Ptr", 0, "Int64", 0, "Ptr", 0, "Ptr*", hAuthzClientContext)) { | |
VarSetCapacity(AUTHZ_ACCESS_REQUEST, 20 * (A_PtrSize == 8 ? 2 : 1), 0) | |
VarSetCapacity(AUTHZ_ACCESS_REPLY, 16 * (A_PtrSize == 8 ? 2 : 1), 0) | |
VarSetCapacity(buf, 1024, 0) | |
NumPut(MAXIMUM_ALLOWED := 0x02000000, AUTHZ_ACCESS_REQUEST,, "UInt") | |
NumPut(1, AUTHZ_ACCESS_REPLY,, "UInt") | |
NumPut(&buf, AUTHZ_ACCESS_REPLY, A_PtrSize, "Ptr") | |
NumPut(&buf+4, AUTHZ_ACCESS_REPLY, 12 * (A_PtrSize == 8 ? 2 : 1), "Ptr") | |
if (DllCall("Authz\AuthzAccessCheck", "UInt", 0, "Ptr", hAuthzClientContext, "Ptr", &AUTHZ_ACCESS_REQUEST, "Ptr", 0, "Ptr", psd, "Ptr", 0, "UInt", 0, "Ptr", &AUTHZ_ACCESS_REPLY, "Ptr", 0)) { | |
GrantedAccessMask := NumGet(buf,, "UInt") | |
GENERIC_WRITE := 0x40000000 | |
FILE_GENERIC_WRITE := 0x00020000 | 0x0002 | 0x0100 | 0x0010 | 0x0004 | 0x00100000 | |
if (((GrantedAccessMask & GENERIC_WRITE) == GENERIC_WRITE) || ((GrantedAccessMask & FILE_GENERIC_WRITE) == FILE_GENERIC_WRITE)) | |
ret := True | |
} | |
DllCall("Authz\AuthzFreeContext", "Ptr", hAuthzClientContext) | |
VarSetCapacity(buf, 0) | |
if (ret) | |
break | |
} | |
} | |
DllCall("Authz\AuthzFreeResourceManager", "Ptr", hAuthzResourceManager) | |
} | |
} | |
_FreeLibrary(authzMod) | |
return ret | |
} | |
LogonDesktop_SetUiAccessToken(hToken, reallyHigh) { | |
; Unsure if there is more to it | |
static tilSize := 8 * (A_PtrSize == 8 ? 2 : 1), SECURITY_LABEL_MEDIUM_MORE_SID := 0, SECURITY_LABEL_HIGH_SID | |
if (hToken) { | |
if (reallyHigh) { | |
; 0x3000 | |
if (!VarSetCapacity(SECURITY_LABEL_HIGH_SID)) { | |
VarSetCapacity(SECURITY_LABEL_HIGH_SID, cbSize := 256) ; MAX_SID_SIZE | |
if (!_CreateWellKnownSid(68, 0, &SECURITY_LABEL_HIGH_SID, cbSize)) ; WinHighLabelSid | |
return | |
} | |
} else { | |
; SECURITY_MANDATORY_MEDIUM_RID (0x2000) + 0x10 - not the same thing as SECURITY_MANDATORY_MEDIUM_PLUS_RID (0x100)! | |
if (!SECURITY_LABEL_MEDIUM_MORE_SID) { | |
if (!DllCall("advapi32.dll\ConvertStringSidToSidW", "WStr", "S-1-16-8208", "Ptr*", SECURITY_LABEL_MEDIUM_MORE_SID)) ; "higherIntegrityLevelSidForLimitedAccounts" | |
return | |
} | |
} | |
lpSecLabel := reallyHigh ? &SECURITY_LABEL_HIGH_SID : SECURITY_LABEL_MEDIUM_MORE_SID | |
if (_SetTokenInformation(hToken, 26, True, 4, "UInt*")) { ; TokenUIAccess | |
; https://msdn.microsoft.com/en-us/library/bb625960.aspx | |
VarSetCapacity(TOKEN_MANDATORY_LABEL, tilSize, 0), NumPut(lpSecLabel, TOKEN_MANDATORY_LABEL,, "Ptr"), NumPut(0x00000020, TOKEN_MANDATORY_LABEL, A_PtrSize, "UInt") ; SE_GROUP_INTEGRITY | |
_SetTokenInformation(hToken, 25, &TOKEN_MANDATORY_LABEL, tilSize + _GetLengthSid(lpSecLabel)) ; TokenIntegrityLevel | |
} | |
; if (SECURITY_LABEL_MEDIUM_MORE_SID) | |
; DllCall("LocalFree", "Ptr", SECURITY_LABEL_MEDIUM_MORE_SID, "Ptr") | |
} | |
} | |
; https://code.msdn.microsoft.com/windowsapps/CppUACSelfElevation-5bfc52dd | |
LogonDesktop_DoesTokenContainAdminGroupDirectlyOrNot(hToken, fallBackToLegacyMethod := False) | |
{ | |
static adminSID, CheckTokenMembership := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "CheckTokenMembership", "Ptr"), DuplicateToken := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "DuplicateToken", "Ptr") | |
hTokenToCheck := fInAdminGroup := 0 | |
if (!hToken) | |
return fInAdminGroup | |
; Create the SID corresponding to the Administrators group. | |
if (!VarSetCapacity(adminSID)) { | |
VarSetCapacity(adminSID, cbSize := 68) ; SECURITY_MAX_SID_SIZE | |
if (!_CreateWellKnownSid(26, 0, &adminSID, cbSize)) { ; WinBuiltinAdministratorsSid | |
VarSetCapacity(adminSID, 0) | |
return fInAdminGroup | |
} | |
} | |
; Determine token type: limited, elevated, or default | |
if (!_GetTokenInformation(hToken, 18, elevType, 4, cbSize, "UInt*")) ; TokenElevationType | |
return fInAdminGroup | |
; If limited, get the linked elevated token for further check. | |
if (3 == elevType) ; TokenElevationTypeLimited | |
{ | |
if (!_GetTokenInformation(hToken, 19, hTokenToCheck, A_PtrSize, cbSize, "Ptr*")) ; TokenLinkedToken | |
return fInAdminGroup | |
} | |
/* CheckTokenMembership requires an impersonation token. If we just got a | |
linked token, it already is an impersonation token. If we did not get | |
a linked token, duplicate the original into an impersonation token for | |
CheckTokenMembership. | |
*/ | |
if (!hTokenToCheck) | |
{ | |
if (!DllCall(DuplicateToken, "Ptr", hToken, "UInt", 1, "Ptr*", hTokenToCheck)) ; SecurityIdentification | |
return fInAdminGroup | |
} | |
/* Check if the token to be checked contains admin SID. | |
http://msdn.microsoft.com/en-us/library/aa379596(VS.85).aspx: | |
To determine whether a SID is enabled in a token, that is, whether it | |
has the SE_GROUP_ENABLED attribute, call CheckTokenMembership. | |
*/ | |
if (!DllCall(CheckTokenMembership, "Ptr", hTokenToCheck, "Ptr", &adminSID, "Int*", fInAdminGroup) && fallBackToLegacyMethod && A_LastError == 1309) ; ERROR_NO_IMPERSONATION_TOKEN | |
fInAdminGroup := _DetermineIfTheTokenHasAGroupTheNT4Way(hTokenToCheck, &adminSID) | |
if (hTokenToCheck) | |
LogonDesktop_CloseHandle(hTokenToCheck) | |
return fInAdminGroup | |
} | |
_isTokenUiAccess(hToken) | |
{ | |
ret := False | |
if (hToken) | |
_GetTokenInformation(hToken, TokenUIAccess := 26, ret, 4, dwLengthNeeded, "UInt*") | |
return ret | |
} | |
LogonDesktop_isThisProcessUiAccess() | |
{ | |
ret := False | |
if (LogonDesktop_OpenProcessToken(LogonDesktop_GetCurrentProcess(), TOKEN_QUERY := 0x0008, hToken)) { | |
ret := _isTokenUiAccess(hToken) | |
LogonDesktop_CloseHandle(hToken) | |
} | |
return ret | |
} | |
LogonDesktop_isThisProcessHighIntegrity() | |
{ | |
ret := false | |
if (LogonDesktop_OpenProcessToken(LogonDesktop_GetCurrentProcess(), TOKEN_QUERY := 0x0008, hToken)) { | |
if (!_GetTokenInformation(hToken, TokenIntegrityLevel := 25, 0, 0, dwLengthNeeded)) | |
if (A_LastError == (ERROR_INSUFFICIENT_BUFFER := 122)) | |
if (VarSetCapacity(pTIL, dwLengthNeeded) && _GetTokenInformation(hToken, TokenIntegrityLevel, &pTIL, dwLengthNeeded, dwLengthNeeded)) | |
ret := (DllCall("advapi32.dll\GetSidSubAuthority", "Ptr", (pSid := NumGet(pTil,, "Ptr")), "UInt", DllCall("advapi32.dll\GetSidSubAuthorityCount", "Ptr", pSid, "UChar*")-1, "UInt*")) >= 0x00002010 | |
LogonDesktop_CloseHandle(hToken) | |
} | |
return ret | |
} | |
LogonDesktop_SessionIsLocked(sessionId) | |
{ | |
static WTS_CURRENT_SERVER_HANDLE := 0, WTSSessionInfoEx := 25, WTS_SESSIONSTATE_LOCK := 0x00000000, WTS_SESSIONSTATE_UNLOCK := 0x00000001 ;, WTS_SESSIONSTATE_UNKNOWN := 0xFFFFFFFF | |
ret := False | |
if (DllCall("wtsapi32\WTSQuerySessionInformation", "Ptr", WTS_CURRENT_SERVER_HANDLE, "UInt", sessionId, "UInt", WTSSessionInfoEx, "Ptr*", sesInfo, "Ptr*", BytesReturned)) { | |
SessionFlags := NumGet(sesInfo+0, 16, "Int") | |
; "Windows Server 2008 R2 and Windows 7: Due to a code defect, the usage of the WTS_SESSIONSTATE_LOCK and WTS_SESSIONSTATE_UNLOCK flags is reversed." | |
ret := A_OSVersion != "WIN_7" ? SessionFlags == WTS_SESSIONSTATE_LOCK : SessionFlags == WTS_SESSIONSTATE_UNLOCK | |
DllCall("wtsapi32\WTSFreeMemory", "Ptr", sesInfo) | |
} | |
return ret | |
} | |
LogonDesktop_WTSEnumerateProcessesEx(ByRef WTS, hServer := 0, SessionID := 0xFFFFFFFE) ; WTS_CURRENT_SERVER_HANDLE, WTS_ANY_SESSION | |
{ ; Todo: 32-Bit support. https://msdn.microsoft.com/en-us/library/ee621013(v=vs.85).aspx. Based on jNizM's code: https://github.com/jNizM/AHK_ProcessExplorer/blob/HEAD/src/ProcessExplorer.ahk#L112 | |
local PI := PI_EX := TTL := 0 | |
if (!DllCall("wtsapi32\WTSEnumerateProcessesEx", "ptr", hServer, "UInt*", 1, "UInt", SessionID, "Ptr*", PI_EX, "UInt*", TTL)) | |
return False | |
PI := PI_EX, WTS := [] | |
loop % TTL | |
{ | |
entry := {"SessionID": NumGet(PI+0, "UInt") | |
,"ProcessID": NumGet(PI+4, "UInt") | |
,"ProcessName": StrGet(NumGet(PI+8, "ptr")) | |
,"NumberOfThreads": NumGet(PI+24, "UInt") | |
,"HandleCount": NumGet(PI+28, "UInt") | |
,"PagefileUsage": NumGet(PI+32, "UInt") | |
,"PeakPagefileUsage": NumGet(PI+36, "UInt") | |
,"WorkingSetSize": NumGet(PI+40, "UInt") | |
,"PeakWorkingSetSize": NumGet(PI+44, "UInt") | |
,"UserTime": NumGet(PI+48, "Int64") | |
,"KernelTime": NumGet(PI+56, "Int64")} | |
SID := NumGet(PI+16, "ptr") | |
if (_IsValidSid(SID)) { | |
if (_LookupAccountSidW(SID, Name, Domain)) { | |
entry["UserName"] := Name | |
entry["UserDomain"] := Domain | |
} | |
SIDLength := _GetLengthSid(SID) | |
if (entry.SetCapacity("UserSID", SIDLength) >= SIDLength) | |
DllCall("ntdll\RtlMoveMemory", "Ptr", entry.GetAddress("UserSID"), "Ptr", SID, "Ptr", SIDLength) | |
} | |
WTS.Push(entry) | |
PI += 64 | |
} | |
DllCall("wtsapi32\WTSFreeMemoryEx", "UInt", 1, "ptr", PI_EX, "UInt", TTL) | |
return True | |
} | |
_DetermineIfTheTokenHasAGroupTheNT4Way(hToken, pSid) { ; Seriously, don't use this. | |
static SE_GROUP_ENABLED := 0x00000004, SE_GROUP_USE_FOR_DENY_ONLY := 0x00000010, cbSID_AND_ATTRIBUTES := 8 * (A_PtrSize == 8 ? 2 : 1) | |
retval := False | |
if (!hToken || !pSid) | |
return retval | |
if (!_GetTokenInformation(hToken, TokenGroups := 2, 0, 0, dwSize)) | |
if (A_LastError != 122) ; ERROR_INSUFFICIENT_BUFFER | |
return retval | |
VarSetCapacity(groupInfo, dwSize, 0) | |
if (!_GetTokenInformation(hToken, TokenGroups, &groupInfo, dwSize, dwSize)) | |
return retval | |
GroupCount := NumGet(groupInfo,, "UInt") | |
Loop % GroupCount { | |
currGroupOffset := A_PtrSize + (cbSID_AND_ATTRIBUTES * (A_Index - 1)) | |
Attributes := NumGet(groupInfo, currGroupOffset + A_PtrSize, "UInt") | |
if (Attributes & SE_GROUP_USE_FOR_DENY_ONLY) | |
continue | |
if ((Attributes & SE_GROUP_ENABLED) && _EqualSid(pSID, NumGet(groupInfo, currGroupOffset, "Ptr"))) { | |
retval := true | |
break | |
} | |
} | |
return retval | |
} | |
_EqualSid(pSid1, pSid2) | |
{ | |
static EqualSid := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "EqualSid", "Ptr") | |
return DllCall(EqualSid, "Ptr", pSid1, "Ptr", pSid2) | |
} | |
LogonDesktop_GetUserObjectName(hObj, ByRef out) { | |
static GetUserObjectInformationW := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "user32.dll", "Ptr"), "AStr", "GetUserObjectInformationW", "Ptr") | |
nLengthNeeded := VarSetCapacity(out) | |
if (!(ret := DllCall(GetUserObjectInformationW, "Ptr", hObj, "Int", 2, "WStr", out, "UInt", nLengthNeeded, "UInt*", nLengthNeeded))) ; UOI_NAME | |
if (A_LastError == 122 && VarSetCapacity(out, nLengthNeeded)) ; ERROR_INSUFFICIENT_BUFFER | |
ret := DllCall(GetUserObjectInformationW, "Ptr", hObj, "Int", 2, "WStr", out, "UInt", nLengthNeeded, "Ptr", 0) | |
return ret | |
} | |
_OnWinLogonDesktop() | |
{ | |
static OpenInputDesktop := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "user32.dll", "Ptr"), "AStr", "OpenInputDesktop", "Ptr"), desktopName | |
if !VarSetCapacity(desktopName) | |
VarSetCapacity(desktopName, 65534) | |
if hDesk := DllCall(OpenInputDesktop, "UInt", 0, "Int", False, "UInt", 0, "Ptr") | |
return !LogonDesktop_GetUserObjectName(hDesk, desktopName) || desktopName == "Winlogon", LogonDesktop_CloseDesktop(hDesk) | |
return True | |
} | |
LogonDesktop_LoadWtsApi() { | |
static lib := "wtsapi32.dll" | |
return _LoadLibrary(lib) | |
} | |
LogonDesktop_UnloadWtsApi(wtsapiModule) { | |
return _FreeLibrary(wtsapiModule) | |
} | |
LogonDesktop_WTSQueryUserToken(SessionId, ByRef phToken) { | |
return DllCall("wtsapi32\WTSQueryUserToken", "UInt", SessionId, "Ptr*", phToken) | |
} | |
LogonDesktop_DuplicateTokenEx(hExistingToken, dwDesiredAccess, lpTokenAttributes, ImpersonationLevel, TokenType, ByRef phNewToken) { | |
static DuplicateTokenEx := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "DuplicateTokenEx", "Ptr") | |
return DllCall(DuplicateTokenEx, "Ptr", hExistingToken, "UInt", dwDesiredAccess, "Ptr", lpTokenAttributes, "UInt", ImpersonationLevel, "UInt", TokenType, "Ptr*", phNewToken) | |
} | |
_CreateProcessAsUserW(hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation) { | |
static CreateProcessAsUserW := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "CreateProcessAsUserW", "Ptr") | |
return DllCall(CreateProcessAsUserW, "Ptr", hToken, "Ptr", lpApplicationName, "Ptr", lpCommandLine, "Ptr", lpProcessAttributes, "Ptr", lpThreadAttributes, "Int", bInheritHandles, "UInt", dwCreationFlags, "Ptr", lpEnvironment, "Ptr", lpCurrentDirectory, "Ptr", lpStartupInfo, "Ptr", lpProcessInformation) | |
} | |
_CreateProcessWithTokenW(hToken, dwLogonFlags, lpApplicationName, lpCommandLine, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInfo) { | |
static CreateProcessWithTokenW := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "CreateProcessWithTokenW", "Ptr") | |
return DllCall(CreateProcessWithTokenW, "Ptr", hToken, "UInt", dwLogonFlags, "Ptr", lpApplicationName, "Ptr", lpCommandLine, "UInt", dwCreationFlags, "Ptr", lpEnvironment, "Ptr", lpCurrentDirectory, "Ptr", lpStartupInfo, "Ptr", lpProcessInformation) | |
} | |
LogonDesktop_OpenProcessToken(ProcessHandle, DesiredAccess, ByRef TokenHandle) { | |
static OpenProcessToken := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "OpenProcessToken", "Ptr") | |
return DllCall(OpenProcessToken, "Ptr", ProcessHandle, "UInt", DesiredAccess, "Ptr*", TokenHandle) | |
} | |
LogonDesktop_CloseHandle(hObject) { | |
static CloseHandle := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "kernel32.dll", "Ptr"), "AStr", "CloseHandle", "Ptr"), INVALID_HANDLE_VALUE := -1 | |
return (hObject && hObject != INVALID_HANDLE_VALUE) ? DllCall(CloseHandle, "Ptr", hObject) : False | |
} | |
LogonDesktop_CloseDesktop(hDesktop) { | |
static CloseDesktop := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "user32.dll", "Ptr"), "AStr", "CloseDesktop", "Ptr") | |
return DllCall(CloseDesktop, "Ptr", hDesktop) | |
} | |
_PROCESS_INFORMATION(ByRef pi) { | |
static piCb := A_PtrSize == 8 ? 24 : 16 | |
if (IsByRef(pi)) | |
VarSetCapacity(pi, piCb, 0) | |
} | |
_PROCESS_INFORMATION_hProcess(ByRef pi) { | |
return NumGet(pi,, "Ptr") | |
} | |
_PROCESS_INFORMATION_hThread(ByRef pi) { | |
return NumGet(pi, A_PtrSize, "Ptr") | |
} | |
_STARTUPINFO(ByRef si, lpDesktop := 0, ShowWindow := -1, restOneDay*) { | |
static siCb := A_PtrSize == 8 ? 104 : 68 | |
if (IsByRef(si)) { | |
dwFlags := 0 | |
VarSetCapacity(si, siCb, 0), NumPut(siCb, si,, "UInt") | |
if (lpDesktop) | |
NumPut(lpDesktop, si, A_PtrSize * 2, "Ptr") | |
if (ShowWindow > -1) { | |
dwFlags |= 0x00000001 ; STARTF_USESHOWWINDOW | |
NumPut(ShowWindow, si, A_PtrSize == 8 ? 64 : 48, "UShort") | |
} | |
NumPut(dwFlags, si, A_PtrSize == 8 ? 60 : 44, "UInt") | |
} | |
} | |
_PrepareEnvironmentBlockCall() { | |
static lib := "userenv.dll" | |
return _LoadLibrary(lib) | |
} | |
_CreateEnvironmentBlock(ByRef lpEnvironment, hToken, bInherit) { | |
return DllCall("userenv.dll\CreateEnvironmentBlock", "Ptr*", lpEnvironment, "Ptr", hToken, "Int", bInherit) | |
} | |
_DestroyEnvironmentBlock(lpEnvironment) { | |
return DllCall("userenv.dll\DestroyEnvironmentBlock", "Ptr", lpEnvironment) | |
} | |
_EndEnvironmentBlockCall(userenvModule) { | |
return _FreeLibrary(userenvModule) | |
} | |
_GetTokenInformation(TokenHandle, TokenInformationClass, ByRef TokenInformation, TokenInformationLength, ByRef ReturnLength := 0, _tokenInfoType := "Ptr") { | |
static GetTokenInformation := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "GetTokenInformation", "Ptr") | |
return DllCall(GetTokenInformation, "Ptr", TokenHandle, "UInt", TokenInformationClass, _tokenInfoType, TokenInformation, "UInt", TokenInformationLength, "UInt*", ReturnLength) | |
} | |
_SetTokenInformation(TokenHandle, TokenInformationClass, ByRef TokenInformation, TokenInformationLength, _tokenInfoType := "Ptr") { | |
static SetTokenInformation := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "SetTokenInformation", "Ptr") | |
return DllCall(SetTokenInformation, "Ptr", TokenHandle, "UInt", TokenInformationClass, _tokenInfoType, TokenInformation, "UInt", TokenInformationLength) | |
} | |
_CreateWellKnownSid(WellKnownSidType, DomainSid, pSid, ByRef cbSid) { | |
static CreateWellKnownSid := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "CreateWellKnownSid", "Ptr") | |
return DllCall(CreateWellKnownSid, "UInt", WellKnownSidType, "Ptr", DomainSid, "Ptr", pSid, "UInt*", cbSid) | |
} | |
_IsValidSid(pSid) { | |
static IsValidSid := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "IsValidSid", "Ptr") | |
return DllCall(IsValidSid, "Ptr", pSid) | |
} | |
_GetLengthSid(pSid) { | |
static GetLengthSid := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "GetLengthSid", "Ptr") | |
return DllCall(GetLengthSid, "Ptr", pSid, "UInt") | |
} | |
_FindASystemProcessToken(TokenWantedPerms := 0xF, FilterFunc := 0, FilterFuncExtraData := 0, lookInSession := 0) { ; TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_QUERY | TOKEN_IMPERSONATE - the token returned isn't a duplicated one | |
static PROCESS_QUERY_INFORMATION := 0x0400 | |
ret := 0 | |
if (LogonDesktop_AdjustThisProcessPrivileges({"SeDebugPrivilege": True}, PreviousState)) { | |
if (LogonDesktop_WTSEnumerateProcessesEx(WTS,, lookInSession)) { | |
FilterFuncValid := IsObject(FilterFunc) && IsFunc(FilterFunc) | |
for _, proc in WTS { | |
if (_IsSystemSid(proc.GetAddress("UserSID"))) { | |
if ((hProc := DllCall("OpenProcess", "UInt", PROCESS_QUERY_INFORMATION, "Int", False, "UInt", proc.ProcessID, "Ptr"))) { | |
if (LogonDesktop_OpenProcessToken(hProc, TokenWantedPerms, ret), LogonDesktop_CloseHandle(hProc)) { | |
if (!FilterFuncValid || FilterFunc.Call(proc, ret, FilterFuncExtraData)) | |
break | |
} | |
} | |
} | |
} | |
} | |
LogonDesktop_AdjustThisProcessPrivileges(0, PreviousState) | |
} | |
return ret | |
} | |
LogonDesktop_GetCurrentProcessId() { | |
static dwProcessId := DllCall("GetCurrentProcessId", "UInt") ; well, it's not like this one is going to change each time we call it | |
return dwProcessId | |
} | |
LogonDesktop_GetCurrentProcess() { | |
static hProc := DllCall("GetCurrentProcess", "Ptr") ; always -1 | |
return hProc | |
} | |
_LoadLibrary(lpFileName) { | |
static LoadLibraryW := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "kernel32.dll", "Ptr"), "AStr", "LoadLibraryW", "Ptr") | |
return DllCall(LoadLibraryW, "WStr", lpFileName, "Ptr") | |
} | |
_FreeLibrary(hModule) { | |
static FreeLibrary := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "kernel32.dll", "Ptr"), "AStr", "FreeLibrary", "Ptr") | |
return DllCall(FreeLibrary, "Ptr", hModule) | |
} | |
_TOKEN_ALL_ACCESS() | |
{ | |
return (STANDARD_RIGHTS_REQUIRED := 0x000F0000 | TOKEN_ASSIGN_PRIMARY := 0x0001 | TOKEN_DUPLICATE := 0x0002 | TOKEN_IMPERSONATE := 0x0004 | TOKEN_QUERY := 0x0008 | TOKEN_QUERY_SOURCE := 0x0010 | TOKEN_ADJUST_PRIVILEGES := 0x0020 | TOKEN_ADJUST_GROUPS := 0x0040 | TOKEN_ADJUST_DEFAULT := 0x0080 | TOKEN_ADJUST_SESSIONID := 0x0100) | |
} | |
GetParentProcessID() | |
{ | |
; Undocumented, and could break at any time, but far easier than the CreateToolhelp32Snapshot way... | |
VarSetCapacity(PROCESS_BASIC_INFORMATION, pbiSz := A_PtrSize == 8 ? 48 : 24) | |
if (DllCall("ntdll\NtQueryInformationProcess", "Ptr", LogonDesktop_GetCurrentProcess(), "UInt", 0, "Ptr", &PROCESS_BASIC_INFORMATION, "UInt", pbiSz, "Ptr", 0) >= 0) | |
return NumGet(PROCESS_BASIC_INFORMATION, pbiSz - A_PtrSize, "UInt") | |
return 0 | |
} | |
GetParentProcessName() | |
{ | |
if (parentPID := GetParentProcessID()) { | |
if (hProc := DllCall("OpenProcess", "UInt", 0x1000 | 0x0010, "Int", False, "UInt", parentPID, "Ptr")) { ; PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ | |
VarSetCapacity(procName, (260 + 1) * 2) | |
bnOK := !!DllCall("K32GetModuleBaseNameW", "Ptr", hProc, "Ptr", 0, "WStr", procName, "UInt", 260, "UInt") | |
LogonDesktop_CloseHandle(hProc) | |
if (bnOK) | |
return procName | |
} | |
} | |
return "" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment